php - Saving multiple embedded forms using Symfony's Formbuilder, multiple entrees work fine 1 level deep, goes wrong 2 levels deep. (1-to-many), -
the problem have regarding symfony's (3) formbuilder. have 3 entities created 3 formtypes. see below; actual question below code.
i have following entities:
documentbaldoc 1 -> * documentbaldocconnectionpoint 1 -> * documentbaldocaccount
i try achieve following. want create form documentbaldoc, want create multiple forms documentbaldocconnectionpoints , want create multiple forms documentbaldocconnectionpointaccounts. when saved these need stored in database relation (fk).
i have following class documentbaldoc (form)
namespace foobundle\form\documents\baldoc; use foobundle\entity\documents\baldoc\documentbaldoc; use symfony\component\form\abstracttype; use symfony\component\form\extension\core\type\submittype; use symfony\component\form\formbuilderinterface; use symfony\component\optionsresolver\optionsresolver; use symfony\component\form\extension\core\type\collectiontype; class documentbaldoctype extends abstracttype { /** * {@inheritdoc} */ public function buildform(formbuilderinterface $builder, array $options) { $builder ->add('document_release') ->add('identification') ->add('version') ->add('type') ->add('creationdatetime') ->add('validityperiod') ->add('contractreference') ->add('contracttype') ->add('issuermarketparticipantidentification') ->add('issuermarketparticipantidentificationcodingscheme') ->add('issuermarketparticipantmarketrolecode') ->add('recipientmarketparticipantidentification') ->add('recipientmarketparticipantidentificationcodingscheme') ->add('recipientmarketparticipantmarketrolecode') ->add('applicationcontext') ->add('applicationcontextcodingscheme') ->add('connectionpoints', collectiontype::class, [ 'entry_type' => documentbaldocconnectionpointtype::class, 'allow_add' => true, 'by_reference' => false, ]) ->add('save', submittype::class); } /** * {@inheritdoc} */ public function configureoptions(optionsresolver $resolver) { $resolver->setdefaults(array( 'data_class' => documentbaldoc::class )); } }
i have following class documentbaldocconnectionpoint (form)
namespace foobundle\form\documents\baldoc; use foobundle\entity\documents\baldoc\documentbaldocconnectionpoint; use symfony\component\form\abstracttype; use symfony\component\form\extension\core\type\collectiontype; use symfony\component\form\formbuilderinterface; use symfony\component\optionsresolver\optionsresolver; class documentbaldocconnectionpointtype extends abstracttype { /** * {@inheritdoc} */ public function buildform(formbuilderinterface $builder, array $options) { $builder ->add('identification') ->add('identificationcodingscheme') ->add('measureunitcode') ->add('accounts', collectiontype::class, [ 'entry_type' => documentbaldocaccounttype::class, 'allow_add' => true, 'by_reference' => false, ]); } /** * {@inheritdoc} */ public function configureoptions(optionsresolver $resolver) { $resolver->setdefaults(array( 'data_class' => documentbaldocconnectionpoint::class )); } }
and have following class documentbaldocaccount (form)
namespace foobundle\form\documents\baldoc; use foobundle\entity\documents\baldoc\documentbaldocaccount; use symfony\component\form\abstracttype; use symfony\component\form\formbuilderinterface; use symfony\component\optionsresolver\optionsresolver; class documentbaldocaccounttype extends abstracttype { /** * {@inheritdoc} */ public function buildform(formbuilderinterface $builder, array $options) { $builder ->add('identification') ->add('identificationcodingscheme') ->add('accounttso') ->add('accounttsocodingscheme'); } /** * {@inheritdoc} */ public function configureoptions(optionsresolver $resolver) { $resolver->setdefaults(array( 'data_class' => documentbaldocaccount::class )); } }
i use symfony's formbuilder generate form documentbaldoc entity. adding collectiontype documentbaldocconnectionpoint entry_type gives me ability make uses of prototype variable in template.
{% block document %} {{ form_start(form) }} <ul class="connectionpoints" data-prototype="{{ form_widget(form.connectionpoints.vars.prototype)|e('html_attr') }}"> {{ form_widget(form) }} </ul> {{ form_end(form) }} {% endblock %}
after can use javascript create endless stream of documentbaldocconnectionpoint forms , when press save (multiple!!) documentbaldocconnectionpoints stored in db fk parent documentbaldoc.
so far works well, problem though comes when want same documentbaldocconnectionpointaccount. documentbaldocconnectionpoint form not exists on pageload can not access prototype attribute directly, solved creating javascript logic fires when documentbaldocconenctionpoint form created. follows same logic parent. problem encounter can not save multiple documentbaldocconenctionpointaccounts, saves last 1 makes me think somewhere in process it's not saved array, or somewhere array gets overwritten last entry. i've been tinkering on couple of days can not find differences in logic (formtypes or entities, relation definitions follow same structure) makes me think not using supposed used.
these annotation relation definitions both entities, both $connectionpoints , $accounts instantiated arraycollections in constructor of entity.
// documentbalcon @orm\onetomany(targetentity="documentbaldocconnectionpoint", mappedby="document", cascade={"persist"}) private $connectionpoints; // documentbalconconnectionpoint @orm\onetomany(targetentity="documentbaldocaccount", mappedby="connectionpoint", cascade={"persist"}) private $accounts;
the thing stands out prototype of documentbaldocconnectionpoint form rendered __name__ syntax needs replaced unique identifier , same thing not happen when grab documentbaldocconnectionpointaccount prototype, solved creating own identifier guarantee uniqueness.
i've read symfony documentation regarding formbuilder , creating these kind of embedded forms documentation states trying possible, without examples. have no clue if doing proper way of handling these kind of embedded forms or missing steps in process.
any information or regarding problem more welcome!
problem solved.
the first child form documentbaldocconnectionpoint contained attribute prototype contains form documentbaldocconnectionpointaccount. when changing __name__ value in documentbaldocconnectionpoint values documentbaldocconnectionpointaccount als got changed unintentionally resulted in unexpected behaviour every documentbaldocconnectionpointaccount form got placed in array on key value of 'index', changed per documentconnectionpoint.
the solution used following:
in documentbaldocconnectionpointtype class in function buildform added prototype key value "accounts" gives me possibility fetch prototype form name reference.
public function buildform(formbuilderinterface $builder, array $options) { $builder ->add('identification') ->add('identificationcodingscheme') ->add('measureunitcode') ->add('accounts', collectiontype::class, [ 'entry_type' => documentbaldocaccounttype::class, 'allow_add' => true, 'by_reference' => false, 'prototype' => 'accounts' ]); }
in twig template added div following:
<div id="prototypes" data-prototype-account="{{ form_widget(form.connectionpoints.vars.prototype.children['accounts'].vars.prototype) | e }}" data-prototype-connection-point="{{ form_widget(form.connectionpoints.vars.prototype) | e }}"> </div>
this results in div prototype forms stored , gives me possibility query , use them when needed.
Comments
Post a Comment