thei Posted July 17 Posted July 17 (edited) When writing a process module the execute<name> methods output ... either is handled as the part of content embedded in a admin page ... or as output for an appropriate ajax-request (if ajax is detected while processing the incoming request by ProcessWire). When integrating HTMX this leads to an architectural problem: output of HTMX cannot be handled inside the modules process object (which can be seen as "controller") because it is handled as content and will be embedded in an admin page layout. One has to introduce a second route and a has to create a second Controller-Object to handle especially HTMX-responses. put on the wishlist: Processing the execute<name> methods should have something like an option to control processing the output (direct output and appropriate HTTP-headers) - not only ajax. Edited September 9 by thei solved
Jan Romero Posted July 17 Posted July 17 (edited) Idk if I understand the problem, but you can just detect HTMX requests by isset($_SERVER['HTTP_HX_Request']). You could override $config->ajax with it or introduce your own $config->htmx. Edited July 22 by Jan Romero
thei Posted July 17 Author Posted July 17 (edited) Hi, thanks for your response! But: meanwhile i found out... it's not possible ajax handling is processed in admin.php and only there the ProcessController instance is created. This controller has its own method isAjax() and gets the result directly from the http header. But there's no way to hook in here. so one has to modify the admin.php - which i want to avoid. i simply manipulated the $ajax with the debugger and it works except that tracy debugger pollutes the response with its own stuff. Edited July 17 by thei
thei Posted July 21 Author Posted July 21 (edited) The problem could be solved by modifying ProcessController->isAjax()   i.e. in  wire/core/ProcessController.php In case of Htmx as well in case of ajax this method should return true. More flexible: when ProcessController would delegate this to its Process object (and the parent Process class would provide such a method by default) than a module could override the default implementation isAjax().  And ... since this is no longer related to ajax only but decides between   a direct output of content   or embedding the output in a admin page the method should be named to needsDirectOutpput() or similar. context:  $config ->ajax is set in the ProcessWire instance by evaluating the http header HTTP_X_REQUESTED_WITH. It is used by admin.php to control an output buffer (ob_...) inbetween $ajax is overwritten by ProcessController->isAjax(). If true the output returned by the processes execute() is not embbedded in an admin page but output directly. In the current implementation ProcessController->isAjax() checks the http header in the same way like the ProcessWire instance. So this has no added value in the moment. It seems this is some sort of preparation for future plans. e.g. this works: in ProcessController.php (delegation to Process) public function isAjax() { return $this->process->isAjax(); } in Process.php (default implementation) public function isAjax() { return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && ($_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest'); } now this can be overridden by the modules class to enable htmx output Discussion: this is a "quick" solution. May be there is some kind of architectural snag: the decision whether something is to be embedded in an outer frame / page would belong to the view part e.g. in a "viewFile" instead of the modules main object - which acts as a controller in this context. If - alternatively - we want to handle the mode of output controlled purely on a protocol basis we should have something like $input->asynchProtocolType() which should return true in case of ajax, htmx and so on and should be hookable. So this is a question to the ProcessWire Masters here...  🙂 Edited July 21 by thei
Jan Romero Posted July 22 Posted July 22 (edited) I see the problem now. It seems weird that ProcessController::isAjax() even exists, tbh. It may be vestigial and can be replaced by $config->ajax, which you could then override yourself in ready.php. But maybe it’s got some vital purpose. I’d say, open an issue about it on Github. Some other options you can implement right now without hacking the core: Just die() public function ___executeCount() { $count = (int)$this->input->post('count'); die($this->renderCountButton(++$count)); } Instead of returning markup from your execute() method, just terminate the request with your desired output. This will skip things like finished.php, so that’s something to be aware of, but it’s probably fine.  Just add X-Requested-With public function ___execute() { $this->config->scripts->add('https://cdn.jsdelivr.net/npm/htmx.org@2.0.6/dist/htmx.min.js'); return <<<HTML <div hx-headers='{"X-Requested-With": "XMLHttpRequest"}'> <h2>Hello.</h2> {$this->renderCountButton(0)} </div> HTML; } public function ___executeCount() { $count = (int)$this->input->post('count'); return $this->renderCountButton(++$count); } Make HTMX send the X-Requested-With header. Now you're an ajax request according to ProcessWire. The attribute is inherited, so you can just set it once and forget about it, as in the above example.  I have attached a complete module that minimally demonstrates the issue. ProcessHtmxTest.module Edited July 22 by Jan Romero 1
thei Posted July 22 Author Posted July 22 Hi, thank you for your response and your "tricky" smart ideas 🙂 With halting the process / dying i was in doubt if this would lead to some side effects. But injecting an fake HTTP header would be more save - i guess. Â
thei Posted July 23 Author Posted July 23 Quote I’d say, open an issue about it on Github. OK - i opened an issue
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now