mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-09-27 20:06:52 +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) {
|
function redirect($url, $code=302) {
|
||||||
if($this->request->isAjax()) {
|
if($this->request->isAjax()) {
|
||||||
$this->response->addHeader('X-ControllerURL', $url);
|
$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
|
return ''; // Actual response will be re-requested by client
|
||||||
} else {
|
} else {
|
||||||
parent::redirect($url, $code);
|
parent::redirect($url, $code);
|
||||||
|
@ -80,18 +80,14 @@
|
|||||||
// as automatic browser ajax response redirects seem to discard the hash/fragment.
|
// as automatic browser ajax response redirects seem to discard the hash/fragment.
|
||||||
formData.push({name: 'BackURL', value:History.getPageUrl()});
|
formData.push({name: 'BackURL', value:History.getPageUrl()});
|
||||||
|
|
||||||
// Some action buttons are redirecting to content areas as oposed to reloading the form.
|
// Standard Pjax behaviour is to replace the submitted form with new content.
|
||||||
// They will have pjax-content class on them.
|
// The returned view isn't always decided upon when the request
|
||||||
var pjaxType = 'CurrentForm', pjaxSelector = '.cms-edit-form';
|
// is fired, so the server might decide to change it based on its own logic,
|
||||||
if ($(button).hasClass('pjax-content')) {
|
// sending back different `X-Pjax` headers and content
|
||||||
pjaxType = 'Content';
|
|
||||||
pjaxSelector = '.cms-content';
|
|
||||||
}
|
|
||||||
|
|
||||||
jQuery.ajax(jQuery.extend({
|
jQuery.ajax(jQuery.extend({
|
||||||
headers: {
|
headers: {
|
||||||
"X-Pjax" : pjaxType,
|
"X-Pjax" : "CurrentForm",
|
||||||
'X-Pjax-Selector': pjaxSelector
|
'X-Pjax-Selector': '.cms-edit-form'
|
||||||
},
|
},
|
||||||
url: form.attr('action'),
|
url: form.attr('action'),
|
||||||
data: formData,
|
data: formData,
|
||||||
|
@ -36,13 +36,13 @@ jQuery.noConflict();
|
|||||||
$(document).ajaxComplete(function(e, xhr, settings) {
|
$(document).ajaxComplete(function(e, xhr, settings) {
|
||||||
// Simulates a redirect on an ajax response.
|
// Simulates a redirect on an ajax response.
|
||||||
if(window.History.enabled) {
|
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.
|
// Normalize trailing slashes in URL to work around routing weirdnesses in SS_HTTPRequest.
|
||||||
var isSame = (url && History.getPageUrl().replace(/\/+$/, '') == url.replace(/\/+$/, ''));
|
var isSame = (url && History.getPageUrl().replace(/\/+$/, '') == url.replace(/\/+$/, ''));
|
||||||
if(url && !isSame) {
|
if(url && !isSame) {
|
||||||
var opts = {
|
opts = {
|
||||||
pjax: settings.headers ? settings.headers['X-Pjax'] : null,
|
pjax: xhr.getResponseHeader('X-Pjax') ? xhr.getResponseHeader('X-Pjax') : settings.headers['X-Pjax'],
|
||||||
selector: settings.headers ? settings.headers['X-Pjax-Selector'] : null
|
selector: xhr.getResponseHeader('X-Pjax-Selector') ? xhr.getResponseHeader('X-Pjax-Selector') : settings.headers['X-Pjax-Selector']
|
||||||
};
|
};
|
||||||
window.History.pushState(opts, '', url);
|
window.History.pushState(opts, '', url);
|
||||||
}
|
}
|
||||||
@ -216,11 +216,14 @@ jQuery.noConflict();
|
|||||||
state: state, element: contentEl
|
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 = {};
|
var headers = {};
|
||||||
if(state.data.pjax) {
|
if(state.data.pjax) {
|
||||||
headers['X-Pjax'] = state.data.pjax;
|
headers['X-Pjax'] = state.data.pjax;
|
||||||
} else {
|
} else {
|
||||||
// Replace full RHS content area
|
// Standard Pjax behaviour is to replace right content area
|
||||||
headers["X-Pjax"] = 'Content';
|
headers["X-Pjax"] = 'Content';
|
||||||
}
|
}
|
||||||
headers['X-Pjax-Selector'] = selector;
|
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 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()]`).
|
through identifiers like `CurrentForm` or `Content` (see `[api:LeftAndMain->getResponseNegotiator()]`).
|
||||||
These identifiers are passed to `loadPanel()` via the `pjax` data option.
|
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
|
## Ajax Redirects
|
||||||
|
|
||||||
|
@ -291,9 +291,8 @@ class GridFieldDetailForm_ItemRequest extends RequestHandler {
|
|||||||
if($this->record->ID !== 0) {
|
if($this->record->ID !== 0) {
|
||||||
$actions->push(FormAction::create('doSave', _t('GridFieldDetailForm.Save', 'Save'))
|
$actions->push(FormAction::create('doSave', _t('GridFieldDetailForm.Save', 'Save'))
|
||||||
->setUseButtonTag(true)->addExtraClass('ss-ui-action-constructive')->setAttribute('data-icon', 'accept'));
|
->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'))
|
$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
|
}else{ // adding new record
|
||||||
//Change the Save label to 'Create'
|
//Change the Save label to 'Create'
|
||||||
$actions->push(FormAction::create('doSave', _t('GridFieldDetailForm.Create', '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
|
//when an item is deleted, redirect to the revelant admin section without the action parameter
|
||||||
$controller = Controller::curr();
|
$controller = Controller::curr();
|
||||||
$noActionURL = $controller->removeAction($data['url']);
|
$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
|
return $controller->redirect($noActionURL, 302); //redirect back to admin section
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user