mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
BUGFIX Respecting server-overrides on X-Pjax responses during ajax redirects. Fixes GridFieldDetailForm redirect after delete, e.g. in ModelAdmin. Partially reverts 8b4b896
. Closes pull request #488
This commit is contained in:
parent
909c5bd3b1
commit
5b03f49245
@ -351,6 +351,8 @@ class LeftAndMain extends Controller implements PermissionProvider {
|
||||
function redirect($url, $code=302) {
|
||||
if($this->request->isAjax()) {
|
||||
$this->response->addHeader('X-ControllerURL', $url);
|
||||
if($header = $this->request->getHeader('X-Pjax')) $this->response->addHeader('X-Pjax', $header);
|
||||
if($header = $this->request->getHeader('X-Pjax-Selector')) $this->response->addHeader('X-Pjax-Selector', $header);
|
||||
return ''; // Actual response will be re-requested by client
|
||||
} else {
|
||||
parent::redirect($url, $code);
|
||||
|
@ -80,18 +80,14 @@
|
||||
// as automatic browser ajax response redirects seem to discard the hash/fragment.
|
||||
formData.push({name: 'BackURL', value:History.getPageUrl()});
|
||||
|
||||
// Some action buttons are redirecting to content areas as oposed to reloading the form.
|
||||
// They will have pjax-content class on them.
|
||||
var pjaxType = 'CurrentForm', pjaxSelector = '.cms-edit-form';
|
||||
if ($(button).hasClass('pjax-content')) {
|
||||
pjaxType = 'Content';
|
||||
pjaxSelector = '.cms-content';
|
||||
}
|
||||
|
||||
// Standard Pjax behaviour is to replace the submitted form with new content.
|
||||
// The returned view isn't always decided upon when the request
|
||||
// is fired, so the server might decide to change it based on its own logic,
|
||||
// sending back different `X-Pjax` headers and content
|
||||
jQuery.ajax(jQuery.extend({
|
||||
headers: {
|
||||
"X-Pjax" : pjaxType,
|
||||
'X-Pjax-Selector': pjaxSelector
|
||||
"X-Pjax" : "CurrentForm",
|
||||
'X-Pjax-Selector': '.cms-edit-form'
|
||||
},
|
||||
url: form.attr('action'),
|
||||
data: formData,
|
||||
|
@ -36,13 +36,13 @@ jQuery.noConflict();
|
||||
$(document).ajaxComplete(function(e, xhr, settings) {
|
||||
// Simulates a redirect on an ajax response.
|
||||
if(window.History.enabled) {
|
||||
var url = xhr.getResponseHeader('X-ControllerURL');
|
||||
var url = xhr.getResponseHeader('X-ControllerURL'), opts, requestHeaders = settings.headers;
|
||||
// Normalize trailing slashes in URL to work around routing weirdnesses in SS_HTTPRequest.
|
||||
var isSame = (url && History.getPageUrl().replace(/\/+$/, '') == url.replace(/\/+$/, ''));
|
||||
if(url && !isSame) {
|
||||
var opts = {
|
||||
pjax: settings.headers ? settings.headers['X-Pjax'] : null,
|
||||
selector: settings.headers ? settings.headers['X-Pjax-Selector'] : null
|
||||
opts = {
|
||||
pjax: xhr.getResponseHeader('X-Pjax') ? xhr.getResponseHeader('X-Pjax') : settings.headers['X-Pjax'],
|
||||
selector: xhr.getResponseHeader('X-Pjax-Selector') ? xhr.getResponseHeader('X-Pjax-Selector') : settings.headers['X-Pjax-Selector']
|
||||
};
|
||||
window.History.pushState(opts, '', url);
|
||||
}
|
||||
@ -216,11 +216,14 @@ jQuery.noConflict();
|
||||
state: state, element: contentEl
|
||||
});
|
||||
|
||||
// Set Pjax headers, which can declare a preference for the returned view.
|
||||
// The actually returned view isn't always decided upon when the request
|
||||
// is fired, so the server might decide to change it based on its own logic.
|
||||
var headers = {};
|
||||
if(state.data.pjax) {
|
||||
headers['X-Pjax'] = state.data.pjax;
|
||||
} else {
|
||||
// Replace full RHS content area
|
||||
// Standard Pjax behaviour is to replace right content area
|
||||
headers["X-Pjax"] = 'Content';
|
||||
}
|
||||
headers['X-Pjax-Selector'] = selector;
|
||||
|
@ -183,6 +183,9 @@ Within the PHP logic, the `[api:PjaxResponseNegotiator]` class determines which
|
||||
Through a custom `X-Pjax` HTTP header, the client can declare which view he's expecting,
|
||||
through identifiers like `CurrentForm` or `Content` (see `[api:LeftAndMain->getResponseNegotiator()]`).
|
||||
These identifiers are passed to `loadPanel()` via the `pjax` data option.
|
||||
Keep in mind that the returned view isn't always decided upon when the Ajax request
|
||||
is fired, so the server might decide to change it based on its own logic,
|
||||
sending back different `X-Pjax` headers and content.
|
||||
|
||||
## Ajax Redirects
|
||||
|
||||
|
@ -291,9 +291,8 @@ class GridFieldDetailForm_ItemRequest extends RequestHandler {
|
||||
if($this->record->ID !== 0) {
|
||||
$actions->push(FormAction::create('doSave', _t('GridFieldDetailForm.Save', 'Save'))
|
||||
->setUseButtonTag(true)->addExtraClass('ss-ui-action-constructive')->setAttribute('data-icon', 'accept'));
|
||||
// The delete action will redirect, hence pjax-content class.
|
||||
$actions->push(FormAction::create('doDelete', _t('GridFieldDetailForm.Delete', 'Delete'))
|
||||
->addExtraClass('ss-ui-action-destructive')->addExtraClass('pjax-content'));
|
||||
->addExtraClass('ss-ui-action-destructive'));
|
||||
}else{ // adding new record
|
||||
//Change the Save label to 'Create'
|
||||
$actions->push(FormAction::create('doSave', _t('GridFieldDetailForm.Create', 'Create'))
|
||||
@ -405,6 +404,7 @@ class GridFieldDetailForm_ItemRequest extends RequestHandler {
|
||||
//when an item is deleted, redirect to the revelant admin section without the action parameter
|
||||
$controller = Controller::curr();
|
||||
$noActionURL = $controller->removeAction($data['url']);
|
||||
$controller->getRequest()->addHeader('X-Pjax', 'Content'); // Force a content refresh
|
||||
|
||||
return $controller->redirect($noActionURL, 302); //redirect back to admin section
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user