使用表单实体字段类型 (Symfony3) 在 Twig 模板中用自定义 html 包装复选框
wrap checkboxes with custom html in Twig template using form entity fieldtype (Symfony3)
当 Symfony3 呈现表单时,我想在 twig 模板中用自定义 HTML 包装复选框。
而不是这个:
<input type="checkbox" id="form_role_1" name="form[role][]" value="1" />
<label for="form_role_1">ROLE 1</label>
<input type="checkbox" id="form_role_2" name="form[role][]" value="2" />
<label for="form_role_2">ROLE 2</label>
<input type="checkbox" id="form_role_3" name="form[role][]" value="3" />
<label for="form_role_3">ROLE 3</label>
我想得到这样的东西:
<div class="input-group">
<input type="checkbox" id="form_role_1" name="form[role][]" value="1" />
<label for="form_role_1">ROLE 1</label>
</div>
<div class="input-group">
<input type="checkbox" id="form_role_2" name="form[role][]" value="2" />
<label for="form_role_2">ROLE 2</label>
</div>
<div class="input-group">
<input type="checkbox" id="form_role_3" name="form[role][]" value="3" />
<label for="form_role_3">ROLE 3</label>
</div>
在控制器动作中:
$form = $this->createForm(RolesFormType::class, $roles);
$form->handleRequest($request);
return $this->render(
'role/edit_roles.html.twig',
array(
'form' => $form->createView()
)
);
在表格中输入:
class RolesFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->add('role', EntityType::class, array(
'label' => 'form.elements.roles',
'class' => 'RoleBundle\Entity\Role',
'choice_label' => 'role_name',
'expanded' => true,
'multiple' => true
));
}
}
经典模板如下所示:
<div class="container-fluid">
<div class="row">
{{ form_start(form, {'method': "POST"}) }}
<div class="col-md-12">
<div class="form-group">
{{ form_errors(form.role) }}
{{ form_widget(form.role, {}) }}
</div>
</div>
{{ form_rest(form) }}
{{ form_end(form) }}
</div>
</div>
我在 twig 模板中尝试过这种方式,但只渲染了标签:
<div class="container-fluid">
<div class="row">
{{ form_start(form, {'method': "POST"}) }}
<div class="col-md-12">
{% for role in form.role %}
<div class="input-group">
{{ form_label(role) }}
{{ form_widget(role) }}
</div>
{% endfor %}
</div>
{{ form_rest(form) }}
{{ form_end(form) }}
</div>
</div>
是否可以不创建新的字段类型?
解决方案
关于@xabbuh 的回答,我在 How to Customize Form Rendering in Symfony 3
找到了解决方案
我在我的 Bundle 中创建了一个文件夹:
src/RoleBundle/Resources/views/form
然后我将一个新文件 (fields.html.twig
) 放入其中,其中包含此内容
{%- block choice_widget_expanded -%}
<div {{ block('widget_container_attributes') }}>
{%- for child in form %}
<div class="input-group">
{{- form_widget(child) -}}
{{- form_label(child, null, {translation_domain: choice_translation_domain}) -}}
</div>
{% endfor -%}
</div>
{%- endblock choice_widget_expanded -%}
同时我发现了另一个处理这个问题的问题:
Overriding symfony radio widget
您可以使用自定义表单主题自定义表单的呈现。您可以在项目级别执行此操作,甚至可以只针对特定表单执行此操作(有关详细信息,请参阅 How to Customize Form Rendering and How to Work with Form Themes)。
您的示例看起来需要覆盖 choice_widget
和 choice_label
当我玩symfony不是很熟练的时候,我并不经常使用这个公认的方案来解决
浏览量:
<label class="layui-form-label">所属地市:</label>
<div class="layui-inline">
<select name="{{ form.cityId.vars.full_name }}" lay-verify="" id="{{ form.cityId.vars.id }}" lay-filter="case_city">
<option value="0">请选择</option>
{% if citylist is not empty %}
{% for list in citylist %}
<option value="{{ list.id is defined ? list.id : 0 }}">{{ list.areaName is defined ? list.areaName : '' }}</option>
{% endfor %}
{% endif %}
</select>
</div>
控制器:
$caseReg = new CaseRegister();
$form = $this->createForm('Alarm\Component\Form\CaseRegisterType', $caseReg);
$form->handleRequest($request);
$citylist = $this->getDoctrine()->getRepository('AlarmComponent:OfficeArea')->findBy(array('pid'=>0,'status'=>0));
$caseType = $this->getDoctrine()->getRepository('AlarmComponent:CaseType')->findBy(array('status'=>0));
if ($form->isSubmitted()) {
$em = $this->getDoctrine()->getManager();
$param = $request->request->get('alarm_component_caseregister');
if($param['receiveId'] == 0)
{
$case = new CaseType();
$case->setCaseName($param['receiveName']);
$em->persist($case);
$em->flush($case);
$caseReg->setReceiveId($case->getId());
$caseReg->setReceiveName($case->getCaseName());
}
if($param['cityId'] != 0)
{
$city = $this->getDoctrine()->getRepository('AlarmComponent:OfficeArea')->find($param['cityId']);
$caseReg->setCityId($city);
}
if($param['subofficeId'] != 0)
{
$suboffice = $this->getDoctrine()->getRepository('AlarmComponent:OfficeArea')->find($param['subofficeId']);
$caseReg->setSubofficeId($suboffice);
}
$em->persist($caseReg);
$em->flush($caseReg);
return $this->redirectToRoute('case_register_index');
}
return $this->render('AlarmWebBundle:BackendBat\CaseRegister:new.html.twig', array(
'caseReg' => $caseReg,
'form' => $form->createView(),
'citylist' => $citylist,
'casetype' => $caseType
));
它也能解决我的问题,但是当我优化这个的时候来晚了,不然就得改了。但我希望这个答案可以解决你目前的问题。
当 Symfony3 呈现表单时,我想在 twig 模板中用自定义 HTML 包装复选框。
而不是这个:
<input type="checkbox" id="form_role_1" name="form[role][]" value="1" />
<label for="form_role_1">ROLE 1</label>
<input type="checkbox" id="form_role_2" name="form[role][]" value="2" />
<label for="form_role_2">ROLE 2</label>
<input type="checkbox" id="form_role_3" name="form[role][]" value="3" />
<label for="form_role_3">ROLE 3</label>
我想得到这样的东西:
<div class="input-group">
<input type="checkbox" id="form_role_1" name="form[role][]" value="1" />
<label for="form_role_1">ROLE 1</label>
</div>
<div class="input-group">
<input type="checkbox" id="form_role_2" name="form[role][]" value="2" />
<label for="form_role_2">ROLE 2</label>
</div>
<div class="input-group">
<input type="checkbox" id="form_role_3" name="form[role][]" value="3" />
<label for="form_role_3">ROLE 3</label>
</div>
在控制器动作中:
$form = $this->createForm(RolesFormType::class, $roles);
$form->handleRequest($request);
return $this->render(
'role/edit_roles.html.twig',
array(
'form' => $form->createView()
)
);
在表格中输入:
class RolesFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->add('role', EntityType::class, array(
'label' => 'form.elements.roles',
'class' => 'RoleBundle\Entity\Role',
'choice_label' => 'role_name',
'expanded' => true,
'multiple' => true
));
}
}
经典模板如下所示:
<div class="container-fluid">
<div class="row">
{{ form_start(form, {'method': "POST"}) }}
<div class="col-md-12">
<div class="form-group">
{{ form_errors(form.role) }}
{{ form_widget(form.role, {}) }}
</div>
</div>
{{ form_rest(form) }}
{{ form_end(form) }}
</div>
</div>
我在 twig 模板中尝试过这种方式,但只渲染了标签:
<div class="container-fluid">
<div class="row">
{{ form_start(form, {'method': "POST"}) }}
<div class="col-md-12">
{% for role in form.role %}
<div class="input-group">
{{ form_label(role) }}
{{ form_widget(role) }}
</div>
{% endfor %}
</div>
{{ form_rest(form) }}
{{ form_end(form) }}
</div>
</div>
是否可以不创建新的字段类型?
解决方案
关于@xabbuh 的回答,我在 How to Customize Form Rendering in Symfony 3
找到了解决方案我在我的 Bundle 中创建了一个文件夹:
src/RoleBundle/Resources/views/form
然后我将一个新文件 (fields.html.twig
) 放入其中,其中包含此内容
{%- block choice_widget_expanded -%}
<div {{ block('widget_container_attributes') }}>
{%- for child in form %}
<div class="input-group">
{{- form_widget(child) -}}
{{- form_label(child, null, {translation_domain: choice_translation_domain}) -}}
</div>
{% endfor -%}
</div>
{%- endblock choice_widget_expanded -%}
同时我发现了另一个处理这个问题的问题: Overriding symfony radio widget
您可以使用自定义表单主题自定义表单的呈现。您可以在项目级别执行此操作,甚至可以只针对特定表单执行此操作(有关详细信息,请参阅 How to Customize Form Rendering and How to Work with Form Themes)。
您的示例看起来需要覆盖 choice_widget
和 choice_label
当我玩symfony不是很熟练的时候,我并不经常使用这个公认的方案来解决
浏览量:
<label class="layui-form-label">所属地市:</label>
<div class="layui-inline">
<select name="{{ form.cityId.vars.full_name }}" lay-verify="" id="{{ form.cityId.vars.id }}" lay-filter="case_city">
<option value="0">请选择</option>
{% if citylist is not empty %}
{% for list in citylist %}
<option value="{{ list.id is defined ? list.id : 0 }}">{{ list.areaName is defined ? list.areaName : '' }}</option>
{% endfor %}
{% endif %}
</select>
</div>
控制器:
$caseReg = new CaseRegister();
$form = $this->createForm('Alarm\Component\Form\CaseRegisterType', $caseReg);
$form->handleRequest($request);
$citylist = $this->getDoctrine()->getRepository('AlarmComponent:OfficeArea')->findBy(array('pid'=>0,'status'=>0));
$caseType = $this->getDoctrine()->getRepository('AlarmComponent:CaseType')->findBy(array('status'=>0));
if ($form->isSubmitted()) {
$em = $this->getDoctrine()->getManager();
$param = $request->request->get('alarm_component_caseregister');
if($param['receiveId'] == 0)
{
$case = new CaseType();
$case->setCaseName($param['receiveName']);
$em->persist($case);
$em->flush($case);
$caseReg->setReceiveId($case->getId());
$caseReg->setReceiveName($case->getCaseName());
}
if($param['cityId'] != 0)
{
$city = $this->getDoctrine()->getRepository('AlarmComponent:OfficeArea')->find($param['cityId']);
$caseReg->setCityId($city);
}
if($param['subofficeId'] != 0)
{
$suboffice = $this->getDoctrine()->getRepository('AlarmComponent:OfficeArea')->find($param['subofficeId']);
$caseReg->setSubofficeId($suboffice);
}
$em->persist($caseReg);
$em->flush($caseReg);
return $this->redirectToRoute('case_register_index');
}
return $this->render('AlarmWebBundle:BackendBat\CaseRegister:new.html.twig', array(
'caseReg' => $caseReg,
'form' => $form->createView(),
'citylist' => $citylist,
'casetype' => $caseType
));
它也能解决我的问题,但是当我优化这个的时候来晚了,不然就得改了。但我希望这个答案可以解决你目前的问题。