Symfony2动态分配attr到表单字段

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

我希望能够动态设置表单字段的

required=true/false
选项或
array(...other stuff..., 'class' => ' hidden')

上下文如下:有一个带有一些字段的“项目”实体。当我使用表单创建其他实体时,我想检查项目实体的某些属性,并就我正在创建的实体的某些字段的可见性/必需性做出决策。

例如,如果项目具有属性“timePressure=high”,则不需要给定实体的字段(但可见)。如果有其他条件它就会变得不可见等等...

所以基本上我希望在表单生成器的每个

->add()
中调用一个函数来吐出相关部分(例如,该函数将返回一个带有“required=true”的字符串或与隐藏类相关的其他字符串)。问题是该函数应该作为参数:projectID(好的,这可以作为表单构建器的选项传递)、我们正在讨论的类和字段来决定。我正在设想类似的事情:

->add('background', 'textarea', array('attr' => array('rows' => 4, functionToDecideIfInvisible($projectId)), functionToDecideRequiredness($projectId)))

这两个函数将返回字符串

'class' => ' hidden'
required=true
(或 false)

我想避免指定字段名称(在本例中为

background
)以避免代码重复。

这可以吗?

关于如何解决问题的其他建议?

谢谢!

SN

php symfony symfony-forms
2个回答
2
投票

您需要的是表单事件:http://symfony.com/doc/current/cookbook/form/dynamic_form_modification.html#cookbook-form-events-underlying-data

它们允许您根据您的数据修改表单。

您在控制器中创建项目表单:

$form = $this->createForm(new ProjectType(), $project, array(
    'action' => $this->generateUrl('project.edit'),
    'method' => 'POST',
));

然后添加 FormEvents::PRE_SET_DATA 监听器:

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
        $project = $event->getData();
        $form = $event->getForm();

        // check timePressure on the Project object
        if ('high' === $project->timePressure) {
            $form->add('timePressure', 'text', array(
                'required' => false
            );
        }
    });
}

-1
投票

我找到了一种方法。

我的添加如下:

->add('background', 'textarea', array_merge($this->vr->fieldReq(get_class($this), 
'background', $projectID), array('attr' => array_merge(array('rows' => 4, ),
$this->vr->fieldCssClass(get_class($this), 'background', $projectID) ) )))

为此,我必须将表单定义为服务,另外我创建了另一个类作为服务(包含我需要的两种方法的类)。

这是班级:

class FieldReqAndCssClass
{
public function fieldReq($parentEntity, $field, $projectID)
    {
    $required = array();
    $required['required'] = false; //do stuff on the database instead of setting it to false hardcoded
    return $required;
    }

public function fieldCssClass($parentEntity, $field, $projectID)
    {
    $cssClass= array();
    //do stuff on the database instead of setting the class as hidden hardcoded
    //$cssClass['class'] = ' hidden';
    $cssClass['class'] = '';
    return $cssClass;
    }
}

当然,以我的形式,我必须:

public function __construct(\AppBundle\Util\FieldReqAndCssClass $fieldReqAndCssClass)
{
$this->vr = $fieldReqAndCssClass; // vr stands for visibility and requiredness
}

这是两项服务:

app_bundle.field_req_and_css_class:
    class: AppBundle\Util\FieldReqAndCssClass
    arguments: []

app_bundle.form.type.projectdetail:
    class: AppBundle\Form\Type\ProjectDetailFormType
    arguments: [@app_bundle.field_req_and_css_class]
    tags:
        - { name: form.type, alias: ProjectDetail }

当然,在第一个服务中,我需要注入实体管理器并将其添加到构造中,也可能在表单服务中,但基本框架正在工作:)

我是一个快乐的人:)

编辑 上面的唯一问题是它隐藏了小部件而不是标签。要修复它:

->add('background', 'textarea', array_merge($vr->fieldReq($myClass,
'background', $project), array('label_attr' => $vr->fieldCssClass($myClass, 
'background', $project),'attr' => array_merge(array('rows' => 4, ), 
$vr->fieldCssClass($myClass, 'background', $project) ) ))) 

显然在我必须声明之前:

$myClass = get_class($this);
$vr = $this->vr;
© www.soinside.com 2019 - 2024. All rights reserved.