Reputation: 4207
I have a ChoiceType::Type field that display some choices, and i want to add, for each choices, an input to add a price on it. I did it like this :
->add('product_price', ChoiceType::class, array(
'choices' => array(
"Product 1",
"Product 2",
),
)
The JS that add the input for each choices :
var productBoxes = $("[id^=product_]");
// Listen the checkbox to display or hide the prices inputs
productBoxes.each(function (index) {
var priceField = '<label class="control-label required" for="product_price_' + index + '">Capacité</label>' +
'<input type="text" id="product_price_' + index + '" name="product[price][]" class="form-control">';
$(this).click(function () {
if ($(this).is(':checked')) {
$(this).parent().append(priceField);
}
})
})
The javascript works, it append fields next to each choices. Now I want to send my data in an array, like this : ["Product 1" => "value of the attached field"]
But I don't know how to fetch that extra data and save it to the database.
Did someone knows how to do it ?
EDIT 1 I tried to do it with CollectionType, but don't find out how to render each CollectionType element as checkbox. Is there a way to do it this way ?
Thanks for your help !
Upvotes: 0
Views: 927
Reputation: 98
Maybe I'm wrong but I think you should dig in the ChoiceType class.
When using the basic ChoiceType, Symfony docs says :
The choices option is an array, where the array key is the item's label and the array value is the item's value
If I correctly understand your case, you want something very specific like this kind of choices :
$choices = [
'item_label' => [
'value' => 'item_value',
'price' => 'item_price'
],
'item_label2' => [
'value' => 'item_value2',
'price' => 'item_price2'
],
...
]
I can't tell you precisely which class to override but your best bet will be to take a look at :
I have two questions :
What is the data model to store the label and the price ?
What is this list for ? If it's too complicated for you to dig in the Form components, maybe you should split your process in two steps :
Upvotes: 0
Reputation: 126
I think better way is to create custom type and set additional field there.
For example:
You main form type:
$builder->add('product_price', CollectionType::class, array(
'label' => 'Prices',
'entry_type' => ProductPriceType::class
));
And ProductPriceType:
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('product', TextType::class, array())
->add('price', NumericType::class, array());
}
/**
* @param OptionsResolver @resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\SomeEntity'
));
}
I think you get product data from base. In this case you get array that contains 2 values - product and price
Upvotes: 1
Reputation: 567
In your example, the easiest way would be to add two more fields to your form. Keep them hidden with CSS (display: none), and just show them with JS (toggle class "hidden" when the choice gets un/selected)
->add('product_one_price', NumberType::class, array(
'attr' => array('class' => 'hidden')
))
->add('product_two_price', NumberType::class, array(
'attr' => array('class' => 'hidden')
))
An alternative would be to have nested forms, or to build the form dynamically which may or may not be overkill, depending on what you're actually doing
Upvotes: 1