Jump to content

htmx: Auto-refresh Frontend Content on Backend Page Save


Recommended Posts

The problem: how to refresh a page's frontend content in real time without a page refresh when the page has been edited in the backend.

This is an alternative approach to the one discussed in the topic below.

The above topic attempts to solve the problem using SSE.

The solution in this topic instead relies on Local Storage and htmx. There is no ajax polling. Please note that auto-refresh here refers to a page refresh during the same session and in the same domain. It is not cross-site. The solution can be summarised as follows:

  1. Use a hook in ready.php to inject custom JavaScript to the ProcessWire backend admin, specifically in ProcessPageEdit. This can be a JavaScript file or inline script. The purpose of this file is to update a given Local Storage key after a page has been edited. Instead of listening to the Save Button click, the script just checks on load if a certain hidden input whose value matches the page currently being edited is present. This hidden input is placed inside ProcessPageEdit form using a hook as detailed below. The hook in this step #1 can be: $this->addHookAfter('AdminTheme::getExtraMarkup', null, 'hookAddCustomScriptsToAdmin');
  2. In ready.php, add a hook to listen to saveReady(), e.g. $this->addHookAfter('Pages::saveReady', null, 'hookNotifyFrontendOfBackendPageSave');. When the page is saved, the handler method hookNotifyFrontendOfBackendPageSave will check if there are changed fields. It will then write to a temporary session variable for the current page with the names of the fields that have changed.
  3. On page load/reload, there is a hook in ready.php that monitors ProcessPageEdit, i.e. $this->addHookAfter('ProcessPageEdit::execute', null, 'hookAddMarkupToNotifyFrontendOfBackendPageSave'); The handler hookAddMarkupToNotifyFrontendOfBackendPageSave will check if there is a session variable set in #2 indicating that the page has had recent changes in the fields names set to that session variable. If this is true (that there have been changes), this hook will simply append the hidden input in #1 to the ProcessPageEdit form. The JavaScript in #1 will detect the presence of the hidden input. It will then amend the Local Storage value in #1. It cannot simply set the value to the ID of the page being edited as that will not be construed as a change. It will instead append a timestamp to the id of the page as well and set that as the value. This will enable a listener in the frontend, described in the following steps, to detect that change.
  4. In the frontend, we have a simple JavaScript file that listens to changes to the Local Storage storage Event. The frontend also has a simple hidden input in the template file whose pages we want to refresh. This hidden input has htmx attributes. Its trigger is a custom event 'autorefreshpage'. It will listen for this event before firing a message to the server. This hidden input also has hx-swap=none as nothing will be swapped to it. Instead, the server will send back results of changed fields in various markup with hx-swap-oob=true. That will enable swapping markup in any parts of the frontend html in one go.
  5. When the Script at #4 detects that a given Local Storage value has changed, it first checks if the page ID for that Local Storage value matches the page ID of the page currently being viewed in the frontend. If the answer is yes, it will fire the custom event autorefreshpage. This will make htmx fire a message to the server whose only value is the page ID it has been passed.
  6. On the server, in home.php, we have code that is listening to ajax requests. If it detects an ajax request, it checks if the page ID that htmx sent matches an available session that was recently updated. This would be the temporary session detailed in #2 above. If a match is found, it calls a function in _func.php that will set variables for fields for that page. These use partial templates (optional). These partial templates are for different outputs of the page, e.g. images, headline, etc and all their markup have hx-swap-oob='true' in appropriate places. All these content is sent back as one output back to htmx. It will read the hx-swap-oob and find the markup to replace in the DOM using the html IDs of the markup with the hx-swap-oob. This approach allows the developer to have maximum control over what to send back to htmx and over the markup. In this step, we also delete the temporary session, ready for the next updates.
  7. The result is as demonstrated below. A simple and effective DOM swap that places very little strain on the server. 

I'll clean up the code for this and upload to GitHub. This approach will not work with Save + Exit and similar :-).

  • Like 10
  • Thanks 2
Link to comment
Share on other sites

  • 8 months later...

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 account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Create New...