twig render controller() passes an array instead of an object - symfony

I'm trying to render a controller amd send the $from->createView() object. Now, this works in <=2.1, but I can't seem to get it to work in 2.2.
Here is the code:
EventsContoller::newAction
return $this->render('SplurginEventsBundle:SplurginEventEvents:new.html.twig', array(
'entity' => $entity,
'form' => $form->createView(),
'existingFiles'=>$existingFiles,
'editId'=>$editId,
'isNew'=>true,
));
Right now the form variable is holding an object of the form view, I verified with var_dump.
In twig:
{% render controller('JulLocationBundle:Googlemaps:placesAutocomplete' , {locationForm: form}) %}
When I go to the controller placesAutocomplete and again use var_dump, I can see that it is an array and not an object.
How can I send an object and not an array to the controller being rendered?
EDIT :
this issue was resolved , with lot's of edits .. if any one is interested in the JulLocationBundle i will provide a pull request in a few days .

try this :
{{ render(controller('JulLocationBundle:Googlemaps:placesAutocomplete' , {locationForm: form})) }}
http://symfony.com/doc/current/book/templating.html#embedding-controllers

Related

how to make modify form for list of entity in symfony

I use symfony2 framework and i have a template which shows a list of entities (for example my products ) i would like to create a single form to delete , activate/inactivate and some other actions in the lists , actually i have done it before but on that occasion i created some action(for example toggleActiveAction(Product $product)) without the use of a form, just by creating a link but i think in this approach i am in danger of Cross-site request forgery attacks,someone has suggested to create a form for each entity but i think it isn't a good way, how can i handle this?
/**
*
* #Route("/news/update/{id}", name="news_update")
*/
public function updateAction(Request $request, $id) {
//Here I call my service
$newsService = $this->get('app.news_service');
//Here I receive the Entity I want to edit
$toUpdate = $newsService->fetchById($id);
//Here I create the form that I have defined in AppBundle\Forms
$form = $this->createForm(new NewsForm(), $toUpdate);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
//Once the form is submitted my newsService updates the Entity in the database.
$newsService->update($toUpdate);
//I redirect overview
return $this->redirectToRoute('news_show', array(), 301);
}
return $this->render('default/news/updateNews.html.twig', array(
'base_dir' => realpath($this->container->getParameter('kernel.root_dir') . '/..'),
'form' => $form->createView(),
));
}
This would first bring you to a form which the user submits to save the changes.
use the same structure you use to show a list.
To show active products in the view you can use:
{% if product.active %}
{{ product.attribute }} //It will put the products attribute in the browser if it is active
{%endif%}
Here twig checks if product.active ==(=) true.
You can use it in a for loop to loop through al the products.
{% for product in products %}
//The if block could go here.
{% enfor %}

Symfony2 KnpMenuBundle - Following tutorial and came across this error

I followed this tutorial:
https://github.com/KnpLabs/KnpMenuBundle/blob/master/Resources/doc/index.md#installation
And have come across the following error:
An exception has been thrown during the rendering of a template ("Unable to generate a URL for the named route "page_show" as such route does not exist.") in /var/www/bundles/src/Acme/DemoBundle/Resources/views/Default/index.html.twig at line 4.
Is there a step I am missing here to pass something to a controller?
From link:
use Knp\Menu\FactoryInterface;
use Symfony\Component\DependencyInjection\ContainerAware;
class Builder extends ContainerAware
{
public function mainMenu(FactoryInterface $factory, array $options)
{
$menu = $factory->createItem('root');
$menu->addChild('Home', array('route' => 'homepage'));
$menu->addChild('About Me', array(
'route' => 'page_show',
'routeParameters' => array('id' => 42)
));
// ... add more children
return $menu;
}
}
To actually render the menu, just do the following from anywhere in any Twig template:
{{ knp_menu_render('AcmeDemoBundle:Builder:mainMenu') }}
Do a ./app/console router:debug - it will show you all the routes registered in your application. I am guessing page_show is not one of them.
The documentation you are using probably expects you to add your own routes/pages to the menu like this:
$menu->addChild('Home', array('route' => 'homepage'));
Where 'homepage' has to already exist. So does 'show_page'. So you need a controller somewhere that handles a request to the show_page route, or exchange show_page for a route that you have already defined in your app. Hope I made sense.
Following the tutorial exactly, this error is caused by line 25 in the file
2 // src/Acme/MainBundle/Menu/MenuBuilder.php
...
25 $menu->addChild('Home', array('route' => 'homepage'));
The tutorial code assumes that you have a route called 'homepage'. Assuming you set this up inside a custom Bundle, then a quick way to solve this problem so you can get the tutorial up and running is to go to...
// src/Acme/MainBundle/Resources/config/routing.yml
...and copy the homepage route from there (will look something like acme_main_bundle_homepage)

datagrid filter for relation object as text field (insted of dropdown) in sonata admin in symfony 2.4

I have entity 'Action' with relation to 'User'. Created Admin CRUD controller in SonataAdminBundle. Everything works fine except user filter is rendered as dropdown list. I have 8k user count and growing so you must see why this is a problem.
I want user filter to be text input and on submit to search with LIKE %username%
Right now I add user filter like this - $datagridMapper->add('user').
I know I can add filter type and field type but I am not able to find the right combination and options. Found information on http://sonata-project.org/bundles/doctrine-orm-admin/master/doc/reference/filter_field_definition.html but still no success.
Final solution
Following Alex Togo answer I used this code:
$datagridMapper->add('user', 'doctrine_orm_callback', array(
'callback' => function($queryBuilder, $alias, $field, $value) {
if (empty($value['value'])) {
return;
}
$queryBuilder->leftJoin(sprintf('%s.user', $alias), 'u');
$queryBuilder->where('u.username LIKE :username');
$queryBuilder->setParameter('username', '%'.$value['value'].'%');
return true;
},
'field_type' => 'text'
))
I needed something like this on a project. I implemented this feature using this. You can try to set the 'field_type' option to 'text' (I used 'choice' in the project I worked at) and add the querybuilder actions you need to filter.
Use doctrine_orm_choice option.
protected function configureDatagridFilters(DatagridMapper $datagridMapper)
{
$datagridMapper->add(
'module',
'doctrine_orm_choice',
[],
'choice',
[
'choices' => $this->filterModuleList
]
)
....

Symfony2 - default values in Form Collection prototype

I'm trying to get the collection prototype to have a set of default values instead of blank values. Ideally I'd like to be able to define those default somewhere either in the model class or the form definition class, but I cannot find a way to do this anywhere.
As an example:
I've created an AbstractType for my form which contains a nested collection of Person rows (relevant code shown below):
public function buildForm(FormBuilder $builder, array $options)
{
...
$builder->add('people', 'collection', array(
'type' => new PersonType(),
'allow_add' => true,
'allow_delete' => true,
'prototype' => true,
));
...
}
The PersonType class contains the following code:
public function buildForm(FormBuilder $builder, array $options)
{
$builder->add('name', 'text');
$builder->add('date_of_birth', 'date');
$builder->add('age', 'number');
// This would be great if I could do this but I can't:
//$builder->add('date_of_birth', 'date', array('empty_value' => new \DateTime(...))); // some default value defined here
}
The best I've been able to come up with so far is shown below in the view file (the code shown is used to render the collection prototype):
...
<tr>
<td> {{ form_widget(person.name) }} </td>
{# THIS DOES NOT WORK (I just get the default selected date) #}
<td> {{ form_widget(person.date_of_birth, {'value': person.date_of_birth.get('value')|default({'year':2010, 'month':10, 'day':15})} }} </td>
{# THIS WORKS (the field contains '0' instead of being empty) #}
<td> {{ form_widget(person.age, {'value': person.age.get('value')|default(0)} }} </td>
</tr>
...
It only seems to work with simple types like text and number. It doesn't work with the date type.
This anyway doesn't feel like the right approach. I should be able to define a default/empty value either in the underlying model (e.g. protected $age = 10; inside the model class), or else in the form definition (AbstractType) class (e.g. array('empty_value' => new DateTime()), but neither are currently possible.
So in summary, my question is:
How can I define default values for a model class that will be set automatically on the client when adding new items to a form 'collection' (instead of just getting blanks).
Does anyone know of a good way to do this?
In the constructor of the entity that the form is being used for, you simply set the date with a \DateTime object, like so:
class MyEntity {
private $myDate;
public function __construct() {
$this->myDate = new \DateTime('today');
}
}
You can also use \DateTime('now') or \DateTime('tomorrow'), as described in the discussion below
http://groups.google.com/group/symfony2/browse_thread/thread/18a5b20aca485dc4/e9947d0f06d6519d
Edit: Actually, this information is in the symfony2 documentation:
http://symfony.com/doc/2.0/book/forms.html#building-the-form
may be
$builder->setData(array('date_of_birth', new \DateTime(...)));
With Symfony >2.0 this is not possible.
Symfony 2.0 retrieved the values for the prototype from the underlying object so setting them in the constructor also changed the values in the prototype. However, this behavior was changed with Symfony 2.1 which removed this functionality, depraving us of the possibility of setting default values for the prototype:
I think setting a default value for the prototype is then indeed not possible right now. --webmozart, Symfony collaborator (https://github.com/symfony/symfony/issues/5087)
There is an open bug under active development which should add support for a data_prototype option. Using this option, it will be possible to supply data to prefill the prototype. However, this will probably be released no sooner than with Symfony 2.7.
As #Alexey Kosov mentioned in his comment and #Chris mentioned was going to be possible, you can now set the option 'prototype_data' => new YourEntity()
$builder
->add('your_field', CollectionType::class, [
'entry_type' => YourEntityType::class,
// ...
'prototype_data' => new YourEntity(),
])
;

How do I access the Twig path() function from a Controller?

Okay, I know I can't literally call a twig template function from a controller, but to make links, I usually do the {{ path('_routeName') }} and that's great.
However, now I want to formulate some links in the controller that will then be passed to the template via parameters like this:
$params = array(
'breadcrumbs' = array(
'Donuts' => '/donuts',
'Bearclaws' => '/donuts/bearclaws',
'Strawberry bearclaw' => null,
),
);
return $this->render('Bundle:Donut:info.html.twig', $params);
Except I don't want to hard-code those links. What I'd like is to be able to do
'Donuts' => path('_donutRoute'),
but how to reach the path method or equivalent?
If your controller is extending the Symfony2 Controller (Symfony\Bundle\FrameworkBundle\Controller\Controller) you can use the following to generate urls like this :
$this->generateUrl('_donutRoute')
If you want it with parameters use the following:
$this->generateUrl('_donutRoute', array('param1'=>'val1', 'param2'=>'val2'))
I found an alternative way to do this that I feel is equal to the one proposed by #d.syph.3r
The plan is to do:
'breadcrumbs' = array(
'Donuts' => 'donutsRoute',
'Bearclaws' => 'bearclawRoute',
'Strawberry bearclaw' => null,
)
Then in the twig template, do:
{% for name, route in breadcrumbs %}
{{ path(route) }}
The advantage here is that the Controller is not generating any HTML in this case.

Resources