Skip to content

Instantly share code, notes, and snippets.

@jacksleight
Last active August 17, 2022 09:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jacksleight/04fdc8c1f8d827313a68261ac94f34fa to your computer and use it in GitHub Desktop.
Save jacksleight/04fdc8c1f8d827313a68261ac94f34fa to your computer and use it in GitHub Desktop.
`statamic_form()` function for Blade
<?php
use Statamic\Tags\Loader;
use Statamic\View\Antlers\Parser;
if (! function_exists('statamic_form')) {
function statamic_form($handle, $params = [])
{
$form = Form::find($handle);
$html = app(Loader::class)->load('form', [
'parser' => app(Parser::class),
'params' => $params,
'content' => '',
'context' => [],
'tag' => "form:{$handle}",
'tag_method' => $handle,
])->$handle();
preg_match('/^<form (.*?)>(.*?)<\/form>$/is', $html, $match);
return [
'handle' => $handle,
'attrs' => $match[1],
'params' => $match[2],
'errors' => optional(session()->get('errors'))->getBag("form.{$handle}"),
'success' => session("form.{$handle}.success"),
'fields' => $form->fields(),
'honeypot' => $form->honeypot(),
];
}
}
@php
$form = statamic_form('contact', [
'redirect' => url('thank-you'),
]);
@endphp
<div>
@if ($form['success'])
<x-success :message="$form['success']" />
@else
<x-errors :errors="$form['errors']" />
<form {!! $form['attrs'] !!}>
<div class="space-y-4">
@foreach ($form['fields'] as $field)
<label>
{{ $field->display() }}
</label>
@if ($field->type() === 'text')
<input name="{{ $field->handle() }}" type="text">
@elseif ($field->type() === 'select')
<select name="{{ $field->handle() }}">
@foreach ($field->get('options') as $option)
{{-- ... --}}
@endforeach
</select>
@else
{{-- ... --}}
@endif
@endforeach
<button>Send Message</button>
</div>
{!! $form['params'] !!}
<input name="{!! $form['honeypot'] !!}">
</form>
@endif
</div>
@DenyEs
Copy link

DenyEs commented Jun 7, 2022

Hi Jack, is it possible to show me the blade template where you use this? I am trying to build a form from this it seems too difficult which made me think I am doing something wrong and there is an easier way.

@jacksleight
Copy link
Author

Sure, here's a (slightly cut down) example:

@php
$form = statamic_form($handle, [
    'redirect'       => url()->current() . "#form-{$handle}",
    'error_redirect' => url()->current() . "#form-{$handle}",
]);
@endphp
<div>
    @if ($form['success'])
        <x-success>Thank you, your message has been sent successfully.</x-success>
    @else
        <x-errors :errors="$form['errors']" />
        <form {!! $form['attrs'] !!} id="form-{{ $form['handle'] }}">
            <div class="space-y-4">
                @foreach ($form['fields'] as $field)
                    {{-- ... --}}
                @endforeach
                <x-button>Send Message</x-button>
            </div>
            {!! $form['params'] !!}
            <input name="{!! $form['honeypot'] !!}">
        </form>
    @endif
</div>

@DenyEs
Copy link

DenyEs commented Jun 7, 2022

Thank you! I had something similar so I am definitely on a good path, however every time I am trying to access any field attributes within the loop I am getting this error.

Cannot access protected property Statamic\Fields\Field::$config

@foreach ($form['fields'] as $field)
    {{ $field->handle }}
@endforeach

@jacksleight
Copy link
Author

Ah yeah, you need to use the handle and config methods:

{{ $field->handle() }}
{{ $field->config()['type'] }}

@DenyEs
Copy link

DenyEs commented Jun 7, 2022

Ohh, I didnt realize those are methods, it makes sense now. Thank you Jack!

@jacksleight
Copy link
Author

No problem. I've updated the gist with a more complete example of how to use this as well.

@DenyEs
Copy link

DenyEs commented Jun 7, 2022

Awesome! Appreciate the help! :)

@jacksleight
Copy link
Author

jacksleight commented Jun 7, 2022

One thing I missed, you can also use $field->type(), $field->display() and $field->get('key') as a shortcut for $field->config()['key'].

@DenyEs
Copy link

DenyEs commented Jun 7, 2022

That makes it look a lot cleaner in templates, thank you :) This is a great workaround to use forms with Blade and have it fully customisable at the same time.

@markverg
Copy link

Thanks Jack, really helpful!

@jacksleight
Copy link
Author

@markverg You’re welcome!

FYI: As of 3.3.28 you can now get this data from the built-in form tag. 👍

@markverg
Copy link

@markverg You’re welcome!

FYI: As of 3.3.28 you can now get this data from the built-in form tag. 👍

Thanks, we were on 3.3.25 but looking at the commit I did notice it's now in 3.3.28 so will upgrade right away.

One more thing (sorry)..
I noticed after a submit the field values are missing, I try to put back the values in case of errors so the user can just correct the field(s) and re-submit. Is that just me or is that fixed when using the 3.3.28 native way?

@markverg
Copy link

The old values seem to work, so switching to the now native function.
Thanks a lot for all your work!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment