In my update form, I want to add a data attribute on the inputs that will contains the initial value of the entity. This way, I will be able to highlight the input when the user will modify it.
In the end, only the input modified by the users will be highlighted.
I want to use this only in update, not in creation.
To do so, I created a form extension like this:
class IFormTypeExtension extends AbstractTypeExtension{...public static function getExtendedTypes(){ //I want to be able to extend any form type return [FormType::class];}public function configureOptions(OptionsResolver $resolver){ $resolver->setDefaults(['is_iform' => false,'is_iform_modification' => function (Options $options) { return $options['is_iform'] ? null : false; }, ]); $resolver->setAllowedTypes('is_iform', 'bool'); $resolver->setAllowedTypes('is_iform_modification', ['bool', 'null']);}public function buildView(FormView $view, FormInterface $form, array $options){ if (!$options['is_iform'] && !$this->isParentIForm($form)) { return; } //We need to add the original value in the input as data-attributes if (is_string($form->getViewData()) || is_int($form->getViewData())) { $originValue = $form->getViewData(); } elseif (is_array($form->getViewData())) { if (is_object($form->getNormData())) { $originValue = implode('###', array_keys($form->getViewData())); } elseif (is_array($form->getNormData()) && count($form->getNormData()) > 0 && is_object($form->getNormData()[0])) { $originValue = implode('###', array_keys($form->getViewData())); } else { $originValue = implode('###', $form->getViewData()); } } else { //There's no value yet $originValue = ''; } $view->vars['attr'] = array_merge($view->vars['attr'], ['data-orig-value' => $originValue]);}private function isParentIForm(FormInterface $form){ if (null === $form->getParent()) { return $form->getConfig()->getOption('is_iform'); } return $this->isParentIForm($form->getParent());}}
As you can see in the buildView method, I get the originValue from the ViewData.
In a lot of cases, this works well.
But if I have any validation error in my form OR if I reload my form through AJAX, the ViewData
contains the new information and not the values of the entity I want to update.
How can I get the values of the original entity?
- I don't want to make a DB request in here.
- I think I can use the
FormEvents::POST_SET_DATA
event, then save the entity values in session and use these in thebuildView
. - I could also give a new Option in my OptionResolver to ask for the initial entity.
- Is it possible to have the original data of the entity directly form the
buildView
? (If I'm not wrong, this means the form before we call thehandleRequest
method).
Someone wanted to have an example with a controller. I don't think it's really interresting, because with the FormExtension, the code will be added automatically. But anyway, here is how I create a form in my controller :
$form = $this->createForm(CustomerType::class, $customer)->handleRequest($request);
And in the CustomerType, I will add the 'is_iform' key with configureOptions() :
public function configureOptions(OptionsResolver $resolver){ $resolver->setDefaults(["translation_domain" => "customer","data_class" => Customer::class,'is_iform' => true //This line will activate the extension ]);}