Input Sources

In nearly all uses cases the input data in Mayd forms is coming from user input. After all, that’s the main purpose of Mayd forms. However, in certain kinds of cases it would be great to either prefill a form field or by setting its value to a specific value.

Both of these use cases are covered by input sources.

Implementing an Input Source

This examples covers a registration form. Every field in the registration form should be input by the user, except for the email address. The start of the registration is not just a link, but instead an email form, where we validate the email address by letting the user click a link in an email.

This way we can be sure that this email address is valid. Afterwards we want to let the user fill in the remaining fields of the form. The whole form is a regular Mayd form.

So first we need to build our integration:

use Mayd\Forms\Entity\Field\FormInput;
use Mayd\Forms\Input\Config\EmailInputConfig;
use Mayd\Forms\Input\Sources\InputSource;
use Mayd\Foundation\Request\Context\WebsiteRequestContextInterface;

class AdditionalDataEmailInputSource extends InputSource
{
    /**
     * @inheritDoc
     */
    public function supports (FormInput $input) : bool
    {
        return $input->getConfig() instanceof EmailInputConfig;
    }


    /**
     * @inheritDoc
     */
    public function getValue (
        WebsiteRequestContextInterface $context,
        FormInput $input,
        array $additionalData,
        $previousValue
    )
    {
        $email = $additionalData["email"] ?? null;

        return \is_string($email)
            ? $email
            : $previousValue;
    }
}

That is the complete code.

First, we tell the integration in supports() that we only apply to email fields.

In the actual implementation in getValue() we fetch the value (if we find one), otherwise we just use the previous value. The previous value is the value that was in the field before your input source:

  • in case of an unsubmitted form, this will be the default value
  • in case of an submitted (editable) form, this will be the user input

The value as returned by getValue() must be in the same format as your form input expects.

With this implementation we can prefill the email field with the value from additional data.

While this example uses additional data to prefill, you can fetch any value from everywhere.

Making the Value Immutable

So, now we have prefilled the field with the pre-validated email address. However, the user can edit this field and just submit a different email address. That’s not what we want.

That’s why the input source has the option to make the returned value immutable. This way it will be rendered in the form, but it is not user-editable (so disabled and not mapped).

You can make any value immutable by returning an ImmutableValue or just by using the associated helper function. We modify our getValue() method:

/**
 * @inheritDoc
 */
public function getValue (
    WebsiteRequestContextInterface $context,
    FormInput $input,
    array $additionalData,
    $previousValue
)
{
    $email = $additionalData["email"] ?? null;

    return \is_string($email)
        ? $this->immutable($email)
        : $previousValue;
}

The marked line was changed to now return an immutable value.

Because the user can never fix any validation issues for immutable fields, the validation constraints are removed for immutable fields. So you should always validate beforehand that the value is valid (eg. a valid email in email fields).

Assigning the Input Source to the Form Field

So now we have implemented the input source, however our form field needs to use it. So navigate to the form administration in the backend and assign the input source to the form field, you want to assign it to.

The edit form for every form input will display a choice to select the input source:

Backend UI for selecting the input source

The field will only be displayed if there is at least one input source that supports the given input field.