statamic / v2-hub

Statamic 2 - Feature Requests and Bug Reports
https://statamic.com
95 stars 5 forks source link

form:create won't allow x-on:submit attribute #2522

Open dannyuk1982 opened 4 years ago

dannyuk1982 commented 4 years ago

Using Alpine and submitting a form via AJAX I need to add x-on:submit to a form attribute. Using form:create this is impossible as the : is used to separate attributes.

For example {{ form:create in="enquiry-form" attr="class:relative|x-data:contactForm()|x-on:submit.prevent:submit()" }}

outputs <form method="POST" action="/!/Form/create" class="relative" x-data="contactForm()" x-on="submit.prevent: submit()" ><input type="hidden" name="_token" ...

with x-on="submit.prevent: submit()" instead of x-on:submit.prevent="submit()"

I've made a very simple addon which changes the : to § so then this works: {{ form_alt:create in="enquiry-form" attr="class§relative|x-data§contactForm()|x-on:submit.prevent§submitForm()" }}

Feels very hacky, though, and I can't be the only one with this problem - especially as Alpine gets more popular?

Addon code:


/*
 * uses an alternative separator for the form:create tag,
 * useful for passing e.g. x:on-submit
 * use as {{ form_alt:create in="formset" }}...{{ /form_alt:create }}
 * */

namespace Statamic\Addons\FormAlt;

use Statamic\Addons\Form\FormTags;

class FormAltTags extends FormTags
{
    private $separator = '§';

    protected function formOpen($action)
    {
        $attr_str = $this->getAttributeString();

        if ($this->getBool('files')) {
            $attr_str .= 'enctype="multipart/form-data"';
        }

        $action = str_replace('FormAlt', 'Form', $this->eventUrl($action));

        $html = '<form method="POST" action="'.$action.'" '.$attr_str.'>'.csrf_field();

        return $html;
    }

    protected function getAttributeString()
    {
        $attr_str = '';

        if ($attrs = $this->getList('attr')) {
            foreach ($attrs as $attr) {
                $bits = explode($this->separator, $attr);
                $param = array_shift($bits);

                $attr_str .= $param . '="' . implode($this->separator.' ', $bits) . '" ';
            }
        }

        return $attr_str;
    }
}