访问视图中的嵌套表单字段(嵌入表单集合)

问题描述 投票:2回答:1

我尝试使用CollectionType在symfony 3中构建一个巨大的形式。我必须定义多个子表单,一些是多个,一些是单个。

这是我的FormType:

public function buildRegistrationForm(FormBuilderInterface $builder, array $options) {
    $builder->add('userRegistration', CollectionType::class, [
        'entry_type' => UserRegistrationType::class,
        'entry_options' => ['label' => true],
    ]);
    $builder->add('meters', CollectionType::class, [
        'entry_type' => MeterType::class,
        'entry_options' => ['label' => true],
        'allow_add' => true,
    ]);
    ...
}

现在我尝试访问视图中的CollectionType字段。这个代码是:

{{ form_label(registrationForm.email, null, {'label_attr': {'class': 'form-label'}}) }}
{{ form_widget(registrationForm.email, {'attr': {'class': 'form-control'}}) }}

但我得到错误:

Neither the property "email" nor one of the methods "email()", "getemail()"/"isemail()"/"hasemail()" or "__call()" exist and have public access in class "Symfony\Component\Form\FormView".

我知道Symfony试图直接从主窗体(registrationForm)中获取电子邮件字段,但我不知道如何访问子窗体。在文档(http://symfony.com/doc/current/form/form_collections.html)中,我描述了我可以使用registrationForm.userRegistration.email简单地访问子表单。但这给了我错误:

Neither the property "userRegistration" nor one of the methods ...

如何访问视图中的子字段?

php symfony symfony-forms symfony-3.3
1个回答
0
投票
  1. 第一步是了解我们为什么要使用collectionType?如果您具有“一对多”或“多对多”关系,则应使用CollectionType。例: /** * Class Team * * @ORM\Entity * @ORM\Table(name="example_project_team") */ class Team { // ... /** * Unidirectional Many-To-Many * * Many Teams has many users accounts. * * @var ArrayCollection $users * * @ORM\ManyToMany( * targetEntity="AppBundle\Entity\User", * cascade={"persist", "remove"}, * orphanRemoval=true * ) * * @ORM\JoinTable(name="teams_to_users", * joinColumns={@ORM\JoinColumn(name="team_id", referencedColumnName="id", onDelete="CASCADE")}, * inverseJoinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id", onDelete="CASCADE")} * ) */ protected $users; // ... }

在这个例子中,我们有一个名为team的实体。每个团队都有很多用户(这只是与您相关的示例)。我想,你已经创建了User实体。

  1. 想象一下,因为你有用户实体的UserRegistrationType。 /** * Class UserRegistrationType */ class UserRegistrationType extends AbstractType { /** * @param FormBuilderInterface $builder * @param array $options */ public function buildForm(FormBuilderInterface $builder, array $options) { $builder ->add('username', 'Symfony\Component\Form\Extension\Core\Type\TextType', [ 'label' => false, 'translation_domain' => 'messages' ]) ->add('email', 'Symfony\Component\Form\Extension\Core\Type\TextType', [ 'label' => false, 'translation_domain' => 'messages' ]) // ... the other fields ; } /** * @return string */ public function getName() { return 'app_user_registration_type'; } /** * @return null|string */ public function getBlockPrefix() { return 'app_user_registration'; } /** * @param OptionsResolver $resolver */ public function configureOptions(OptionsResolver $resolver) { $resolver->setDefaults(array( 'data_class' => User::class, 'csrf_protection' => true, 'validation' => true, )); } } 请注意!!!我们在这里使用'data_class' => User::class,正如您所看到的,我们在userRegistrationType中使用User对象。这意味着,我们可以为每个对象使用此表单,其中包含User类型的字段或类型为CollectionType的字段(您的情况!)但是用户集合!我们的团队实体拥有现场用户。
  2. 现在,由于我们已经创建了userRegistrationType,我们可以将它添加到TeamFormType中。 public function teamRegistrationFormType(FormBuilderInterface $builder, array $options) { $builder->add('users', CollectionType::class, [ 'entry_type' => UserRegistrationType::class, 'entry_options' => [ 'label' => false, ], 'label' => false, 'allow_add' => true, 'allow_delete' => true, 'by_reference' => false, ]); // ... }
  3. 最后。你的表格在树枝上: {# you can add this form in your twig file #} <div class="box"> {% block team_form %} {{ form_start(team_form, { 'attr': {'class': 'form-horizontal', 'role' : 'form'}}) }} <div class="box-body"> <div class="form-group"> {% block users_collection %} <label for="" class="col-sm-2 control-label"> {{ 'admin.label.phones'|trans }} </label> <div class="col-sm-10 users" data-prototype="{{ form_widget(team_form.users.vars.prototype)|e('html_attr') }}"> {% for user in users %} <div> {{ form_widget(user) }} </div> {% endfor %} </div> <span class="help-block"> {{ form_errors(users) }} </span> {% endblock users_collection %} </div> <div class="form-group"> <div class="col-sm-offset-2 col-sm-10"> <button type="submit" class="btn btn-danger"> {{ 'admin.button.submit'|trans }} </button> </div> </div> {{ form_end(team_form) }} </div> {% endblock team_form %} </div>
  4. 在这里,我们有奇怪的小部件{{ form_widget(user) }}。我想,你想编辑这个小部件的样式。你可以使用Symfony内置的表单样式来完成它。创建文件(如果你还没有创建它)path_to_your_project/src/AppBundle/Resources/views/Form/fields.html.twig并添加你的userRegistrationType的样式。请注意,此窗口小部件的名称是从表单块前缀的名称和字符串“_widget”(public function getBlockPrefix())创建的 {% file fields.html.twig %} {% trans_default_domain 'messages' %} {% block app_user_registration_widget %} {% spaceless %} <div class="form-group" {{ block('widget_container_attributes') }}> <div class="col-sm-2"> {{ form_widget(form.username, {'attr' : {'class' : 'form-control' }}) }} </div> <div class="col-sm-4"> {{ form_widget(form.email, {'attr' : {'class' : 'form-control' }}) }} </div> </div> {% endspaceless %} {% endblock %}
  5. 当然,您必须设置添加和删除按钮。为此,我建议你使用官方文档:How to Embed a Collection of Forms或者你可以使用bundle(但不是官方文档):ninsuo/symfony-collection
© www.soinside.com 2019 - 2024. All rights reserved.