Form plugin : how to dynamically initialize form value depending on header data from a plugin

Hi there,

I am trying to initialize form field’s default values from a plugin based on data from the page header. For this I try to hock onFormInitialized but I cannot access page from here.

public function onFormInitialized(Event $event)
{
  $form = $event['form'];

  if( $form->getName() != 'my-form' ) {
    return;
  }

  $page = $this->grav['page'];
  $my_data = $page->header()->my_data;
  if( $my_data ) {
    $form->setData('my_data', $my_data);
  }
}

This is not working (Grav is rendering not_found.md)

Any suggestion on how to achieve this ?

@randoum, Played a bit with your code…

Having a page with the following header:

---
title: Contact
variables:
  name: My default value
form:
    name: contact

    fields:
        name:
          label: Name
          placeholder: Enter your name
          autocomplete: on
          type: text
          validate:
            required: true
     ... etc.
  

You could try the following in your plugin:

public function onPageInitialized(Event $event)
{
    $this->page = $event['page'];
}

public function onFormInitialized(Event $event)
{
    $form = $event['form'];
    if (isset($this->page) && $form->name === 'contact') {
        $form->setData('name.default', $this->page->header()->variables['name']);
    }
}

This will yield the following form:
image

Another possible solution is calling a static method of a plugin to get default values:

Form definition in Page

form:
    name: contact

    fields:
        name:
          label: Name
          placeholder: Enter your name
          autocomplete: on
          data-default@: ['\Grav\Plugin\MyPluginClass::getDefault', 'name']
          type: text
          validate:
            required: true

Plugin:

public function onPageInitialized($event) {
    self::$page = $event['page'];
}

public static function getDefault(string $field) {
    if (isset(self::$page)) {
        return self::$page->header()->variables[$field] ?? '';
    }
}

Hi,

Yes both work, I would not use the second one though cause static functions are meant to be static.

I also found another alternative, which I am not very satisfied with, but it works :

public function onTwigInitialized(Event $e)
{
  $this->grav['twig']->twig()->addFunction(
    new \Twig_SimpleFunction('set_form_default_values', [$this, 'setFormDefaultValues'])
  );
}

public function setFormDefaultValues($form)
{
  $form->setData(...);
}

In twig template:

{{ set_form_default_values(form) }}

@randoum

I would not use the second one though cause static functions are meant to be static.

For my understanding, would you mind elaborating?

As an alternative:

public static function getDefault(string $field) {
    $grav = Grav::instance();

    $pages = $grav['pages'];
    $page = $pages->find('route/of/page');

    return $page ? $page->header()->variables['name'] : '';
}

There is a very elegant Grav-way of initialising form fields with data in frontmatter by using the Form Plugin method setAllData().

It’s a well kept secret. On the other hand, the how-to is in this forum, see Twig in form yaml, dynamic input values

It took me over two years before I found that post last week. I will be dropping the plugin I created which resembles the answers in this thread.