symfony1 icon indicating copy to clipboard operation
symfony1 copied to clipboard

SaveEmbeddedForms replaced by saveObjectEmbeddedForms ???

Open anvaya opened this issue 9 years ago • 9 comments

Hi,

We have a project with Symfony 1.4 which worked. After replacing Symfony with this version, found that the subform functionality was not working as expected.

Turns out the original symfony form function SaveEmbeddedForms has been removed and saveObjectEmbeddedForms is being called instead.

Also noticed, the validators in subforms while being called, are not able to modify the values. We provided a "Remove" button in subform list, and in validator where checking for the remove flag, and removing that item from the values. This no longer works, despite removing the item, at the saveObjectEmbeddedForms, if we do a $form->getValues($subform_name), we get the originally submitted values, not the values modified by the validator.

anvaya avatar Sep 04 '15 11:09 anvaya

Try this version instead https://github.com/punkave/symfony1

j0k3r avatar Sep 04 '15 12:09 j0k3r

Hey! I think that I have the same problem! Any solution to apply in LExpress fork?

davidvegacl avatar Sep 04 '15 14:09 davidvegacl

IMO, this is the wrong way to remove a subform from a list, you must do that before submitting the form.

jeromemacias avatar Oct 01 '15 21:10 jeromemacias

Can you explain how to remove a subform before the user has requested the removal ? You mentioning the remove before form submit is basically asking the same I think. How does the code know in advance which subform the user has asked to remove ?

If you are saying that before "bind" we should do that, then it basically means the same as I suggested "bind" / "saveEmbeddedForms" of the parent.

anvaya avatar Oct 02 '15 02:10 anvaya

You need to do it before calling the bind method.

You can use something like that, in your form class:

  public function bind(array $taintedValues = null, array $taintedFiles = null)
  {
    // get actual sub forms
    $subForms = array_keys($this->embeddedForms);

    // get submitted parameters
    $subParams = null !== $taintedValues ? array_keys($taintedValues) : array();

    // add new forms
    foreach (array_diff($subParams, $subForms) as $index)
    {
      if (strval($index) === self::$CSRFFieldName)
      {
        continue;
      }

      $subForm = new sfForm(); // build your new form here

      $this->embedForm($index, $subForm);
      $this->widgetSchema->setLabel($index, 'added subform'); // configure the label here
    }

    // unset deleted line forms
    foreach (array_diff($subForms, $subParams) as $index)
    {
          unset($this[$index]);
    }

    parent::bind($taintedValues, $taintedFiles);
  }

This is the power of our hacked embedded form implementation.

jeromemacias avatar Oct 02 '15 10:10 jeromemacias

Thank you for that. Always good to know about other methods.

SaveEmbeddedForms will still be involved though, in order to remove the values from the database. This can not be done at the bind stage as validation error will (and should) stop delete action. And subforms database addition / removal only should proceed after parent form save.

anvaya avatar Oct 02 '15 11:10 anvaya

You can manage addition/deletion of item into your doctrine (for example) collection in the overwritted bind method. Call on save will be done after, and as your collection had already been altered object will be add or delete from your database on doctrine form save.

jeromemacias avatar Oct 05 '15 19:10 jeromemacias

Solved?

miniche avatar May 31 '16 14:05 miniche

First, this breaks existing code, so this version of symfony can not be used with existing projects where you simply wish to add PHP 5.5 / 5.6 compatibility.

We also found that if there is a post validator which removes an item from taintedvalues, those values re-appear rendering the validator useless.

anvaya avatar Sep 30 '18 14:09 anvaya