Table sheet like data in symfony2 form - symfony

I need to have this type of data in my form :
value11, value12, value13 ...
value21, value22, value23
value31, value32, value33
value41, value42, value43
...
This is how the form should look like :
Is there any form type that can do that automatically or the form must be created manually? There is collection type but its seems cant fit in my case. I am planing to serialize data from this table sheet and story it to single db table column (single property of entity class).
Is there any better way to store table sheet data type presented in this example? Preserving all values in their own entity properties is not an option, because there will be plenty of table data in that form.

You should create an entity class with x , y and value properties.
x & y being unique combinations, representing the position in your matrix.
This entity does not have to be stored in your database and can only be used to generate the form.
Then create a form-collection which renders your fields in this matrix form.
Finally: use a DataTransformer to transform the collection of entities to an array as desired.
Now save the array in your database.

I have tried couple of solutions and this is best result by my opinion:
Step 1.
Creation of macro for generating tableSheet in separate twig file (for later usage in other forms).
{# in Default:form.html.twig #}
{% macro tablesheet(name, rows, colums, titles) %}
... titles header ...
{% for i in 1..rows %}
{% for j in 1..colums %}
<input name="{{ name }}_{{ i }}{{ j }}" type="text" class="flat-form" />
{% endfor %}
{% endfor %}
{% endmacro %}
Step 2.
Import macro and create tables of input fields, in add/edit template :
{% import "ProjectSomeBundle:Default:form.html.twig" as forms %}
...
{{ form_widget(form) }}
{{ forms.tablesheet('table1', 4, 3, {0:'col1', 1:'col2', 2:'col3'}) }}
{{ forms.tablesheet('table2', 7, 3, {0:'col1', 1:'col2', 2:'col3'}) }}
...
</form>
Step 3.
Create jQuery function to serialize/deserialize form (input elements with flat-form class attr in this case). For serilize I used something like this http://css-tricks.com/snippets/jquery/serialize-form-to-json/ . Serialized values are stored in single entity filed as string and saved to db like that.
How it's works :
on opening edit form, jQuery deserialized data from that entity field and loaded to tablesheet input fields. Before sending it back (post) to server values are collect and put in that same field via serialized function.

Related

Grouped view for datasets in sonata admin list view

I am wondering if there is a easy way to implement a group view for datasets grouped by its "root" element.
Lets say i have a "person" entity. Many persons can have a "root" person they belong to. So i would add a reference to the person entity itself.
Now i don't want to show every person in the flat list view. Instead i want to display only every root-person and with clicking this dataset a accordion opens with the subordinated person entities ... how is that possible?
It would also be fine without a accordion, it can be enough if the subordinated entities are indented a bit ...
Can somebody give me a clue which approach i should follow? I would be the if i can reuse the most of the sonata admin functionality, especially the templates ...
Thanks
Was solving something similar in past. Got that working in few steps:
Override first field in your Datagrid
With this code you say that you want use my_custom_template.html.twig to render this field (in your admin class).
protected function configureListFields(ListMapper $list)
{
$list->add('yourFirstField', null, ['template' => 'my_custom_template.html.twig'])
}
Enable filtering for yourFirstField
Prepare filtering for your parent field (in your admin class)
protected function configureDatagridFilters(DatagridMapper $filter)
{
$filter->add('parent');
}
Write custom template for first field
Then in your custom template you use to set up filter value on click on link.
{% extends 'SonataAdminBundle:CRUD:base_list_field.html.twig' %}
{% block field %}
{% if object.isRoot %}
{{ object.name }}
{% else %}
{{ object.name }}
{% endif %}
{% endblock %}
Later on you can override break breadcrumbs builder service (https://sonata-project.org/bundles/admin/master/doc/reference/breadcrumbs.html) and create nice path in breadcrumbs, so user can go navigate.

Regenerate current url with additional GET parameter [duplicate]

This question already has answers here:
Twig - dynamically replace GET parameter's value
(2 answers)
Closed 6 years ago.
In a Symfony 2.7 app, with Twig, I want to create generate pagination buttons.
I have a search page, with optional GET parameters :
Empty :
www.[...].com/search
Search by name :
www.[...].com/search ?name=john
Search by name and sort by relevance :
www.[...].com/search ?name=john&sort=relevance
Search by name and sort by relevance, page 2 :
www.[...].com/search ?name=john&sort=relevance&p=2
More than 10 possibles parameters, so I don't want to define a route pattern with all optional parameters.
Then, when I display the search results, I want to link next pages :
www.[...].com/search?name=john&sort=relevance &p=2
www.[...].com/search?name=john&sort=relevance &p=3
www.[...].com/search?name=john&sort=relevance &p=4
In the TWIG template I tried it so :
{% set param = app.request.get('_route_params') %}
{% if param is null %}
{% set param = {'p': page} %}
{% else %}
{% set param = param|merge({'p': page}) %}
{% endif %}
{{ page }}
But, because the optional parameters are not defined in the route, they are not in request.get('_route_params') and the link builded only define ?p=X.
Is there any other way to get queried GET parameters and to edit them creating a new url with an other p ?
In your twig template, you can use:
app.request.query.all
to get all your query parameters

Translate the value of twig variable

Is it possible to translate the value of twig variables in a template with the 'trans' tag?
Say for instance I am passing a product to my template. This product has a definition with a trans tag e.g {{ product.definition|trans }}. This definition could either be in EN or DE or some other language. How could I translate the definition.
What are you trying to do is not a good way, It would look like this:
messages.en.yml
product:
definition:
some_value1: Some value 1
some_value2: Some value 2
and in template, you would do something like this:
{% set definition_value = product.definition %}
{% set trans_definition = 'product.definition.' ~ definition_value %}
{{ trans_definition|trans }}
it'll work, if it finds the key. What if it cant find it?
That's why you should use DoctrineBehaviors from KnpLabs, which handles all the dynamic translations for you..
If {{ product.definition }} equals 'cellphone' the following should work.
message.language.yml:
'cellphone': This will work!
However if you want to map it with the 'product' key in your message file like this:
product:
'cellphone': This also works
add the key to the twig template like so:
{{('product.'~product.definition)|trans }}

Using doctrine database object in a template

I am new to Symfony and am finally beginning to understand how to query a database using a Doctrine. However, I am lost as far understanding how to use the database object content in a Twig template.
Lets say my database object contains product Id's, names, prices, for 50 different products. After I am done querying the database in the controller, I do the following, to pass the database object into the Twig template:
public function searchAction($word)
{
//query database using the $word slug and prepare database object accordingly
$dataObject; // contains query results
return $this->render('GreatBundle:Default:search.html.twig', array('word' => $word));
}
This is where I am stuck. Now I have a Twig template, I would like to pass the DB object from the controller and then print out the database data in my Twig template.
I appreciate any suggestions as to how I can accomplish this.
Many thanks in advance!
I'll respond with an example (more easier for me to explain)
You want to search something with a slug (the var $word in your example). Let's say you want to find a article with that.
So your controller :
public function searchAction($word)
{
//query database using the $word slug and prepare database object accordingly
// Search the list of articles with the slug "$word" in your model
$articleRepository = $this->getDoctrine()->getRepositoy('GreatBundle:Article');
$dataObject = $articleRepository->findBySlug($word);
// So the result is in $dataObject and to print the result in your twig, your pass the var in your template
return $this->render('GreatBundle:Default:search.html.twig', array('result' => $dataObject));
}
The twig template 'GreatBundle:Default:search.html.twig'
{% for item in result %}
{{ item.title }} : {{ item.content }}
{% endfor %}
Just look the second example in the Symfony2 Book (Sf2 Book - templating), you have to use the function "for" to parse your object (like an array in php !)
Example in your twig template :
{% for item in word %}
{{ item.id }} - {{ item.name }} - {{ item.description }}{# etc... #}<br>
{% else %}
<h2>Aoutch ! No data !</h2>
{% endfor %}
Ah, and it's not the good var in your render method (but it's was for your example !)
public function searchAction($word)
{
//query database using the $word slug and prepare database object accordingly
$dataObject; // contains query results
return $this->render('GreatBundle:Default:search.html.twig', array('word' => $dataObject));
}

writing doctrine query with symfony 2

i have two tables:
products products_images
-id -id
-name -product_id
-image_name
There is one to many relation from product to products_images table
I have created two entities with its relation defined as: Product and ProductImage
I need to get list of products and its images but the limiting the record of no of images to 1.
Currently, I did this :
$product = $this->getDoctrine()
->getRepository('TestBundle:Product');
Then in the twig template:
{% for image in product.images if loop.first %}
{% endfor %}
I used this loop to fetch one image for that product. I dont think this is efficient way to do since i have fetching all the images for that product.
What I want to do is just fetch only one image per product from the database? How can i do this ?
I'd add another method to the Product-entity, something like getThumbnail. This encapsulates the logic of which image is considered the thumbnail (i.e your view does not contain any logic of whether to display the first, last or any other product image, it just asks the product for its thumbnail):
in the view
{% if product.thumbnail %}
{{ // Output the product.thumbnail-entity }}
{% endif %}
In the entity
public function getThumbnail ()
{
return $this->getImages()->first();
}
Now, after profiling, if you're concerned that the full image collection is loaded when only a single image/product is shown, then I'd update the repository DQL to only fetch-join a single image, or make sure that the association to the images is EXTRA_LAZY

Resources