Get option values of multiple selected from form - symfony

I make the form using this code:
$builder
->add('person','entity',array(
'class'=>'MyBundle:Person',
'multiple' => true,
'empty_value' => 'None',
'required'=>false,
'mapped'=>false));
And as a result I get this html:
<select id="mybundle_person_person" multiple="multiple" name="mybundle_person[person][]">
<option value="1">Surname1</option>
<option value="5">Surname2</option>
<option value="6">Surname3</option>
<option value="11">Surname4</option>
<option value="19">Surname5</option>
</select>
Here, the value "option value" (1,5,6,11,19) corresponds to the data fields "Id" from the table (from the entity) "Person".
Yet it's OK.
When processing the form in Controller I want to get these option'svalues of selected items.
For example, were selected items "Surname2", "Surname3", "Surname5" and I want to get values "2", "6", "19".
My question is how to do it?
If I use this code
if ($form->isValid()) {
$per = $form->get('person')->getData();
$logger=$this->get('logger');
foreach($per as $key => $value){
$logger->info('person: key='.$key.' value='.$value);
}
in variable $key gets the number of the order 0,1,2,... (array indexes).
But this is not what I need.

If you have created a form by using entity and person field is a mapped property of YourEntity like
$form = $this->createFormBuilder(new YourEntity());
Then you can simply call the getter of your property like
if ($form->isValid()) {
$persons=$form->getData()->getPerson();
echo '<pre>';print_r($persons);echo '</pre>';
}
If your form is not mapped through entity then you can get all the from request like
if ($form->isValid()) {
$requestAll = $this->getRequest()->request->all();
$persons = $requestAll['mybundle_person']['person'];
echo '<pre>';print_r($persons);echo '</pre>';
}

By this line $per = $form->get('person')->getData(); you retrieve a list of persons object and not an indexed array
So inside your loop just do $logger->info('person: key='.$value->getId().' value='.$value);

Related

Creating a Search Box without a Button in Laravel 9

I have a page with a several articles and I would like to be able to search the articles by title (words in their title not the whole title). I have created a form in a column side bar on the page. I do not want to be redirected to a new page but rather to have the search filter the articles already on the page. I have tried many different things from my internet research but nothing is working out and I think I am just not seeing something. I have only been working with Laravel for a month or two so it is entirely likely!
Form in the Blade:
<form action="{{ route('search') }}" method="get">
<div class="search-box">
<input type="submit" class="search" name="search" placeholder="Search..." value="">
</div>
</form>
Routes:
Route::get('/news', [ArticleController::class, 'grid'])
->name('news');
Route::get('/news/{article_id}', [ArticleController::class, 'article'])
->where('course', '[0-9]')->name('article');
Route::get('/news/search', [ArticleController::class, 'search'])
->name('search');
Controller:
public function search(Request $request)
{
$articles = Article::all();
$articles = $articles->where('title', 'LIKE', '%' . $request . '%')
->orderBy('created_at', 'desc')
->paginate(4);
return view('search', compact('articles'));
}
public function article($slug)
{
return view('pages/article', ['article' => Article::find($slug)]);
}
public function grid(Request $request)
{
$categories = Category::all();
$users = User::all();
$tags = Tag::all();
$all = Article::with('user')
->orderBy('created_at', 'desc')
->paginate(4);
$columns = Schema::getColumnListing('articles');
return view('pages/news', compact('categories', 'users', 'tags', 'all', 'columns'));
}

Render a choice field without form

I often need to render very simple imputs in some of my templates.
I'd like to take advantage of the twig macros & form blocks to render certain HTML inputs without involving the whole Symfony forms machinery.
For example from the controller:
$templateContext = array(
'my_input' = new FormField('my_input', 'choice', array(
'choices' => array('value1', 'value2', 'my_value'),
'value' => 'my_value',
));
);
In the template:
<div>{{ form_widget(my_input) }}</div>
would render:
<div>
<select name="my_input">
<option>value1</option>
<option>value2</option>
<option selected="selected">my_value</option>
</select>
</div>
Is there a simple way to do that ?
Eventually I would also like to be able to reuse these fields elsewhere (like we can reuse form types)
There are many ways to go about this. The easiest would be to write the plain HTML into your twig template.
<form method="post">
<div>
<select name="my_input">
<option>value1</option>
<option>value2</option>
<option selected="selected">my_value</option>
</select>
</div>
</form>
And then in your controller read the values back.
$request = $this->getRequest();
if($request->getMethod() == 'POST'){
$data = $request->get('my_input')
//Do whatever you want with $data
}
If you want you re-use the html, you can build it somewhere in your PHP and pass it into Twig whenever you need it; or you can place it in a separate twig template and read that with the {include ''} command in twig.
Here is what I finally ended up with:
Class MyInput {
public static values = array(
'value1',
'value2',
'my_value',
);
}
class MyInputType extends AbstractType
{
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'choices' => MyInput::$value,
));
}
public function getParent() { return 'choice'; }
public function getName() { return 'my_input_type'; }
}
Field type used from the controller (after having registered it as a service)
public function MyAction(Request $request)
{
$form = $this->createForm('my_input_type');
$form->handleRequest($request);
$templateContext['myForm'] = $form->createView();
// ...
}
Input rendered into the template
<div>{{ form(myForm) }}</div>
To conclude: I've not been able to render an input without the form machinery, but the actual form remains rather simple.
I found my own solution for it since i need to create subforms from existing forms.
create totally empty twig template,
add in it only {{form(form)}}
render this template render()->getContent()
do a preg replace on the result (i do it in js) formView = formView.replace(/<(.*?)form(.*?)>/, '');
Yes yes - i know that regex is not perfect so before someone says it - i say it on my own, change it for youself as it catches "form-group" classes etc as well.
This is just a showcase of my solution

symfony 2 - twig - How view more (20) fields with use "prototype"?

I want view 20 same fields (name: matchday) with use "prototype".
I have a code like this:
Form:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('matchday', 'collection', array(
'allow_add' => true,
'type' => new MatchdayType(),
))
...
}
and View (Twig):
<form action="{{ path('meet_create') }}" method="post" {{ form_enctype(form) }}>
{% for i in 1..20 %}
{{ form_widget(form.matchday.vars.prototype) }}
{% endfor %}
<p>
<button type="submit">Create</button>
</p>
</form>
but I don' know how use iteration in this code with "prototype" .
thanks
The prototype is only a model that you can use to create new fields in the form's collection, but it's not really a field per say. If you want to display 20 empty fields from the beginning, you have basically two choices:
add 20 empty 'matchday' objects in the form object in your controller before creating the form
use Javascript (jQuery) to add the fields in the view on the client side
The first solution would give something like this:
$meet = new Meet();
for ($i=0; $i < 20; $i++) {
$matchday = new MatchDay();
$meet->getMatchdays->add($matchday);
}
$form = $this->createForm(new MeetType(), $meet);
For the second solution, you have a good example in the Symfony Cookbook about form collection: http://symfony.com/doc/current/cookbook/form/form_collections.html

Symfony2 Forms: How do I create a collection of 'entity' forms

I have a one to many unidirectional relationship in my model. A User has one of many Status.
Using doctrine these are mapped as a unidirectional many-to-many with a unique constraint on one of the join columns.
I'd like to use a symfony form to select a status from the status table, submit the form and have symfony persist the relationship.
I've tried two approaches:
Using the Entity form type, however this produces an error (due to the many-to-many relationship doctrine expects to receive an instance of ArrayCollection rather than a single status object.
Using a collection entity objects. When using this approach an empty div with the id status is rendered in the form. Where as I expected a select box to appear containing status options.
Here is the code. Where am I wrong?
Entity code:
/**
* #ORM\ManyToMany(targetEntity="Status")
*/
protected $status;
Form type code:
$builder->add('status', 'collection', array(
'type' => 'entity',
'allow_add' => true,
'options' => array(
'class' => 'SunflyCoreBundle:Status',
'property' => 'name',
))
);
Form template code:
<form action="{{ path('_product_create_process') }}" method="post" {{ form_enctype(form) }}>
{{ form_widget(form) }}
<input type="submit" />
</form>
HTML Rendered on the page:
<div id="product_status" data-prototype="STUFF THAT WONT RENDER ON SO"></div>

Symfony2: entity field (html SELECT) set SELECTED item

I am using a form (filterForm) to filter entities on a twig view.
The 'filterForm' only has a field of 'entity' type. On the view it shows a HTML-SELECT-OPTIONs tag.
When the user changes the selection, the same controller is called doing the neccesary stuff to filter the entities-list.
All is working fine but I need to show the SELECT-field with the value that is filtering the list. And here is the problem, I don't know how to do it.
A bit of code of the field from the index.html.twig:
{{ form_widget(personalFilterForm.personaFiltrarMail,
{ 'empty_value': 'Todos',
'attr': {'selected': personaFiltrarMail,
'onChange': 'javascript:document.filtrado.submit()' }
}
)
}}
That code is generating this html code:
<select name="test_onebundle_type[personaFiltrarMail]" id="test_onebundle_type_personaFiltrarMail"
onchange="javascript:document.filtrado.submit()"
required="required" selected="two#mail.com">
<option value="">Todos</option>
<option value=one#mail.com">Name One</option>
<option value=two#mail.com">Name Two</option>
<option value=three#mail.com">Name three</option>
The real problem here (I think) is knowing how can I get access to the OPTIONS sub-element to set de SELECTED attribute on a concrete OPTION item.
Thanks.
=== Controller ===
Here the 'Controller'...
All four numbered 'echoes' gives me the mail: 'two#mail.com' But the SELECT html TAG is always located on the first one OPTION tag.
class HorasController extends Controller
{
/**
* Lists all Horas entities.
*
* #Route("/", name="horas")
* #Template()
*/
public function indexAction()
{
$em = $this->getDoctrine()->getEntityManager();
$personas = $em->getRepository('PtGhorgaBundle:Personal')->findAll();
$personalFilterForm = $this->createForm(new PersonalFilterType(), $personas);
$request = $this->getRequest();
$formVars = $request->request->get('pt_ghorgabundle_type');
$personaFiltrarMail = $formVars['personaFiltrarMail'];
//echo "1.- [".$personaFiltrarMail."]<br />";
if (!isset($personaFiltrarMail) || $personaFiltrarMail=="") {
$entities = $em->getRepository('PtGhorgaBundle:Horas')->findAll();
} else {
$criterio = array('persona' => $personaFiltrarMail,);
$entities = $em->getRepository('PtGhorgaBundle:Horas')->findBy($criterio);
$criterio = array('mail' => $personaFiltrarMail,);
$personaFiltrarMail = $em->getRepository('PtGhorgaBundle:Personal')->find($criterio)->getMail();
echo "2.- [".$personaFiltrarMail."]<br />";
$personalFilterForm->personaFiltrarMail = $personaFiltrarMail;
echo "3.- [".$personaFiltrarMail."]<br />";
echo "4.- [".$personalFilterForm->personaFiltrarMail."]<br />";
}
return array('entities' => $entities,
'personas' => $personas,
'personalFilterForm' => $personalFilterForm->createView(),
'personaFiltrarMail' => $personaFiltrarMail,
);
}
In your data you can set the property personaFiltrarMail to the according value.
For example in your controller :
$object = new Object();
$object->personaFiltrarMail = 'two#mail.com';
$form = $this->createFormBuilder($object);
Then render your template.
I have found it:
just belown
echo "4....." line
$data = array('personaFiltrarMail'=> $personaFiltrarMail);
$personalFilterForm->setData($data);
Regards.

Resources