Workaround: custom attributes on Perch form tags

As of v3.1.5, Perch form tags only render data-*, aria-* and HTML attributes. This makes using Perch-templated forms with JS frameworks that use custom attributes (e.g. Vue.js and Alpine.js) harder.

So when you add a custom attribute like Alpine’s x-data directive, Perch removes it from the rendered HTML tags. So this:

<perch:form id="some_form" app="some_app" method="post" action="/contact" x-data="{}"></perch:form>

becomes:

<form method="post" action="/contact"></form>

It is rare for Perch to assume control like this, so hopefully this will be addressed in later versions. For now you can workaround this by prefixing your custom attributes by data-*- making a data attribute which won’t get removed. I tend to use data-persist-. So this:

<perch:form id="some_form" app="some_app" method="post" action="/contact" data-persist-x-data="{}"></perch:form>

renders as:

<form method="post" action="/contact" data-persist-x-data="{}"></form>

And instead of immediately outputting the rendered template to the page, we can have it returned so we can do some string replacement. How you return it depends on what runtime function is rendering the form. If you are using perch_form() from the Perch Forms app:

$form_html = perch_form('some_form', true);

If you are rendering the form with perch_collection():

$form_html = perch_collection('Products', ['template' => 'products/enquire'], true);

There are more ways to render forms, but I won’t go through them all.

Now that $form_html holds the rendered form, we can remove data-persist-. The easiest way is to do a simple string replacement:

$form_html = perch_form('some_form', true);
$form_html = str_replace('data-persist-', '', $form_html);
echo $form_html;

Vue.js and Alpine.js make use of certain characters in their attributes like @, : and .. Given that these attributes are not typically used in HTML, Perch template engine doesn’t handle them well. To workaround this, you can replace them with something else in the template and then do more string replacement in PHP. Your attributes may end up very long like:

data-persist-x-on-submit-dot-prevent

I tend to use something like this for Vue and Alpine:

$form_html = perch_form('some_form', true);
$form_html = str_replace('data-persist-x-on-', '@', $form_html);
$form_html = str_replace('data-persist-x-bind-', ':', $form_html);
$form_html = str_replace('-dot-', '.', $form_html);
$form_html = str_replace('data-persist-', '', $form_html);
echo $form_html;
link

Related articles