Symfony中的多个地址的一种形式 - Twig

时间:2017-12-15 11:13:05

标签: php forms symfony for-loop twig

首先,我想说清楚我没有使用Entities / Doctrine来表示我的表格(甚至是)。我正在使用webservices添加/编辑数据库的数据字段

我正在开展一个项目,我需要使用多个地址编辑公司信息。 第一个地址始终是物理地址,所以我在与公司数据相同的循环中获取它。

然而,第二个(以及第三个或第四个,如果存在的话)地址放在一个单独的数据库条目中。 我能够用一个表单编辑公司数据和公司地址(物理地址)(因为数据都在一个集合中)因此我只需要一个表单,而不必使用循环地址。

现在我想编辑第二个地址。我正在循环遍历树枝中的地址并打印出该公司的所有其他地址。 我知道Symfony不允许同一个表单的多个实例,因为这会干扰ID等。

问题是我应该如何仅为特定地址呈现表单。我想通过点击一个按钮进行编辑(如果不编辑则使用bootstrap折叠隐藏表单)

我的代码如下所示:

控制器:

public function editcompany(Request $request, $klantnr)
{

    [...]

    $result = [
        'gegevens' => [],
        'addresses' => [],
    ];

    foreach ($company as $row) {
        $dataFields = [
            [...] // The data fields of the company (including the physical address)
        ];
        foreach ($dataFields as $dataField) {
            if (empty($result['gegevens'][$dataField])) {
                $result['gegevens'][$dataField] = $row[$dataField];
            }
        }
        if($row['AdrGid'] != $result['gegevens']['AdrGid']) {
            $result['addresses'][$row['AdrGid']] = [
                [...] // The data fields for the other addresses 
            ];
        }
    }

    // The form creation of the company data form
    $form = $this->createForm(EditcompanyForm::class);

    // The form of the other addresses
    $form_adres = $this->createForm(EditcompanyAdresForm::class, array(
        [...]
    ));
    $form->handleRequest($request);
    $form_adres->handleRequest($request);


    if($form->isSubmitted() && $form->isValid()) {
        [...] // Handling the submitted data for the company data
    }

    // GEKOPPELDE ADRESSEN company
    if($form_adres->isSubmitted() && $form_adres->isValid()) {

        [...]

        $data = array(
            [...] // Setting the data for the other addresses
        );

        [...]

        // Passing the data and other options to the webservices
        $this->get('http')->companyRequest($data, $admincode, $service, $token);

        $request->getSession()
            ->getFlashBag()
            ->add('success', 'Linked address successfully edited');

        return $this->redirect($request->getUri());
    }

    return $this->render('pages/company/edit.html.twig', array(
        'client' => $result,
        'form_company' => $form->createView(),
        'form_company_adres' => $form_adres->createView()
    ));
 }

Formbuilder(AbstractType):

class EditcompanyAdresForm extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $factuuradres = $options['NawFactuurAdres'];
        $lands = $options['lands'];

        $data = array();
        $builder
            [...] // Add the necessary fields
    }
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            [...] // setting defaults here
        ));
    }
    /**
     * {@inheritdoc}
     */
    public function getBlockPrefix()
    {
        return 'appbundle_form_editcompanyadresform';
    }
}

Twig模板(显示地址:

{% for address in client.addresses %}
    <div class="right-cont-grey">
        [...] // showing addresses
    </div>
{% endfor %}

Twig模板(编辑表单):

{% for address in client.addresses %}
    {{ form_start(form_company_adres, {'  method': 'POST'}) }}
    {{ form_row(form_company_adres._token) }}
        <section class="collapse" id="adres_plus">
            <div id="adres" class="new-adres collapse right-cont-grey">
                <div class="col-sm-12">
                    [...] // Form_widgets with values from database
            </div>
        </section>
    {{ form_end(form_company_adres) }}
{% endfor %}

简而言之:

如何在不干扰的情况下为每个地址使用地址表单?也许在循环内的twig文件中创建视图(渲染)? 我的表单预先填充了数据库中的数据,以便我可以对其进行编辑。

2 个答案:

答案 0 :(得分:1)

修改了我们在聊天中谈到的内容的答案:

正如我在评论中所写,我确定您只需要设置collection field。整个复杂性基本上消失了

一个非常简单的例子是:

<强>控制器

public function editCompanyAction(Request $request)
{
    // get the data anyway you see fit and produce a model (this could also be a dedicated DTO)
    $company = $this->getInput();

    // create the form
    $form = $this
        ->createForm(CompanyWithAddressesType::class, $company)
        ->handleRequest($request)
    ;

    // handle submission
    if ($form->isSubmitted() && $form->isValid()) {
        dump($form->getData()); // === $company
    }

    return $this->render('default/index.html.twig', [
        'form' => $form->createView(),
    ]);
}

表格

这里重要的部分是你添加的字段的名称与数组中作为数据提供的键匹配!

class CompanyWithAddressesType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        // combine the company with a collection of addresses:
        $builder
            ->add('gegevens', CompanyType::class)
            ->add('addresses', CollectionType::class, [
                'entry_type' => AddressType::class,
            ])
        ;
    }
}

class CompanyType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        // all the fields that are *extra* for companies, address fields are inherited
        // because this type extends the address type (see below getParent)
        $builder
            ->add('NawWebsite', TextType::class)
            ->add('email1', TextType::class)
            ->add('AdrNaam1', TextType::class)
        ;
    }

    /**
     * @return @inheritdoc
     */
    public function getParent()
    {
        return AddressType::class;
    }
}

class AddressType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        // all the fields that define an address
        $builder
            ->add('AdrStraat', TextType::class)
            ->add('AdrHuisnummer', TextType::class)
            ->add('AdrPostcode', TextType::class)
            ->add('NawFactuurAdres', CheckboxType::class)
        ;
    }
}

<强>树枝

只需输出表格即可。任何form customization都适用

{{ form_start(form) }}
    <div>
        <h4>Company</h4>
        {{ form_row(form.gegevens.NawWebsite) }}
        {{ form_row(form.gegevens.email1) }}
        {{ form_row(form.gegevens.AdrNaam1) }}
    </div>

    <div>
        <h4>Main address</h4>
        {{ form_rest(form.gegevens) }}
    </div>

    <div>
        <h4>Extra addresses</h4>
        {% for address in form.addresses %}
            {{ form_errors(address) }}
            {{ form_widget(address) }}
        {% endfor %}
    </div>

    <button>Submit</button>
{{ form_end(form) }}

答案 1 :(得分:0)

我认为你需要将表单放在循环之外,然后有一个隐藏的输入字段,用于标识需要在提交时保存的地址。因此,当未显示其他字段时,不会提交它们。 这意味着您需要一些Javascript逻辑来显示和隐藏地址。

Twig模板(编辑表单):

{{ form_start(form_company_adres, {'  method': 'POST'}) }}
{% for address in client.addresses %}
    <div id="address-{{ loop.index }}" class="address">
        <input type="hidden" name="address-number" value="{{ loop.index }}"/>
        {{ form_row(form_company_adres._token) }}
            <section class="collapse" id="adres_plus">
                <div id="adres" class="new-adres collapse right-cont-grey">
                    <div class="col-sm-12">
                        [...] // Form_widgets with values from database
                </div>
            </section>
    </div>
{% endfor %}
{{ form_end(form_company_adres) }}