New in symfony 1.2: God save the nested forms

In symfony 1.1, we introduced a new form sub-framework. It is a great step forward for symfony, even if the learning curve is a bit steep.

We worked a lot to make it even better for symfony 1.2, and more importantly simpler for newcomers.

One of the form framework strengths is its ability to deal with nested forms. A form can embed a form which in turn can also embed another form (and so on):

$article = ArticlePeer::doSelectOne(new Criteria());
 
$articleForm = new ArticleForm($article);
$authorForm = new AuthorForm($article->getAuthor());
$companyForm = new AuthorForm($article->getAuthor()->getCompany());
 
$authorForm->embedForm('company', $companyForm);
$articleForm->embedForm('author', $authorForm);
 

The articleForm renders as show below:

Embedded forms

Another great feature of the form framework is its ability to automatically serialize forms. As the forms above are Propel ones, a simple call to $articleForm->save() will automatically update the $article object with the submitted and validated values and save it back to the database.

But there was a problem in symfony 1.1. The author and the company objects were not saved automatically. So, you had to override the save() method to get the validated data and update the objects manually. Nothing impossible to do, but really annoying as the form framework already had all the needed information to make it automatic.

This has been implemented in symfony 1.2 and so will be available with the upcoming beta 2. That's right, a single call to $form->save() will now update the article, the author, and the company objects. That's a great news by itself, but there is another one: The new admin generator also takes this new feature into account.

Comments

I don't know if this stems directly from my post in the groups requesting this or not, but I just wanted to be the first to thank you for this and hope that I'm not the only one helped greatly.
@Stephen Ostrow: I was more than embarrassed by this issue. It was the result of an oversight and I am the very first one to be more than happy that it is fixed now. I am sure it will help a lot of people.

Please, Fabien can you do a tutorial how to do a project with DoctrinePlugin with few classes and explaining the "recommended" practises to build the Database.

Because there are a lot of possibilities with Doctrine and It's easy to get paralyzed.
@Fabien: No need to be embarrassed. I think a lot of people were waiting for 1.2 to make the switch, and now that it's getting closer the new framework is going to get a lot more interest. It looks like it will be very useful and save lots of time.

Is it better practice to put the embedForm in the form class or do it in the action. I had found the function initially, but I have it in a new form class and I can't figure out if that's what is causing validation issues.
How about handling one to many relationship such as Article -> Authors?

Hello Fabien,

This post comes at a perfect time for me, I've tried to use this feature on a brand new project, but I have to deal with an issue that many users may have to face on their own project.


On my Article form, I've added an author embeded form, but only on the purpose to add an new author.

So I have 3 important fields on my form:

- A select field with the existing authors
- A checkbox "Add a new Author" that I've added
- An empty author form, to add a new Author

Here is the comportment that I want to have :

if "Add a new Author" is checked
I have to desactivate the validator on the existing authors select field
And then save the new Author, and link it to the article
else
I have to desactivate the "new Author" embeded form
And handle the basic existing authors field

Thanks to sfValidatorCallback, I know that I can ADD some custom validators depending on the values submited.

But how can I properly DISABLE some validators depending on the "Add a new author" checked test ?

I know that this comment might seem confused, so here is the form topic that I've created n this subject, with screenshots and source code.
@Stephen Ostrow: It is better to put everything in the form class directly for better reusability.
Oups, I've forgotten to add the link, here it is : http://www.symfony-project.org/forum/index.php/t/16502/
Is this working for Doctrine forms also ? I can't check it right now.
Fabien: That's what I would assume, but that's where i run into validation errors. I'm trying to embed multiples of Form X in Form Y, in your example many Authors in your Article form. Could you add an example of using the naming function for something like that.

sh1ny: Yes this works for Doctrine as well. I've just noticed in 1.1 you have to manually run doctrine:build-forms app. In 1.2 it will automatically build forms, filters, and models while running doctrine:build-all
This is cool and I believe is a much needed feature.
Does this work for merged forms as well?
Thank for this ! I had 'lots of fun' with multiple embedded forms in symfony 1.1, i will be definitively be better in 1.2 !
Hi Fabien!
How we can approach this when using Admin Generator?
Great news, thanks !
Will it be possible to dynamically add fields ? For example, when you have to edit an invoice, you can have a variable number of lines which may be added dynamically via JS.
For the moment, in my Symfony 1.1 project, I treat my lines as separate forms and I "link" them with my array of Propel line objects (they are linked with the same array index).
This solution works but it doesn't appear reliable to me. It would be appreciable to have a built in solution for that...
Thx
well, with sf 1.1 and Doctrine this already worked or not ?
I have used embedded forms and the embedded objects were also saved by doctrine
@Arne: this is because Doctrine itself is able to save all related records you add/edit automatically while it seems Propel is not
syntax error ?
I think :

$companyForm = new AuthorForm($article->getAuthor()->getCompany());

should be :

$companyForm = new CompanyForm($article->getAuthor()->getCompany());

Great feature this nested thing !
Can we use the sfForm's 1.2 implementation into 1.1 symfony's core ?
@Haghen: Yes, it is possible. But for sfFormPropel to work properly, you will also need to upgrade to Propel 1.3 as some signature have changed.
@sh1ny Yes. This all works the same with Doctrine. I will publish an article that demonstrates all the same functionality very soon.

@Arne Yes this already worked with Doctrine. It was a side affect of how Doctrine handles relationships when using the $object->fromArray() method and propel doesn't.
@ALL: we will publish a real world example on Monday. So, stay tuned. In the meantime, read the post on Doctrine implementation... Jon did an amazing job so that Propel and Doctrine are now on par.

Comments are closed.

To ensure that comments stay relevant, they are closed for old posts.