Laravel validation of input field with wildcard - wildcard

I have a form that dynamically generates input fields, for instance:
input['Supplier1],
input['Supplier2'],
input['Supplier3'],
and so on. The user can create anywhere between 1 and 10 of these input fields.
I am using Laravel's built-in validation feature, and was wondering if there's a way to validate a field with a wildcard.
In other words, instead of creating separate rules for 'Supplier1', 'Supplier2', etc., is it possible to write something along the lines of 'Supplier^' where the '^' symbol represents any given character.
The rules are currently:
public function rules()
{
return [
'Description1' => 'required|min:2',
'Supplier1' => 'canBeEmpty|exists:suppliers,SupplierName'
];
}
'canBeEmpty' is a custom rule that allows the field to be submitted empty.

If you created the 'supplier' inputs as part of an Array, you could utilize a solution like this: https://stackoverflow.com/a/33371994/613703:
Construct your inputs in the following way:
<input type='text' name='suppliers[]' value='theValue' />
<input type='text' name='suppliers[]' value='theValue' />
etc...
$validator = Validator::make($request->all(), [
'suppliers' => 'array',
// your other rules here
]);
// Here you can set the rules for each Supplier in your Array
$validator->each('suppliers', [
'id' => 'required',
'quantity' => 'min:0',
]);

Related

Reinitialize autocomplete after form submission

I have a custom autocomplete input that is not bound to any entities:
$builder
->add('input', TextType::class, [
'autocomplete' => true,
'autocomplete_url' => 'https://path-to-autocomplete',
'tom_select_options' => [
'create' => false,
'preload' => true,
'maxItems' => 1,
'delimiter' => '/',
],
])
;
The input correctly requests the autocomplete URL, fetches results, renders the correct item label, and sends the correct item value with the form.
The problem arises after submitting the form at step #6.
Empty form is rendered.
We select an item with ID 15 and label Foo.
Input is rendered correctly.
Form is submitted.
Value of 15 is sent to the server with the form.
Now we have to re-render a form again with an initial value of the input of 15.
At this point, the input value is rendered as 15 instead of Foo. That makes perfect sense. The input just doesn't know how to get a label for an item with ID 15.
Question: how do I provide the input with data about the item label?
I expected the it to have something like reverse_autocomplete_url that would be called after input initialization to get items by their IDs but I don't think there is such an option.
Considering you used symfony form.
You used $form->isValid() etc..
Persisted and flush your object.
Then instead of re-rendering the twig, call redirectToRoute function to the current route.
If you provide more detail about your usecase i can give you a better answer.
You have to initialize the form field with options array:
'tom_select_options' => [
'options' => [
[
'value' => 15,
'text' => 'Foo',
],
],
],
value and text keys are customizable via valueField and labelField properties.

Symfony 3.4 - Use array as name for input fields

I have a form, and inside this form, I need to display several dynamic fields.
My problem is I want a structure like :
<input name="my_form[PARAM1][active]" />
<input name="my_form[PARAM2][active]" />
For now, in my Form, I use a simple loop :
foreach ($options['myParams'] as $param) {
$builder->add('Param'. $param['id'] .'Active', TextType::class, [
'label' => $param['title'],
]);
}
But I don't have the structure I want. I see the option property_path in Symfony 5, but not in 3.4... I tried with CollectionType, but I am not sure it's possible with 2 nested inputs.

How can I set a value in Twig when the select is built using EntityType?

In a Form say I have a builder option like this:
->add('choice', ChoiceType::class, [
'choices' => [
'Cheese' => 'cheese',
'Plain' => 'plain
]
])
And let's say we are editing this option, in the database they've already selected plain. With twig we can write the widget like this:
{{ form_widget(BurgerForm.choice, {
'value': burger.type
}) }}
This will make the value in the database the pre-selected value for the select. But if you do the same thing with EntityType:
->add('choice', EntityType::class, [
'class' => 'AppBundle:BurgersTypes',
'choice_label' => 'type'
])
And you use the same twig it doesn't pre-select the option from the database. How can I get the value from the database to show as the pre-selected value of the widget?
Pre-selecting a value for this form means setting a value on the underlying data. In your case, the controller ought to look something like:
// src/AppBundle/Controller/MyController.php
namespace AppBundle\Controller\MyController;
use AppBundle\Entity\Order;
use AppBundle\Entity\BurgersTypes;
use AppBundle\Form\Type\FormType;
use Symfony\Component\HttpFoundation\Request;
public function formAction(Request $request)
{
$obj = new Order();
$defaultBurgerChoice = new BurgersTypes('cheese');
$ob->setChoice($defaultBurgerChoice);
$form = $this->create(FormType::class, $obj);
$form->handleRequest($request);
...
// Now, if the form needs to render a value for `choice`,
// it will have the value of BurgerForm.choice determined
// intentionally - by your default, or overridden and
// handled in the request!
return [
'BurgerForm' => $form->createView()
]
}

Symfony form add field without prefix

I want one hidden field in my symfony form without an prefix. This field stores some information I needed to recreate the form type in my listener. I dont want to iterate over all $request parameters to get the right form so I want add simple field without any prefix. This need to be handled in the form builder, because the Frontend is not part of the bundle.
Current simplified code:
$builder->add('firstName'; TextType::class);
$builder->add('lastName'; TextType::class);
// ...
// field without prefix
$builder->add('someValue', HiddenType::class, ['mapped' => false]);
Expected result:
<input type="text" name="form_name[firstName]" />
<input type="text" name="form_name[lastName]" />
<!-- ... -->
<input type="hidden" name="someValue" /> <!-- without prefix -->
The thing is I need to access it with $request->request->get('someValue'). Because my form name is dynamically I cant access the array.
Is this possible?
Yes you can. Look here
Example:
use Symfony\Component\OptionsResolver\OptionsResolver;
class TaskType extends AbstractType
{
// buildForm() method: add your fields here
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\Task',
'csrf_protection' => true,
'csrf_field_name' => 'formKey',
// a unique key to help generate the secret token
'csrf_token_id' => 'task_item',
));
}
// ...
}
LE:
I dug a little to find out more about this problem. And I failed to find a proper way to override only the name attribute for a specific form field. So I end up with:
1.
Add a new attribute name for that field, but you will end up with two name attributes, and I didn't test out to see which one will be used. I guess the first one.
{{ form_row(form.someValue, { attr:{ name:'someValue' } } }}
//This will look like:
<input type="hidden" id="category_someValue" name="category[someValue]" name="someValue" />
And if you look at the source page, you'll see the last name attribute in red color. Not so good I guess.
2.
Use, in your Type class, the getBlockPrefix() method, which will override the whole form prefix:
// AppBundle/Form/FormType.php
public function getBlockPrefix()
{
return ''; // return an empty string here
}
And now remove the attr added for your field, and put just this:
{{ form_row(form.someValue) }}
But now all the form fields, will no longer have that form_name[first_name] like name attribute, but just name="first_name". So your hidden field will have: name="someValue".
But please, let us know if you find a better solution (ideally, the proper one).
I don't know if this is possible (I guess it is not). Could your issue be fixed by using the getName() method of your FormType? Example:
// Controller
$form = $this->createForm(YourType::class, $yourObject);
// Get all parameters related to the form
$data = $request->request->get($form->getName());
// Output 'someValue'
echo $data['someValue'];

Render a field multiple times in Twig and Symfony

I need two inputs so that the user can choose from
Controller
$etud = new Etudiant();
$form=$this->createFormBuilder($etud)
->add('filierechoisit',EntityType::class,array('class'=>'inscriptionBundle\Entity\filieres', 'choice_label'=>'libelle_filiere'))
->add('filierechoisit',EntityType::class,array('class'=>'inscriptionBundle\Entity\filieres', 'choice_label'=>'libelle_filiere'))->getForm();
if ($form->isValid()) {
// ... maybe do some form processing, like saving the Task and Tag objects
}
return $this->render('inscriptionBundle:Default:authentification.html.twig', array(
'modif' => $form->createView(),
));
How can I do it?
I'm almost sure you want a ChoiceType/EntityType field with multiple and expanded options as true.
It should be something like this:
$form->add('filierechoisit', EntityType::class, array(
# query choices from this entity
'class' => 'inscriptionBundle\Entity\filieres',
# use the filieres.libelle_filiere property as the visible option string
'choice_label' => 'libelle_filiere',
# used to render a select box, check boxes or radios
'multiple' => true,
'expanded' => true,
));
You are mixing the form processing and form rendering. If you want user to choose which way he enters data - you do not want to process this data in two different ways until these are two independent fields.
You should just have one
->add('filierechoisit',EntityType::class,array('class'=>'inscriptionBundle\Entity\filieres', 'choice_label'=>'libelle_filiere'))
call to add field processing and left all rendering for the front-end side. You could use some JS, or API there, or in simple case, just override Twig template for that field
http://symfony.com/doc/current/cookbook/form/form_customization.html
You could render your own widget for your form here, allowing user to do some html stuff to change input.
Currently, making two add with identical names call just makes the second one override the first.

Resources