我有一个带2个输入的单选按钮表单
$builder->add('intakeyear', ChoiceType::class, array(
'choices' => array(
'2017' => 2017,
'2018' => 2018,
),
'expanded' => true,
'multiple' => false,
'label' => 'Intake Year',
));
和枝条
<div class="col-sm-3">{{ form_widget(form.intakeyear) }}</div>
这会将表单呈现为
<input />
<label>2017</label>
<input />
<label>2018</label>
但我想将{{ form_widget(form.intakeyear) }}
分成以下各个选项:
{{ form_widget(form.intakeyear/choice_1/) }}
{{ form_widget(form.intakeyear/choice_2/) }}
这样我就可以将bootstrap类radio-inline
添加到标签标签中,并将最终的html输出作为:
<label class="radio-inline"><input />2017</label>
<label class="radio-inline"><input />2018</label>
有什么想法吗?
修改
以下是我得到的输出的快照:
为了更好地理解这里是我的代码:
index.html.twig
:
{% extends 'base.html.twig' %}
{% block stylesheets %}
{% stylesheets '@AppBundle/Resources/public/css/bootstrap.min.css' filter='cssrewrite' %}
<link rel="stylesheet" href="{{ asset_url }}" />
{% endstylesheets %}
{% endblock %}
{% block body %}
<nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#myNavbar">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">EPITA</a>
</div>
<div class="collapse navbar-collapse" id="myNavbar">
<ul class="nav navbar-nav">
<li class="active"><a href="#">Home</a></li>
<li><a href="#">Page 1</a></li>
<li><a href="#">Page 2</a></li>
<li><a href="#">Page 3</a></li>
</ul>
<form class="navbar-form navbar-left">
<div class="input-group">
<input type="text" class="form-control" placeholder="Search">
<div class="input-group-btn">
<button class="btn btn-default" type="submit">
<i class="glyphicon glyphicon-search"></i>
</button>
</div>
</div>
</form>
<ul class="nav navbar-nav navbar-right">
<li><a href="#"><span class="glyphicon glyphicon-user"></span> Sign Up</a></li>
<li><a href="#"><span class="glyphicon glyphicon-log-in"></span> Login</a></li>
</ul>
</div>
</div>
</nav></br></br></br>
<div class="container-fluid">
<div class="row">
<div class="col-sm-4">
<h2>Candidate Application</h2>
</div>
</div></br>
{{ form_start(form, {'attr': {'class': 'form-horizontal'}}) }}
<div class="row form-group">
<div class="col-sm-3">{{ form_label(form.name,'Name' ,{'attr': {'class': 'sr-only'}}) }}</div>
<div class="col-sm-3">{{ form_widget(form.name, {'attr': {'class': 'form-control'}}) }}</div>
<div class="col-sm-6">{{ form_errors(form.name) }}</div>
</div>
<div class="row form-group">
<div class="col-sm-3">{{ form_label(form.programtype) }}</div>
<div class="col-sm-3">{{ form_widget(form.programtype, {'attr': {'class': 'form-control'}}) }}</div>
<div class="col-sm-6">{{ form_errors(form.programtype) }}</div>
</div><br/>
<div class="row form-group">
<div class="col-sm-3">{{ form_label(form.programofinterest) }}</div>
<div class="col-sm-3">{{ form_widget(form.programofinterest, {'attr': {'class': 'form-control'}}) }}</div>
<div class="col-sm-6">{{ form_errors(form.programofinterest) }}</div>
</div><br/>
<div class="row form-group">
<div class="col-sm-3">{{ form_label(form.desiredintake) }}</div>
<div class="col-sm-3">{{ form_widget(form.desiredintake, {'attr': {'class': 'form-control'}}) }}</div>
<div class="col-sm-6">{{ form_errors(form.desiredintake) }}</div>
</div><br/>
<div class="row form-group">
<div class="col-sm-3">{{ form_label(form.intakeyear) }}</div>
<div class="col-sm-3">{{ form_widget(form.intakeyear, {'label_attr': {'class': 'radio-inline'}}) }}</div>
<div class="col-sm-6">{{ form_errors(form.intakeyear) }}</div>
</div><br/>
<div class="row">
<div class="col-sm-offset-3 col-sm-12">{{ form_row(form.save, {'attr': {'class': 'btn btn-primary'}}) }}</div>
</div>
{{ form_end(form) }}
</div>
{% endblock %}
{% block javascripts %}
{% javascripts '@AppBundle/Resources/public/js/jquery-3.2.1.min.js' %}
<script src="{{ asset_url }}"></script>
{% endjavascripts %}
{% javascripts '@AppBundle/Resources/public/js/NewCandidate.js' %}
<script src="{{ asset_url }}"></script>
{% endjavascripts %}
<script src="{{ asset('bundles/fosjsrouting/js/router.js') }}"></script>
<script src="{{ path('fos_js_routing_js', { callback: 'fos.Router.setData' }) }}"></script>
{% javascripts '@AppBundle/Resources/public/js/bootstrap.min.js' %}
<script src="{{ asset_url }}"></script>
{% endjavascripts %}
{% endblock %}
NewCandidate.js
:
//on page load do the following
$(document).ready(function () {
//when the program type value changes do the following
$("#candidate_programtype").change(function () {
//get the program type element
var program_type_element = document.getElementById("candidate_programtype");
//get the program type value
var program_type = program_type_element.options[program_type_element.selectedIndex].value;
//initiate the ajax call
$.ajax({
type: "POST",
url: Routing.generate('homepage'),
contentType: 'application/x-www-form-urlencoded',
//send the program_type_id and flag to the server
data: {program_type_id: program_type, flag: 'program_type'},
//on successfull ajax call do the following
success: function (result, status, xhr) {
//parse the result and save it in pi_arr
var pi_arr = JSON.parse(result);
//remove all the options from the programofinterest select element
$("#candidate_programofinterest").empty();
//loop through the array pi_arr['pi'] one by one
for (var i in pi_arr['pi']) {
//add the option with value i and text pi_arr['pi'][i]
$("#candidate_programofinterest").append($("<option/>", {"value": i, "text": pi_arr['pi'][i]}));
}
//remove all the options from the desiredintake select element
$("#candidate_desiredintake").empty();
//loop through array pi_arr['di'] one by one
for (var i in pi_arr['di']) {
//add the option with value i and text pi_arr['di'][i]
$("#candidate_desiredintake").append($("<option/>", {"value": i, "text": pi_arr['di'][i]}));
}
},
//on unsuccessfull ajax call do the following
error: function (xhr, status, error) {
}
});
});
//when the program of interest value changes do the following
$("#candidate_programofinterest").change(function () {
//get the program of interest element
var program_of_interest_element = document.getElementById("candidate_programofinterest");
//get the program of interest value
var program_of_interest = program_of_interest_element.options[program_of_interest_element.selectedIndex].value;
//initiate the ajax call
$.ajax({
type: "POST",
url: Routing.generate('homepage'),
contentType: 'application/x-www-form-urlencoded',
//send the program_of_interest_id and flag to the server
data: {program_of_interest_id: program_of_interest, flag: 'program_of_interest'},
//on successfull ajax call do the following
success: function (result, status, xhr) {
//parse the result and save it in di_arr
var di_arr = JSON.parse(result);
//remove all the options from the desiredintake select element
$("#candidate_desiredintake").empty();
//loop through array di_arr one by one
for (var i in di_arr) {
//add the option with value i and text di_arr[i]
$("#candidate_desiredintake").append($("<option/>", {"value": i, "text": di_arr[i]}));
}
},
//on unsuccessfull ajax call do the following
error: function (xhr, status, error) {
}
});
});
//when the desired intake value changes do the following
$("#candidate_desiredintake").change(function () {
//get the program type element
var program_type_element = document.getElementById("candidate_programtype");
//get the program type value
var program_type = program_type_element.options[program_type_element.selectedIndex].value;
//get the program of interest element
var program_of_interest_element = document.getElementById("candidate_programofinterest");
//get the program of interest value
var program_of_interest = program_of_interest_element.options[program_of_interest_element.selectedIndex].value;
//get the desired intake element
var desired_intake_element = document.getElementById("candidate_desiredintake");
//get the desired intake value
var desired_intake = desired_intake_element.options[desired_intake_element.selectedIndex].value;
//initiate the ajax call
$.ajax({
type: "POST",
url: Routing.generate('homepage'),
contentType: 'application/x-www-form-urlencoded',
//send the program_of_interest_id and flag to the server
data: {program_type_id: program_type, program_of_interest_id: program_of_interest, desired_intake_id: desired_intake, flag: 'desired_intake'},
//on successfull ajax call do the following
success: function (result, status, xhr) {
//parse the result and save it in intakeyear
var intakeyear = JSON.parse(result);
//remove all the options from the intakeyear select element
$("#candidate_intakeyear").empty();
$("#candidate_intakeyear").append($("<option/>", {"value": intakeyear, "text": intakeyear}));
},
//on unsuccessfull ajax call do the following
error: function (xhr, status, error) {
}
});
});
});
CandidateType.php
:
<?php
namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Doctrine\ORM\EntityRepository;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\OptionsResolver\OptionsResolver;
class CandidateType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder->add('name', TextType::class, array());
$builder->add('programtype', EntityType::class, array(
'class' => 'AppBundle:ProgramType',
'query_builder' => function(EntityRepository $er) {
return $er->createQueryBuilder('p')
->where('p.enabled = 1')
->orderBy('p.id', 'ASC');
},
'choice_label' => 'description',
'expanded' => false,
'multiple' => false,
'label' => 'Program Type',
));
$builder->add('programofinterest', EntityType::class, array(
'class' => 'AppBundle:ProgramOfInterest',
'query_builder' => function(EntityRepository $er) {
return $er->createQueryBuilder('p')
->where('p.enabled = 1')
->orderBy('p.id', 'ASC');
},
'choice_label' => 'description',
'expanded' => false,
'multiple' => false,
'label' => 'Program of Interest',
));
$builder->add('desiredintake', EntityType::class, array(
'class' => 'AppBundle:DesiredIntake',
'query_builder' => function(EntityRepository $er) {
return $er->createQueryBuilder('p')
->where('p.enabled = 1')
->orderBy('p.id', 'ASC');
},
'choice_label' => 'description',
'expanded' => false,
'multiple' => false,
'label' => 'Desired Intake',
));
// $builder->add('intakeyear', ChoiceType::class, array(
// 'choices' => array(
// '2017' => 2017,
// '2018' => 2018,
// ),
// 'expanded' => false,
// 'multiple' => false,
// 'label' => 'Intake Year',
// ));
$builder->add('intakeyear', ChoiceType::class, array(
'choices' => array(
'2017' => 2017,
'2018' => 2018,
),
'expanded' => true,
'multiple' => false,
'label' => 'Intake Year',
'label_attr' => array('class' => 'radio-inline'),
));
$builder->add('save', SubmitType::class, array('label' => 'Submit'));
}
public function configureOptions(OptionsResolver $resolver) {
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\Candidate',
));
}
}
答案 0 :(得分:0)
您无需拆分窗口小部件。您可以通过表单定义或Twig模板本身中的label_attr选项执行此操作:
$builder->add('intakeyear', ChoiceType::class, array(
'choices' => array(
'2017' => 2017,
'2018' => 2018,
),
'expanded' => true,
'multiple' => false,
'label' => 'Intake Year',
'label_attr' => array('class' => 'radio-inline'),
));
或
{{ form_widget(form.intakeyear, {'label_attr': {'class': 'radio-inline'}}) }}