MarkE Posted March 16, 2022 Share Posted March 16, 2022 ... I hope! I can get htmx working fine in the front end but I would like to use it in the back-end also. In particular, I want to incorporate it into my FieldtypeMeasurement module. I am loading it using wire()->config->scripts->append("https://unpkg.com/htmx.org@1.7.0"); in the init() and the Chrome dev tools show that it is loaded OK. I have then added the 'hx-...' attributes in the inputfields and again the dev tools show that they are present. But no 'hx-...' triggers work. I'm probably just being a bit dim, but does anyone have any suggestions? Link to comment Share on other sites More sharing options...
kongondo Posted March 17, 2022 Share Posted March 17, 2022 11 hours ago, MarkE said: But no 'hx-...' triggers work. By this you mean there are no htmx JS errors in the console but htmx does not send an ajax request? 11 hours ago, MarkE said: I have then added the 'hx-...' attributes in the inputfields Maybe show as an example + the types of inputfields (just in case). Link to comment Share on other sites More sharing options...
MarkE Posted March 17, 2022 Author Share Posted March 17, 2022 Thanks @kongondo. 31 minutes ago, kongondo said: By this you mean there are no htmx JS errors in the console but htmx does not send an ajax request? Exactly, yes. Also I can see nothing happening in the 'Network' monitor in the dev tools. 32 minutes ago, kongondo said: Maybe show as an example + the types of inputfields (just in case). This, in my InputfieldMeasurement::render() $f = $this->modules->get("InputfieldSelect"); $f->label = $this->_("Unit"); $f->attr('name', "{$name}_unit"); $f->attr('value', $value->get('unit')); ...... ...... $moduleName = basename(__DIR__); $f->attr('hx-get', $this->config->paths->$moduleName . 'test.php'); $f->attr('hx-target', ".InputfieldMeasurement_magnitude" ); $f->attr('hx-swap', 'outerHtml'); $f->attr('hx-trigger', 'change'); $f->attr('hx-confirm', 'Do you want to convert the magnitude?'); $inputfields->add($f); Nothing gets triggered, but the dev tools show that the attributes are there. The htmx script is added in init() as per my OP. I can see in the dev tools that it is loaded (and the html source shows the relevant <script> tag). I used the exact same script in the front end and it works fine. Link to comment Share on other sites More sharing options...
kongondo Posted March 17, 2022 Share Posted March 17, 2022 (edited) 33 minutes ago, MarkE said: $f->attr('hx-get', $this->config->paths->$moduleName . 'test.php'); This will never work. It should be a URL not a path ?. Either way, ProcessWire will block access to test.php. You have various options for this in the backend, e.g. point it to ProcessModule or a virtual URL that you handle using url hooks or to an Inputfield as shown below: <?php namespace ProcessWire; $adminEditURL = $this->wire('config')->urls->admin . "page/edit/"; $adminEdit = "{$adminEditURL}?id={$this->page->id}&field={$name}"; $out = "<a href='#' hx-get='{$adminEdit}'>"; Which will produce something like this: hx-get="/processwire/page/edit/?id=1234&field=name_of_inputfield" Edited March 17, 2022 by kongondo Example code 2 Link to comment Share on other sites More sharing options...
kongondo Posted March 17, 2022 Share Posted March 17, 2022 (edited) 38 minutes ago, MarkE said: $f->attr('hx-target', ".InputfieldMeasurement_magnitude" ); This might work (am not sure) but did you want to be more specific by using an ID? You probably know this already but wanted to point out that you can pass all those attrs in one go like this: <?php namespace ProcessWire; $field->attr([ 'hx-post' => $ajaxURL, 'hx-swap' => 'beforebegin', // etc... ]); Edited March 17, 2022 by kongondo Examples 2 Link to comment Share on other sites More sharing options...
MarkE Posted March 17, 2022 Author Share Posted March 17, 2022 (edited) Thanks for your helpful suggestions @kongondo. However, my problem is that the hx-... attributes do not seem to be recognised at all - whether or not I have constructed them correctly. I used your example: 15 hours ago, kongondo said: <?php namespace ProcessWire; $adminEditURL = $this->wire('config')->urls->admin . "page/edit/"; $adminEdit = "{$adminEditURL}?id={$this->page->id}&field={$name}"; $out = "<a href='#' hx-get='{$adminEdit}'>"; modified as follows: $adminEditURL = $this->wire('config')->urls->admin . "page/edit/"; $adminEdit = "{$adminEditURL}?id={$this->page->id}&field={$name}"; $button = "<a href='#' hx-get='{$adminEdit}' hx-trigger='click' hx-swap='outerHTML' hx-confirm='OK'>Click Me!</a>"; but still nothing happens (except that the href takes the browser to the top of the page) - the chrome dev tools show all the attributes present but no network activity. Your comment 15 hours ago, kongondo said: This will never work. It should be a URL not a path ?. Either way, ProcessWire will block access to test.php. is spot on. If I do it in the front end, then the network monitor shows a 403 error which is what you would expect. However, in the back-end there is no network activity and therefore no error. At this stage, I am just trying to get htmx to fire - once I do then your suggestions will be very useful ? I short, the problem seems to be that the htmx script is not active, so I am wondering if it is something to do with the sequence in which scripts are being loaded. As an example, the complete set of loaded scripts in the <head> per the html source is (excluding pw config) <script type="text/javascript" src="/wire/modules/Jquery/JqueryCore/jquery.cookie.js?v=1638562531"></script> <script type="text/javascript" src="/wire/modules/Jquery/JqueryWireTabs/JqueryWireTabs.js?v=1638562531"></script> <script type="text/javascript" src="/wire/modules/Jquery/JqueryUI/JqueryUI.js?v=1638562531"></script> <script type="text/javascript" src="/wire/modules/Jquery/JqueryUI/panel.js?v=1638562531"></script> <script type="text/javascript" src="/wire/modules/Jquery/JqueryUI/selectize/js/standalone/selectize.js"></script> <script type="text/javascript" src="/site/modules/SelectizeAll/SelectizeCustomChange.js?v=0.1.1"></script> <script type="text/javascript" src="/site/modules/SelectizeAll/SelectizeAll.js?v=0.1.1"></script> <script type="text/javascript" src="/site/templates/scripts/admin.js?v=2"></script> <script type="text/javascript" src="/site/modules/PageAutosave/PageAutosave.js?v=6"></script> <script type="text/javascript" src="/wire/modules/Process/ProcessPageEdit/ProcessPageEdit.js?v=111-1638562531"></script> <script type="text/javascript" src="/wire/modules/Jquery/JqueryUI/modal.js?v=1641685970"></script> <script type="text/javascript" src="https://unpkg.com/htmx.org@1.7.0"></script> <script type="text/javascript" src="/wire/modules/Jquery/JqueryTableSorter/JqueryTableSorter.js?v=1638562531"></script> <script type="text/javascript" src="/wire/modules/Markup/MarkupAdminDataTable/MarkupAdminDataTable.js?v=1638562531"></script> <script type="text/javascript" src="/wire/modules/Inputfield/InputfieldDatetime/InputfieldDatetime.js?v=107-1638562531"></script> <script type="text/javascript" src="/wire/modules/Jquery/JqueryUI/vex/scripts/vex.combined.min.js"></script> <script type="text/javascript" src="/wire/modules/Fieldtype/FieldtypeRepeater/InputfieldRepeater.js?v=111-1638562531"></script> <script type="text/javascript" src="/site/modules/FieldtypeRepeaterMatrix/InputfieldRepeaterMatrix.js?v=8-1640343319"></script> <script type="text/javascript" src="/wire/modules/Inputfield/InputfieldPageTitle/InputfieldPageTitle.js?v=102-1638562531"></script> <script type="text/javascript" src="/wire/modules/Inputfield/InputfieldPage/InputfieldPage.js?v=107-1638562531"></script> <script type="text/javascript" src="/wire/modules/Inputfield/InputfieldPageName/InputfieldPageName.js?v=106-1638562531"></script> <script type="text/javascript" src="/wire/modules/Process/ProcessPageList/ProcessPageList.js?v=123-1638562531"></script> <script type="text/javascript" src="/wire/modules/Jquery/JqueryCore/jquery.longclick.min.js?v=1638562531"></script> <script type="text/javascript" src="/wire/modules/Inputfield/InputfieldPageListSelect/InputfieldPageListSelect.js?v=101-1638562531"></script> <script type="text/javascript" src="/wire/modules/Inputfield/InputfieldCheckboxes/InputfieldCheckboxes.js?v=108-1638562531"></script> <script type="text/javascript" src="/wire/modules/Inputfield/InputfieldAsmSelect/asmselect/jquery.asmselect.js?v=202"></script> <script type="text/javascript" src="/wire/modules/Inputfield/InputfieldAsmSelect/InputfieldAsmSelect.js?v=202-1638562531"></script> <script type="text/javascript" src="/wire/modules/Inputfield/InputfieldSubmit/dropdown.js"></script> <script type="text/javascript" src="/wire/templates-admin/scripts/inputfields.js?v=33g"></script> <script type="text/javascript" src="/wire/templates-admin/scripts/main.js?v=33g"></script> <script type="text/javascript" src="/wire/modules/AdminTheme/AdminThemeUikit/uikit/dist/js/uikit.min.js?v=33g"></script> <script type="text/javascript" src="/wire/modules/AdminTheme/AdminThemeUikit/uikit/dist/js/uikit-icons.min.js?v=33g"></script> <script type="text/javascript" src="/wire/modules/AdminTheme/AdminThemeUikit/scripts/main.js?v=33g"></script><script>vex.defaultOptions.className='vex-theme-default';vex.dialog.buttons.YES.text='Ok';vex.dialog.buttons.NO.text='Cancel';</script> So we can see that htmx.org is loaded (and it is shown as a source in the dev tools also). Any observations or suggestions for further debugging actions? EDIT: I tested whether the htmx global variable is available, to which the answer is 'yes' in the front end, but 'no' in the back-end, underlining that it seems to be a problem with loading.... Edited March 17, 2022 by MarkE further info Link to comment Share on other sites More sharing options...
MarkE Posted March 18, 2022 Author Share Posted March 18, 2022 14 hours ago, MarkE said: EDIT: I tested whether the htmx global variable is available, to which the answer is 'yes' in the front end, but 'no' in the back-end, underlining that it seems to be a problem with loading.... Moving on.. I managed to get htmx loading. I can now get @kongondo's simple <a> example working (modified to be a <button> as per my previous post). But I can't get InputfieldSelect fields to fire with hx-trigger="change" although they will fire with hx-trigger="mouseover" (or 'focus', 'mouseout' etc., but not 'change' or 'click'). Of course, 'change' is what I want. Nothing works inside a repeater. Link to comment Share on other sites More sharing options...
kongondo Posted March 18, 2022 Share Posted March 18, 2022 @MarkE It is working for me, in your module. I haven't tested in repeaters. I'll add the relevant code in a later post. Meanwhile, attached, the demo of it working. htmx_inputfield_measurement_22-03-18_16-26-08.mp4 Link to comment Share on other sites More sharing options...
kongondo Posted March 18, 2022 Share Posted March 18, 2022 Code for the above demo JavaScript Here we need to tell htmx that ProcessWire expects Ajax calls to send "X-Requested-With" // InputfieldMeasurement.js const InputfieldMeasurement = { initHTMXXRequestedWithXMLHttpRequest: function () { console.log("initHTMXXRequestedWithXMLHttpRequest - configRequest") document.body.addEventListener("htmx:configRequest", (event) => { event.detail.headers["X-Requested-With"] = "XMLHttpRequest" }) }, listenToHTMXRequests: function () { // before send - Just an example to show you where to hook BEFORE SEND htmx request htmx.on("htmx:beforeSend", function (event) { console.log("InputfieldMeasurement - listenToHTMXRequests - event", event) }) }, } /** * DOM ready * */ document.addEventListener("DOMContentLoaded", function (event) { if (typeof htmx !== "undefined") { // CHECK THAT htmx is available console.log("HTMX!") // init htmx with X-Requested-With InputfieldMeasurement.initHTMXXRequestedWithXMLHttpRequest() // just for testing InputfieldMeasurement.listenToHTMXRequests() } else { console.log("NO HTMX!") } }) PHP We are in InputfieldMeasurement.module We load htmx in init() We listen to htmx calls in render() We pass this to a handler testHTMX() Insider render() we listen to change on InputfieldSelect. Notice we don't add a trigger. htmx knows the type of event that a Select outputs <?php namespace ProcessWire; // BELOW, SNIPPETS OF THE RELEVANT CODE public function init() { parent::init(); // wire()->config->scripts->append("https://unpkg.com/htmx.org@1.7.0"); // LOAD htmx // I just prefer this syntax :-) $this->wire('config')->scripts->append("https://unpkg.com/htmx.org@1.7.0"); } public function ___render() { $name = $this->attr('name'); $field = $this->field; $page = $this->page; $value = $this->attr('value'); if (!$value || !$value->quantity) { $value = new Measurement($field->quantity); //bd($value, 'value'); } ##################### HTMX AJAX LISTENER $input = $this->wire('input'); $ajax = $this->wire('config')->ajax; // bd($ajax, __METHOD__ . ': $ajax at line #' . __LINE__); // bd($input->get('field'), __METHOD__ . ': $input->get(field) at line #' . __LINE__); if ($ajax && $input->get('field') == $this->attr('name')) { bd($ajax, __METHOD__ . ': $ajax at line #' . __LINE__); bd($input->get('field'), __METHOD__ . ': $input->get(field) at line #' . __LINE__); bd($input->get('id'), __METHOD__ . ': $input->get(id) at line #' . __LINE__); $out = $this->testHTMX(); echo $out; die(); } else { // @debug bd($ajax, __METHOD__ . ': $ajax - NO AJAX AND/OR WRONG INPUTFIELD - at line #' . __LINE__); } // >>>> MORE CODE HERE ... // ADD HTMX LISTENER TO 'measurement input Select' // unit $f = $this->modules->get("InputfieldSelect"); $f->label = $this->_("Unit"); $f->attr('name', "{$name}_unit"); $f->attr('value', $value->get('unit')); //bd($value, 'value'); bd($field->units, __METHOD__ . ': $field->units at line #' . __LINE__); foreach ($field->units as $unit) { $shortLabel = (isset($units[$unit]) && isset($units[$unit]['shortLabel'])) ? $units[$unit]['shortLabel'] : null; $alias = (isset($units[$unit]) && isset($units[$unit]['alias'])) ? $units[$unit]['alias'] : $unit; if ($shortLabel) $shortLabel = "($shortLabel)"; $f->addOption($unit, "$alias $shortLabel"); } $f->notes = $units[$value->get('unit')]->notes; $f->columnWidth = $colWidth; // ======== #### add HTMX #### $adminEditURL = $this->wire('config')->urls->admin . "page/edit/"; $adminEdit = "{$adminEditURL}?id={$this->page->id}&field={$name}"; bd($adminEditURL, __METHOD__ . ': $adminEditURL at line #' . __LINE__); bd($adminEdit, __METHOD__ . ': $adminEdit at line #' . __LINE__); // ------ $f->attr([ 'hx-get' => $adminEdit, // send get to to InputfieldMeasurement 'hx-target' => '#InputfieldMeasurementTestHTMXTarget', // our element to target with swap 'hx-swap' => 'innerHTML' // we'll swap the innerHTML (this is the default but it has never worked for me if not specified) ]); $inputfields->add($f); // ========= ### FOR HTMX DEMO ONLY ### $f = $this->modules->get("InputfieldMarkup"); $f->label = "InputfieldMeasurement Test HTMX"; $f->attr('id', "InputfieldMeasurementTestHTMX"); // we will swap the innerHTML of the div#InputfieldMeasurementTextHTMXTarget $out = "<div id='InputfieldMeasurementTestHTMXTarget'><h3>HTMX TARGET (will change when Unit changes)</h3></div>"; // $f->collapsed = Inputfield::collapsedYes; $f->value = $out; $f->columnWidth = 100; $inputfields->add($f); // >>>> MORE CODE ..... return $inputfields->render(); } private function testHTMX() { $dateAndTime = date("Y-F-d H:i:s"); $out = "<h3>We got that HTMX Call at {$dateAndTime}!</h3>"; return $out; } 1 Link to comment Share on other sites More sharing options...
MarkE Posted March 18, 2022 Author Share Posted March 18, 2022 Thanks @kongondo. That's enormously helpful. I'll go through it in detail in my usual late-night coding session. My idea is to replace the present, rather clunky, method of doing conversion (checking a box then saving) with a prompt when the user changes units saying "Do you want to convert the measurement" (but which can be turned off in the config). I could, of course, have done this with straight Ajax, but was keen to try htmx as it looks like a really neat approach. BTW the current version of the module on Github still has some bugs. I have a much-debugged version that I have been using extensively and am really pleased with, but planned to incorporate this change before releasing it. Link to comment Share on other sites More sharing options...
MarkE Posted March 18, 2022 Author Share Posted March 18, 2022 Hmm. That's really odd. I implemented your code as described @kongondo, but the effect was as before. 9 hours ago, MarkE said: I can't get InputfieldSelect fields to fire with hx-trigger="change" although they will fire with hx-trigger="mouseover" (or 'focus', 'mouseout' etc., but not 'change' or 'click'). Of course, 'change' is what I want. Nothing works inside a repeater. With hx-trigger="mouseover", all your tracy and console logging displays as expected. But with no hx-trigger or hx-trigger="change" there is no network activity and nothing is logged. Obviously there is something different between our setups. I am on a later version of the Measurement module (which I doubt is the reason) and on PW3.0.190. I therefore tried it in a site on PW3.0.184 and the exact same Measurement module and the change trigger works (although I haven't tested in a repeater yet). So, either it is something in 3.0.190 or something else in the setup of the site I am using it on. Which version of PW are you using? EDIT: It works inside a repeater on PW3.0.184 (haven't tried a repeater matrix), although only for the first such repeater item, which is not a surprise as there is a multiple element id issue with the demo code in a repeater (it fires on all repeater items, just doesn't update the demo target). Link to comment Share on other sites More sharing options...
kongondo Posted March 18, 2022 Share Posted March 18, 2022 13 minutes ago, MarkE said: Which version of PW are you using? That was a different machine from this one but I think it was 3.0.184. Hmm.. Link to comment Share on other sites More sharing options...
MarkE Posted March 19, 2022 Author Share Posted March 19, 2022 Could be something to do with auto save / live preview, but I haven't got auto save turned on for the page in question. EDIT .. but disabling the auto-save module does not fix it Link to comment Share on other sites More sharing options...
kongondo Posted March 19, 2022 Share Posted March 19, 2022 What baffles me is that there is no error and no network activity. I expected at least one of these. Are you able to strip that page bare and leave only title and measurement fields then test? Link to comment Share on other sites More sharing options...
MarkE Posted March 19, 2022 Author Share Posted March 19, 2022 9 hours ago, kongondo said: What baffles me is that there is no error and no network activity Me too! Slightly curiously, when I tried it this morning, there was network activity, but just a whole load of GETs for data:image/svg+xml from pw.min.css - which appears to be the chevrons in the dropdown box. But no ajax activity and no errors. The console shows that HTMX is loaded OK. Mouseover (outside repeater) works. I disabled all hooks, but still no luck! Link to comment Share on other sites More sharing options...
MarkE Posted March 19, 2022 Author Share Posted March 19, 2022 10 hours ago, kongondo said: Are you able to strip that page bare and leave only title and measurement fields then test? I created a bare page with just title and measurement fields and the effect was exactly the same (except in this case, no GETs for data:image/svg+xml) - i.e. working with 'mouseover' and no errors or network activity with 'change' Link to comment Share on other sites More sharing options...
kongondo Posted March 19, 2022 Share Posted March 19, 2022 (edited) 11 hours ago, MarkE said: Which version of PW are you using? I've just checked and actually the version I tested on is 3.0.190. So, there must be something else going on in your install, unless we have different 3.0.190s. Maybe send me a copy of your latest measurement module so I can test on my 3.0.190. I don't have live preview though. Edited March 19, 2022 by kongondo Link to comment Share on other sites More sharing options...
MarkE Posted March 19, 2022 Author Share Posted March 19, 2022 1 hour ago, kongondo said: Maybe send me a copy of your latest measurement module so I can test on my 3.0.190 I can do, but I don't think that is the issue as I installed the latest version of the module on my 3.0.184 site and htmx worked OK. So it must be another module or something else in my site that is causing the problem. As I mentioned earlier, htmx is working OK in the front-end. Plus I tested without all the hooks in ready.php (i.e. site-specific hooks) and that didn't fix anything. I also tried it with auto-save uninstalled without any luck. Aha - I think I've found it (at least partly). I disabled the SelectizeAll module by @Robin S. Now the change trigger works, although not inside a repeater matrix item (it did work inside a repeater [not repeater matrix] item on the 3.0.184 site, so I will try a dummy repeater on this site too). I really like SelectizeAll, so it would be great to get it working without interfering with htmx. EDIT: I have posted an item over on the SelectizeAll support thread. Link to comment Share on other sites More sharing options...
kongondo Posted March 19, 2022 Share Posted March 19, 2022 (edited) 1 hour ago, MarkE said: I can do, but I don't think that is the issue as I installed the latest version of the module on my 3.0.184 site and htmx worked OK. Yeah, you are right. 1 hour ago, MarkE said: Aha - I think I've found it (at least partly). I disabled the SelectizeAll module Good catch. This is why I suggested to strip the page bare - to rule out things one by one. Does this mean SelectizeAll module autoloads? Edit: I've checked. Yes, it autoloads. Edited March 19, 2022 by kongondo Link to comment Share on other sites More sharing options...
MarkE Posted March 19, 2022 Author Share Posted March 19, 2022 I tested htmx on a measurement field in a repeater and it worked OK. I then changed the repeater to a repeater matrix and it failed. So it looks like there is some js in RepeaterMatrix that is hijacking the event. Unfortunately the app which is acting as a test bed for the Measurement module relies heavily on repeater matrix fields ? Link to comment Share on other sites More sharing options...
kongondo Posted March 19, 2022 Share Posted March 19, 2022 19 minutes ago, MarkE said: So it looks like there is some js in RepeaterMatrix that is hijacking the event. Just to confirm, this is apart from the SelectizeAll issue? Either way, htmx is so versatile. You can trigger hx-trigger using an Event. If you are able to listen to change on the RepeaterMatrix field, you can either use that event or fire a custom event to trigger your htmx hx-trigger. Can't elaborate further unless I see your implementation. Link to comment Share on other sites More sharing options...
MarkE Posted March 19, 2022 Author Share Posted March 19, 2022 1 minute ago, kongondo said: Just to confirm, this is apart from the SelectizeAll issue? Correct 2 minutes ago, kongondo said: If you are able to listen to change on the RepeaterMatrix field, you can either use that event or fire a custom event to trigger your htmx hx-trigger. Can't elaborate further unless I see your implementation. Ta. I'll look at it again this evening and post more info then if I can't fix it. Link to comment Share on other sites More sharing options...
kongondo Posted March 19, 2022 Share Posted March 19, 2022 3 minutes ago, MarkE said: Ta. I'll look at it again this evening and post more info then if I can't fix it. Another thing that could be happening is that your repeater matrix are being lazy loaded via Ajax. In this case, htmx 'will not see them' unless you re-trigger the hx-attributes. Link to comment Share on other sites More sharing options...
MarkE Posted March 19, 2022 Author Share Posted March 19, 2022 32 minutes ago, kongondo said: your repeater matrix are being lazy loaded via Ajax That looks like the case. How do you suggest re-triggering the hx- attributes? Link to comment Share on other sites More sharing options...
kongondo Posted March 19, 2022 Share Posted March 19, 2022 (edited) 1 hour ago, MarkE said: How do you suggest re-triggering the hx- attributes? Easiest is probably if you know the events repeater matrix is triggering. Have a look at this section in the htmx docs. https://htmx.org/docs/#3rd-party Edited March 19, 2022 by kongondo typos Link to comment Share on other sites More sharing options...
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