如何为实体类型 select 设置默认 selected 选项?

How to set default selected option for Entity Type select?

所以我试图在我的表单中设置一个 selected 选项,但我似乎无法找到如何执行此操作。我用谷歌搜索了一下,一切似乎都是针对 Symfony2 的,其中 default 是一回事,这似乎不再是 Symfony4 的情况。

我试过使用 dataempty_data 但两者都没有 select 正确的值..

# weirdly, setting to ['guru'] gets undefined index error,
# setting to $options doesn't error
->add('guru', EntityType::class, array(
    'class' => User::class,
    'choice_label' => 'username',
    'data' => $options['guru'] 
 ))

以及我如何传递 $options:

$form = $this->createForm(EditCategoryType::class, array('guru' => $guruName));

正如我在评论中所说,你做错了什么。我会解释所有的过程:

calling the form in the controller

$person = new Person();
$person->setName('My default name');
$form = $this->createForm('AppBundle\Form\PersonType', $person);
$form->handleRequest($request);

然后执行createForm函数这里就是代码

Symfony\Bundle\FrameworkBundle\Controller\ControllerTrait

    protected function createForm($type, $data = null, array $options = array())
    {
        return $this->container->get('form.factory')->create($type, $data, $options);
    }

可以看到数据或选项没有直接在表单中设置,调用另一个函数然后创建表单

这是我在 PersonType 中进行转储时的结果

PersonType.php on line 20:
array:35 [▼
  "block_name" => null
  "disabled" => false
  "label" => null
  "label_format" => null
  "translation_domain" => null
  "auto_initialize" => true
  "trim" => true
  "required" => true
  "property_path" => null
  "mapped" => true
  "by_reference" => true
  "inherit_data" => false
  "compound" => true
  "method" => "POST"
  "action" => ""
  "post_max_size_message" => "The uploaded file was too large. Please try to upload a smaller file."
  "error_mapping" => []
  "invalid_message" => "This value is not valid."
  "invalid_message_parameters" => []
  "allow_extra_fields" => false
  "extra_fields_message" => "This form should not contain extra fields."
  "csrf_protection" => true
  "csrf_field_name" => "_token"
  "csrf_message" => "The CSRF token is invalid. Please try to resubmit the form."
  "csrf_token_manager" => CsrfTokenManager {#457 ▶}
  "csrf_token_id" => null
  "attr" => []
  "data_class" => "AppBundle\Entity\Person"
  "empty_data" => Closure {#480 ▶}
  "error_bubbling" => true
  "label_attr" => []
  "upload_max_size_message" => Closure {#478 ▶}
  "validation_groups" => null
  "constraints" => []
  "data" => Person {#407 ▼ // Here is the data!!!
    -id: null
    -name: "My default name"
    -salary: null
    -country: null
  }
]

如您所见,数据在 data 处建立了索引,这就是您收到未定义索引错误的原因

所以正确的方法是从控制器设置实体值或使用您的表单作为服务并调用存储库并使用自版本 2 以来未更改的数据选项设置值。我的意思是你使用的表格有误。

请更改您的代码。

希望对您有所帮助

EDITED IN THE SYMFONY 4 WAY(with out namespaces bundles)

让我们看看,我有一个个人实体,其名称仅用于此示例

The controller

    $person = new Person(); //or $personsRepository->find('id from request')
    $person->setName('My default name');
    $form = $this->createForm(PersonType::class, $person);
    $form->handleRequest($request);

The form

public function buildForm(FormBuilderInterface $builder, array $options)
    {

        $builder->add('name',TextType::class,[
            //'data' => 'aaaaa' // <= this works too

        ]);

    }

The options array value which proves that you are accessing wrong

PersonType.php on line 20:
array:35 [▼
  "block_name" => null
  "disabled" => false
  "label" => null
  "label_format" => null
  "translation_domain" => null
  "auto_initialize" => true
  "trim" => true
  "required" => true
  "property_path" => null
  "mapped" => true
  "by_reference" => true
  "inherit_data" => false
  "compound" => true
  "method" => "POST"
  "action" => ""
  "post_max_size_message" => "The uploaded file was too large. Please try to upload a smaller file."
  "error_mapping" => []
  "invalid_message" => "This value is not valid."
  "invalid_message_parameters" => []
  "allow_extra_fields" => false
  "extra_fields_message" => "This form should not contain extra fields."
  "csrf_protection" => true
  "csrf_field_name" => "_token"
  "csrf_message" => "The CSRF token is invalid. Please try to resubmit the form."
  "csrf_token_manager" => CsrfTokenManager {#457 ▶}
  "csrf_token_id" => null
  "attr" => []
  "empty_data" => Closure {#480 ▶}
  "error_bubbling" => true
  "label_attr" => []
  "upload_max_size_message" => Closure {#478 ▶}
  "validation_groups" => null
  "constraints" => []
  "data" => Person {#407 ▼
    -id: null
    -name: "My default name" //Here is the data
    -salary: null
    -country: null
  }
]

AppBundle 只是我的文件夹结构中的另一个文件夹。很高兴测试你自己。 formCreate 函数的第二个参数是实体或数据,而不是您认为选项是数据的选项。

$parentCategory = $categoryRepository->repository->find(2);
$category = new Category();
$category->setParentCategory(parentCategory);
$form = $this->createForm(CategoryType::class, $category);

我们选择了预定义的顶级类别,如果你这样使用它就可以了。

试试这个: empty_data documentation

因此,在@Juan I. Morales Pestana 的帮助下,我找到了答案,我将以下内容添加为答案而不是将其标记为正确的唯一原因是因为似乎在方式上略有不同现在可以使用了..:[=​​13=]

控制器现在读取(感谢@Juan):

$category = $this->getDoctrine()->getRepository(Category::class)->find($id);
$category->setGuru($category->getGuru());

$form = $this->createForm(EditCategoryType::class, $category);

我的 EditCategoryType class:

->add('guru', EntityType::class, array(
    'class' => User::class,
    'choice_label' => 'username',
    'mapped' => false,
    'data' => $options['data']->getGuru()
))

更新的树枝模板:

{{ form_widget(form.guru, { 'attr': {'class': 'form-control'} }) }}
<a href="{{ path('register_new', { idpackage: p.id }) }}" class="btn_packages">

//sends to form type the package id
$fromPackage = '';
if($request->query->get('idpackage')) {
$fromPackage = $request->query->get('idpackage');
}

$form = $this->createForm(RegisterFormType::class, $register, ['fromPackage' => $fromPackage]);

in formType set the param in options: 
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Register::class,
'fromPackage' => null
]);
}

->add('package',EntityType::class, [
'label' => 'Select one item',
'class' => Package::class,
'choice_label' => function($package) {
    return $package->getTitle() . ' | crédits : ' . $package->getAmount();
},
'attr' => ['class' => 'input-text', ],
'placeholder' => '...',
'required' => false,
'choice_attr' => function($package) use ($idFromPackage) {
    $selected = false;
    if($package->getId() == $idFromPackage) {
        $selected = true;
    }
    return ['selected' => $selected];
},
])