Reference: Form Actions

Form actions

We saw some example form actions in the simple form example above. Let's detail the actions you can use.

Email

Sends an email with the specified options.

Example:

process:
    - email:
        from: "{{ config.plugins.email.from }}"
        to: "{{ config.plugins.email.to }}"
        subject: "Contact by {{ form.value.name|e }}"
        body: "{% include 'forms/data.html.twig' %}"

Sends an email from the email address specified in the Email plugin configuration, sends it to that same email address (it's a contact form, we send it to ourselves). Unless you want to use other values, you could freely omit from and to, as they are already configured by default to use these values. The email has the set subject and body. In this case, the body is generated by the forms/data.html.twig file, which is found in the active template (Antimatter and the other main themes have it, but it's not guarantee that every theme includes it).

Antimatter sets it to

{% for field in form.fields %}
    <div><strong>{{ field.label }}</strong>: {{ string(form.value(field.name)|e) }}</div>
{% endfor %}

In short, it just loops the values and prints them in the email body.

Dynamic email attribute

If you want for example to set the email.from field from a Form input, you can get its content and use it in this way:

from: "{{ form.value.email }}"

In this case we get the field "email" from the form, and use it for the "from" attribute. This way the site owner will receive an email and will be able to directly reply to the email entered in the form.

Redirect

Redirects the user to another page. The action is immediate, so if you use this, you probably need to put it at the bottom of the actions list.

Message

Sets a message to be shown in the next page. Works if you set a display action too, which redirects the user to another page. Note, you can use Twig in the message if you like.

process:
    - message: Thank you for your feedback!
    - display: thankyou

Display

After submitting the form the user can be redirected to another page. That page will be a subpage of the form, so for example if your form lives in /form, you can redirect users to /form/thankyou with the following code:

process:
    - display: thankyou

The Form plugin provides a formdata template that's suitable for the process destination page, as it outputs the result of the form submission. In the above example, you could create a pages/form/thankyou/formdata.md page.

If you're redirecting to a subpage, display: thankyou works perfect. If you're redirecting to an absolute page path, like site.com/thankyou, prepend it with /, for example: display: /thankyou.

Antimatter and compatible themes provide theformdata.html.twig Twig template, that looks like this:

{% extends 'partials/base.html.twig' %}

{% block content %}

    {{ content }}

    <div class="alert">{{ form.message }}</div>
    <p>Here is the summary of what you wrote to us:</p>

    {% include "forms/data.html.twig" %}

{% endblock %}

If the thankyou/formdata.md page is

---
title: Email sent
cache_enable: false
process:
    twig: true
---

## Email sent!

The output will be a page with the "Email sent!" title, followed by a confirmation message and the form data entered in the previous page.

You could use any page type you want, as a destination page. Just create your own and set the destination page type accordingly.

Save

Saves the form data to a file. The file is saved to the user/data folder, in a subfolder named as the form.name parameter. For example:

The fileprefix and body can contain Twig markup.

process:
    - save:
        fileprefix: feedback-
        dateformat: Ymd-His-u
        extension: txt
        body: "{% include 'forms/data.txt.twig' %}"
        operation: create

The body is taken from the theme's templates/forms/data.html.twig file, provided by Antimatter and updated themes.

the operation can be either create (default) to create a new file per-form-submission or add to append to a single file.

Captcha

To also validate the captcha server-side, add the captcha process action.

    process:
        - captcha:
            recaptcha_secret: ENTER_YOUR_CAPTCHA_SECRET_KEY

The recaptcha_secret is optional, and will use the Form plugin's configuration values if you have provided them there.

User IP Address

Display the user's IP address on the output. Put it above email / save processes in the 'form.md' to ensure it is used by the output processe(s).

process:
    - ip:
        label: User IP Address

Reset the form after submit

By default the form is not cleared after the submit. So if you don't have a display action and the user is sent back to the form page, it's still filled with the data entered. If you want to avoid this, add a reset action:

reset: true

Add your own custom processing to a form

You can "hook" into a form processing and perform any kind of operation. Perform custom processing, add data for an online web application, even save to a database.

To do this, in the form process field add your own processing action name, for example 'yourAction'.

Then, create a simple plugin.

In its main PHP file, register for the event onFormProcessed

namespace Grav\Plugin;
use Grav\Common\Plugin;

class EmailPlugin extends Plugin
{
    public static function getSubscribedEvents()
    {
        return [
            'onFormProcessed' => ['onFormProcessed', 0]
        ];
    }
}

Then provide a handler for the saveToDatabase action:

    public function onFormProcessed(Event $event)
    {
        $form = $event['form'];
        $action = $event['action'];
        $params = $event['params'];

        switch ($action) {
            case 'yourAction':
                //do what you want
        }
    }

If your processing might go wrong and you want to stop the next form actions, which are executed in series, you can stop the processing by calling stopPropagation on the $event object:

$event->stopPropagation();
return;

Sample code with form handling is available in the Form plugin, and in the Email plugin repositories.

An example of custom form handling

The Form plugin offers this ability of sending emails, saving files, setting status messages and it’s really handy. Sometimes however you need total control. That’s for example what the Login plugin does.

It defines the login.md page frontmatter:

title: Login
template: form

form:
    name: login

    fields:
        - name: username
          type: text
          placeholder: Username
          autofocus: true

        - name: password
          type: password
          placeholder: Password

The Forms plugin correctly generates and shows the form. Notice there’s no process defined.

The form buttons are missing too, since they’re manually added in templates/login.html.twig. That’s where the form action and task is defined too.

In this case, task is login.login, and action is set to the page url.

When a user presses 'Login' in the form, Grav calls the onTask.login.login event.

user/plugins/login/login.php hooks up to onTask.login.login to its classes/controller.php file, and that's where the authentication happens.