Symfony Forms: HTML5 Datalist

Symfony Forms: HTML5 datalist

First, add your new FormType for the field:.

<?php
// src/Acme/Form/Type/DatalistType
namespace Acme\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\OptionsResolver\OptionsResolver;

class DatalistType extends AbstractType
{
public function getParent()
{
return TextType::class;
}

public function configureOptions(OptionsResolver $resolver)
{
$resolver->setRequired(['choices']);
}

public function buildView(FormView $view, FormInterface $form, array $options)
{
$view->vars['choices'] = $options['choices'];
}

public function getName()
{
return 'datalist';
}
}

In services.yml:

form.type.datalist_type:
class: Acme\Form\Type\DatalistType
tags:
- { name: form.type, alias: datalist }

Do you have a form theme? If yes, skip to the next step, if no, create a new one in app/Resources/views/Form/fields.html.twig and change your default Twig theme to it:

# app/config/config.yml
twig:
form_themes:
- ':Form:fields.html.twig'

Now define a template for your new field in the form theme:

{% block datalist_widget %}
<input list="{{ id }}_list" {{ block('widget_attributes') }}{% if value is not empty %}value="{{ value }}"{% endif %}>
<datalist id="{{ id }}_list">
{% for choice in choices %}
<option value="{{ choice }}"></option>
{% endfor %}
</datalist>
{% endblock %}

Use your field in FormType:

public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('country', DatalistType::class, ['choices' => ['a', 'b']]);
}

Instead of ['a', 'b'] You need to load your choices from DB somehow, I'd suggest passing them in form options as the easiest solution.

Symfony 4, add a text input field inside a ChoiceType

What you are looking for is an HTML datalist element, currently not supported by Symfony forms, but you can create your own:
Symfony Forms: HTML5 datalist

How to get form data with session in Symfony Form

Yes you can use $form->getData() but to do that you need to do this according to the doc here with using if ($form->isSubmitted() && $form->isValid()) { among others.

Symfony 5 - Custom ChoiceType with TextType

It's not easy to do, but you can do it with a customs form type field and a Twig theme:

1.Create a new field type like ChoiceInputType. That class should contain two field types, ChoiceType and TextType.

/**
* Class ChoiceInputType
*/
class ChoiceInputType extends AbstractType
{
/**
* {@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add(
'choiceType',
ChoiceType::class,
[
'required' => false,
'choices' => $options['choices'],
'label' => 'Make your choice...',
]
)
->add(
'choiceInput',
TextType::class,
[
'required' => false,
'label' => false,
'attr' => [
'placeholder' => 'Other choice...',
],
]
);
}

/**
* {@inheritdoc}
*/
public function buildView(FormView $view, FormInterface $form, array $options): void
{
$view->vars['choices'] = $options['choices'];
}

/**
* {@inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setRequired(['choices']);

$resolver->setDefaults(
[
'choices' => [],
]
);
}

/**
* {@inheritdoc}
*/
public function getName(): string
{
return 'choiceInputType';
}
}

2.Create a twig theme on your new custom field type and organize it as you want.

{% block choiceInputType_widget %}
... custom here ...
{% endblock %}

3.Use your new ChoiceInputTypeinside your form.

$builder->add(
'choiceInputType',
ChoiceInputType::class,
[
'mapped' => false,
'block_prefix' => 'choiceInputType',
'label' => false,
'choices' => [
'test 1' => 1,
'test 2' => 2,
'test 3' => 3,
]
]
);

Here some links to other questions similar to this thread that can help you:

  • Symfony Forms: HTML5 datalist
  • Customize the rendering of a choice/entity field in Symfony2

Symfony form type extension for custom types

FormType inheritance is built on method getParent(). Probably, you should not extend MyBaseType but return it in getParent()

getParent()
When returning a (fully-qualified) class name here, Symfony will call each method of that type (i.e. buildForm(), buildView(), etc.)
and all its type extensions, before calling the corresponding method
of your custom type.

https://symfony.com/doc/current/form/create_custom_field_type.html#creating-form-types-created-from-scratch


class MyBaseType extends AbstractType
{
}

class MySubType1 extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('blahblahblah', TextType::class, [
'label' => 'blahblahblah',
])
(etc.)
;
}

public function getParent()
{
return MyBaseType::class;
}
}



Related Topics



Leave a reply



Submit