ENH Return PJAX responses from gridfield edit forms (#11206)

undefined
This commit is contained in:
Guy Sartorelli 2024-04-26 17:13:27 +12:00 committed by GitHub
parent 19ea32ebfa
commit 142a318fa8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 62 additions and 1 deletions

View File

@ -678,4 +678,15 @@ class RequestHandler extends ViewableData
$url = Director::absoluteURL((string) $url); $url = Director::absoluteURL((string) $url);
return $this->redirect($url); return $this->redirect($url);
} }
/**
* Convert an array of data to JSON and wrap it in an HTML tag as pjax is used and jQuery will parse this
* as an element on the client side in LeftAndMain.js handleAjaxResponse()
* The attribute type="application/json" denotes this is a data block and won't be processed by a browser
* https://html.spec.whatwg.org/#the-script-element
*/
protected function prepareDataForPjax(array $data): string
{
return '<script type="application/json">' . json_encode($data) . '</script>';
}
} }

View File

@ -7,6 +7,7 @@ use SilverStripe\Admin\LeftAndMain;
use SilverStripe\Control\Controller; use SilverStripe\Control\Controller;
use SilverStripe\Control\HTTPRequest; use SilverStripe\Control\HTTPRequest;
use SilverStripe\Control\HTTPResponse; use SilverStripe\Control\HTTPResponse;
use SilverStripe\Control\PjaxResponseNegotiator;
use SilverStripe\Control\RequestHandler; use SilverStripe\Control\RequestHandler;
use SilverStripe\Core\Convert; use SilverStripe\Core\Convert;
use SilverStripe\Core\ClassInfo; use SilverStripe\Core\ClassInfo;
@ -170,7 +171,7 @@ class GridFieldDetailForm_ItemRequest extends RequestHandler
])->renderWith($this->getTemplates()); ])->renderWith($this->getTemplates());
if ($request->isAjax()) { if ($request->isAjax()) {
return $return; return $this->getResponseNegotiator($return)->respond($request);
} else { } else {
// If not requested by ajax, we need to render it within the controller context+template // If not requested by ajax, we need to render it within the controller context+template
return $controller->customise([ return $controller->customise([
@ -298,6 +299,23 @@ class GridFieldDetailForm_ItemRequest extends RequestHandler
} }
$form->Backlink = $this->getBackLink(); $form->Backlink = $this->getBackLink();
// Ensure the correct validation response is returned for AJAX requests
$form->setValidationResponseCallback(function (ValidationResult $errors) use ($form) {
$request = $this->getRequest();
if (!$request->isAjax()) {
return null;
}
$negotiator = $this->getResponseNegotiator($form->forTemplate());
return $negotiator->respond($request, [
'ValidationResult' => function () use ($errors) {
return $this->prepareDataForPjax([
'isValid' => $errors->isValid(),
'messages' => $errors->getMessages()
]);
}
]);
});
} }
$cb = $this->component->getItemEditFormCallback(); $cb = $this->component->getItemEditFormCallback();
@ -945,4 +963,36 @@ class GridFieldDetailForm_ItemRequest extends RequestHandler
} }
return ClassInfo::shortName($this->record); return ClassInfo::shortName($this->record);
} }
/**
* Get Pjax response negotiator so form submission mirrors other form submission in the CMS.
* See LeftAndMain::getResponseNegotiator()
*/
private function getResponseNegotiator(DBHTMLText $renderedForm): PjaxResponseNegotiator
{
return new PjaxResponseNegotiator([
'default' => function () use ($renderedForm) {
return $renderedForm;
},
'Content' => function () use ($renderedForm) {
return $renderedForm;
},
'CurrentForm' => function () use ($renderedForm) {
return $renderedForm;
},
'Breadcrumbs' => function () {
return $this->renderWith([
'type' => 'Includes',
'SilverStripe\\Admin\\CMSBreadcrumbs'
]);
},
'ValidationResult' => function () {
// Assume valid by default, mirroring LeftAndMain's response negotiator
return $this->prepareDataForPjax([
'isValid' => true,
'messages' => '',
]);
}
], $this->getToplevelController()->getResponse());
}
} }