Concat field on custom column in Sonata Admin view - symfony

I'm trying to add a custom field to the list view in Sonata Admin where it will concat a fixed string (http://www.example.com) and the field slug as seen below, so that I can access that specific product url. The column shows in the table and the link is created, but I can't figure out how to pass the slug variable to the template so that it works.
I have the following configuration:
#ProductAdmin.php
protected function configureListFields(ListMapper $listMapper)
{
$listMapper->addIdentifier('id')
->addIdentifier('name')
->add('date')
->add('slug', 'text', [
'editable' => true
])
->add('link', 'string', [
'template' => 'default/admin-link.html.twig',
])
#default/admin-link.html.twig
{% extends 'SonataAdminBundle:CRUD:base_list_field.html.twig' %}
{% block field %}
Product link
{% endblock %}

In template you can access object which holds data of current iteration from loop just call {{object.slug}} in template to access slug for particular row like
{% extends 'SonataAdminBundle:CRUD:base_list_field.html.twig' %}
{% block field %}
Product link
{% endblock %}
Or it would be better if you generate your URLs using route/path method

Related

Symfony ChoiceType deep label customization

I want to customize my EntityType's choice labels highly, like creating a table with multiple attributes of my model.
So I want to access my choices class attributes. The choices are my entities of class MyClass through the EntityType. How can I do so in twig?
Currently I do it like this:
1. in my FormClass I json_encode all fields I need in my label
2. in my template I json_decode these information and display according
IN CODE:
1.
$builder
->add('field', EntityType::class, [
'class' => MyClass::class,
'multiple' => false,
'expanded' => true,
],
'choice_label' => function (MyClass $myClass) {
$data = [
'name' => $myClass->getName(),
'description' => $myClass->getDescription(),
];
return json_encode($data);
},
])
2.
{% block my_form_widget %}
...
{# form is my 'field' FormView of the EntityType #}
{% for child in form %}
{# child is a FormView, one choice of my EntityType #}
{# child.vars.data is boolean as its a checkbox #}
{% set data = child.vars.label|json_decode %}
create some complex html here, like tables
...
{% endfor %}
...
{% endblock %}
Working. But is there a better way?
Thanks,
Kim
In a Symfony form (or form field, which is just a form of its own) that is mapped to an entity, you always have access to the underlying data in form.vars.data. So in this case, form.vars.data would either be null or an instance of MyClass.
For ease of use in your template, you might do something like:
{% set my_object = form.field.vars.data %}
{% if my_object %}
{{ my_object.getName() }}
{{ my_object.getDescription() }}
{% endif %}
Thus there is no need to re-encode your entity data for the view layer, since it's always already available.
If you are working with an EntityType and want to access the properties of each choice's entity, they are available as well in the choices array:
{% for choice in form.field.vars.choices %}
{{ choice.data.getName() }}
{{ choice.data.getDescription() }}
{% endfor %}
A nice trick when you're trying to access any form data and aren't sure where to look is to temporarily add a line to your template like:
{{ dump(form.field) }}
This will allow you to look through the available data and see what all is available. Note that it requires the Twig debug extension to be enabled, and XDebug to be enabled in PHP in order to make the output look nice.
Ok I got it, here is an example of how to access the data of your EntityType's choices in twig. You can check the child.parent.vars.choices list.
{% block my_form_widget %}
...
{# form is my 'field' FormView of the EntityType #}
{% for child in form %}
{# child is a FormView, one choice of my EntityType #}
{# child.vars.data is boolean as its a checkbox #}
{% for choice in child.parent.vars.choices if choice.value == child.vars.value %}
{{ choice.data.name }} {# contains MyClass name #}
{{ choice.data.description }} {# contains MyClass description #}
{% endfor %}
...
{% endfor %}
...
{% endblock %}

Sonata Admin List Field Template is Ignored

I'm using Symfony 4.1.1 and Sonata Admin Bundle 3.35.2.
I want to use a custom template for a field in an admin's list view. The template is ignored. I am using Twig as my templating engine.
In the admin:
# /src/Admin/ImageAdmin.php
protected function configureListFields(ListMapper $listMapper) {
$listMapper
->add('filename', 'string', ['template' => 'list_image.html.twig'])
;
}
The template:
# /templates/list_image.html.twig
{% extends 'SonataAdminBundle:CRUD:base_list_field.html.twig' %}
{% block field %}
<img src="{{ value }}" style="width: 200px" />
{% endblock %}
Should be
# /templates/list_image.html.twig
{% extends 'SonataAdminBundle:CRUD:base_list_field.html.twig' %}
{% block field %}
<div>
<img src="{{ object.filename }}" style="width: 200px" />
</div>
{% endblock %}
SRC will be just filename - not full path for file, so image will not be printed. Fix that problem also.
The other problem is that, you accesed some mystical value? I don't see where you assign value to it.
You can access getters of object by writing object.fieldname. This one works as printing getter function of your current object.
I've had same problem (Symfony 4.1), try solution from here Use custom column in Sonata Admin list
so change:
{% extends 'SonataAdminBundle:CRUD:base_list_field.html.twig' %}
to:
{% extends '#SonataAdmin/CRUD/base_list_field.html.twig' %}
it did work for me. The problem is that even if your location is right (i got to it after some experiments) and you extend the wrong template you wont get any error.
Might be a bit late but for everyone who comes across with the same problem like me - I´ve solved it by creating a specific path within twig.yaml for admin-templates, simply create a subfolder _admin or try to use 'templates/': 'admin' to keep your files where they are (haven't tested this possibility)
# /config/packages/twig.yaml
twig:
paths:
'templates/_admin/': 'admin'
# /src/Admin/ImageAdmin.php
protected function configureListFields(ListMapper $listMapper) {
$listMapper
->add('filename', 'string', ['template' => '#admin/list_image.html.twig'])
;
}

Sonata admin bundle preview image from some entity in list mapper without sonata media bundle

I was wondering how should i approach this problem. In sonata admin dashboard i have users and i would like to preview users profile pictures in thumbnails of a ListMapper. I'm new to symfony and still a bit confused trying to wrap my head around these concepts.
You need to create a custom template where you display the image of your user, i will assume that your Entity User as a Picture Entity which has a path method that gives the image URL :
picture.html.twig
{% extends 'SonataAdminBundle:CRUD:base_list_field.html.twig' %}
{% block field %}
<div>
{% if object.picture != null %}
<img src="{{ object.picture.path }}">
{% else %}
<span>No picture</span>
{% endif %}
</div>
{% endblock %}
You know have to use this template in your list
class UserAdmin extends Admin
{
protected function configureListFields(ListMapper $listMapper)
{
$listMapper
->addIdentifier('id')
->add('picture', null, array(
'template' => 'ApplicationSonataAdminBundle:User:picture.html.twig'
));
}
}
Documentation is available here : http://sonata-project.org/bundles/doctrine-orm-admin/master/doc/reference/list_field_definition.html#custom-template
one separated entity, -no user-, where I have added one media, this for me worked
in admin configureListFields
->add('media', 'string', array('template' => 'SonataMediaBundle:MediaAdmin:list_image.html.twig'))

Raw filter on Sonata Admin Bundle configureShowFields

I'm doing a project with Symfony2 and Sonata Admin Bundle.
How I can apply the filter raw of twig (to display formated text) in action configureShowFields?
I would not override Sonata templates...
The code of my configureShowFields:
protected function configureShowFields(ShowMapper $showMapper)
{
$showMapper
->add('active')
->add('title')
->add('subtitle') // I need this field with twig RAW filter
->add('description') //I need this field with twig RAW filter
->add('url')
->add('date')
->add('tags')
->add('file');
}
You can use the "safe" sonata field option as follow:
protected function configureShowFields(ShowMapper $showMapper)
{
$showMapper
->add('subtitle', null, array('safe' => true))
;
}
It will add the "raw" twig filter to your entity field.
From the base_show_field.html.twig:
{% block field %}
{% if field_description.options.safe %}
{{ value|raw }}
{% else %}
{{ value|nl2br }}
{% endif %}
{% endblock %}
You need to make a custom template.
Under:
sonata_doctrine_orm_admin:
templates:
types:
list:
array: SonataAdminBundle:CRUD:list_array.html.twig
*** other existing declarations ***
raw: MyBundle:CRUD:raw.html.twig
Then make the template that the declaration maps to, and give 'raw' as the second argument to add field. It'll then call your new template to render that field.

SonataAdminBundle custom rendering of text fields in list

I'm using symfony2 and SonataAdminBundle.
I have a simple Entity called Post in which I have content field that is basically html text (from a ckeditor for the record). I need to display in the Post list the content field as raw html, without escaping it.
Hacking base_list_field template like this
{% block field %}{{ value|raw }}{% endblock %}
works, but it's clearly not the proper way.
The solution:
I've defined a custom html type in the config.yml for sonata_doctrine_orm_admin:
sonata_doctrine_orm_admin:
templates:
types:
list:
html: MyBundle:Default:list_html.html.twig
And created the custom list_html.html.twig template in which i do not escape HTML:
{% extends 'SonataAdminBundle:CRUD:base_list_field.html.twig' %}
{% block field%}
{{value|raw}}
{% endblock %}
Now in the PostAdmin I can define the behaviour of the field in the configureListFields method:
$listMapper
->add('content', 'html')
I know it's an old post that has an accepted answer, but now you can also use the safe option to tell Symfony not to sanitize the output.
$mapper->add('content', null, [
'safe' => true,
]);

Resources