jdo*_*dog 5 forms datamapper symfony
我正在使用此处提供的解决方案在 CRUD列表中添加用于批量操作的复选框。
但是,我的结果与Pagerfanta分页,因此看来我需要在表单中使用DataMapper。
我尝试了各种解决方案,但是无法在表单数据中获得所选字段:
class ModelEntitySelectionType extends AbstractType  implements DataMapperInterface
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('model_id', EntityType::class, [
            'required' => false,
            'class' => ModelFile::class,
            'choice_label' => 'id',
            'property_path' => '[id]', # in square brackets!
            'multiple' => true,
            'expanded' => true
        ])
            ->add('action', ChoiceType::class, [
                'choices' => [
                    'Delete' => 'delete'
                ]
            ])
            ->add('submit', SubmitType::class, [
                'label' => 'Process'
            ])
        ->setDataMapper($this)
        ;
    }
    public function setDefaultOptions(ExceptionInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => null,
            'csrf_protection' => false
        ));
    }
    public function mapDataToForms($data, $forms)
    {
        // there is no data yet, so nothing to prepopulate
        if (null === $data) {
            return;
        }
        $formData = [];
        /** @var FormInterface[] $forms */
        $forms = iterator_to_array($forms);
        $forms['model_id']->setData($formData);
    }
    public function mapFormsToData($forms, &$data)
    {
        //$forms = iterator_to_array($forms);
        $data = [
            'model_id' => iterator_to_array($data)
            ];
    }
缺少的部分是当我使用调试器调查mapFormsToData时:
我了解我必须如何“遍历” PagerFanta对象,因为它没有ArrayAccess,但是实际上已勾选了哪个复选框的数据在哪里?另外,我的其他表单字段(操作)在这里无法访问
我认为你的做法是有问题的。Form 组件旨在修改传递给它的对象,据我所知,这不是您想要的。您不想修改Pagerfanta对象,而是想选择实体进行批量操作。
因此,为了解决您的问题,必须发生非常非常原始的事情:<form>必须在页面上显示 A ,并为作为批量操作候选者的每个条目显示一个复选框,并使用一些按钮来触发批量操作)。
我想你的表单 - 除了复选框的条目 - 没问题,据我所知,这并不是你的问题。您甚至对编辑对象不感兴趣Pagerfanta(我希望)而只想进行选择。为此,我们通过一个选项向表单提供排队显示在页面上的对象集合,然后使用该选项构建字段(阅读:将集合传递到 EntityType 字段)。
在你的控制器的某个地方,你应该有类似的东西:
$form = $this->createForm(ModelEntitySelectionType::class, $pagerfanta);
将其更改为:
$form = $this->createForm(ModelEntitySelectionType::class, [], [
    'model_choices' => $pagerfanta->getCurrentPageResults(),
]);
该方法getCurrentPageResults返回当前页面的实体集合(显然)。作为第二个参数的空数组[]最终是您尝试编辑/创建的对象/数组。我在这里选择了一个数组,但您也可以将其设为一个新的操作类(如 DTO),例如ModelBulkAction具有以下属性:model和action:
class ModelBulkAction {
    public $model;
    public $action;
}
请注意,这些类型的对象只有在多个地方使用时才有意义 - 那么调用将是:
$form = $this->createForm(ModelEntitySelectionType::class, new ModelBulkAction(), [
    'model_choices' => $pagerfanta->getCurrentPageResults(),
]);
如果您向表单提供了一个不需要该选项的选项,则表单组件将会抱怨。这就是 的目的AbstractType::configureOptions(OptionsResolver $resolver)。(旁注:我不知道,你setDefaultOptions应该实现什么,尽管如此。ExceptionInterface没有任何线索,真的)。
public function configureOptions(OptionsResolver $resolver) {
    $resolver->setRequired([
         'model_choices', // adds model_choices as a REQUIRED option!
    ]);
    $resolver->setDefaults([
         // change null to ModelBulkAction::class, if applicable
         'data_class' => null, 
    ]);
}
最后将集合实际传递给实体类型子表单:
    // in ModelEntitySelectionType::buildForm($builder, $options)
    $builder->add('model', EntityType::class, [
        'required' => false,
        'class' => ModelFile::class,
        'choice_label' => 'id',
        'choices' => $options['model_choices'], // set the choices explicitly
        'multiple' => true,
        'expanded' => true,
    ])
    // ...
    ;
此外,您的数据映射不再需要,应该删除。
这与您链接的 Stack Overflow 问题和答案非常相似。但是,形式中的键不同,因为我的方法略有不同:
{{ form_start(form) }}
{% for entity in pagerfanta %}
    {# stuff before the checkbox #}
    {{ form_widget(form.model[entity.id]) }}
    {# stuff after the checkbox #}
{% endfor %}
{# place the selection of action somewhere! and possibly the "submit" button #}
{{ form_widget(form.action) }} 
{{ form_end(form) }}
(注意:这可能会显示复选框旁边条目的ID,因为这是您的choice_label,我相信可以通过以下方式删除它:{{ form_widget(form.model[index], {label:false}) }}或者通过将 设为choice_label而false不是'id')。
$form->handleRequest($request);您可以检查提交情况和表单值后:
if($form->isSubmitted() && $form->isValid()) {
    $data = $form->getData();
    // $data['model'] contains an array of entities, that were selected
    // $data['action'] contains the selection of the action field
    // do the bulk action ...
}
如果您实现了该ModelBulkAction方法,$data则它是此类对象,并且可供$data->model您$data->action使用(或传递到存储库)。
显然,该model_choices选项几乎可以以您喜欢的任何方式命名(但不应与可能具有的现有选项冲突AbstractType)。
要使实体可选择(除了复选框之外),您可以使用<label for="{{ form.model[index].vars.id }}"><!-- something to click --></label>非 JavaScript 方法(可以添加样式)。对于 js 来说,这几乎是无关紧要的,因为您可能只需要选择该行中的第一个复选框。
除了向表单提供对象集合之外,理论上您还可以提供 ids 列表并使用ChoiceType代替EntityType. 但这并没有什么好处。
| 归档时间: | 
 | 
| 查看次数: | 101 次 | 
| 最近记录: |