Add class to content field (link) in drupal - drupal

I want to add a class to the <a>-Tag of a Field that consists of a URL-link and a link text (it's a field of type "Link") and the name of the field is content.field_c_button_link
So with twig in my HTML-File I want to have something like this:
{{ content.field_c_button_link.0.addClass('button blue') }}
How can I add a class properly?

Why not piece the anchor tag together manually? That way you have complete control over everything. Something like this in your template
{{content.field_url.0['#title']}}

Ok, this is horrible but it's the only way I found to get this to work:
If you look at the default drupal build array for your link you should see that content.field_c_button_link.0 is an array(4)
'#type' => string(4) "link"
'#title' => string(15) "Big Blue Button"
'#options' => array(0)
'#url' => object Drupal\Core\Url(11)
So, to set classes directly on the <a> tag we have to load '#options' (which is presently empty) with the right setup of subarrays
'#options' => array(1)
'attributes' => array(1)
'class' => array(2)
string(6) "button"
string(4) "blue"
The only way I could find to do this within twig was to use a series of temps and merging them with the original array because twig wouldn't parse anything else I tried:
{% set temp = {'attributes': {'class': ['button','blue']}} %}
{% set temp2 = content.field_c_button_link.0 %}
{% set temp2 = temp2|merge({'#options': temp}) %}
{% set temp3 = content.field_c_button_link|without('0') %}
{% set temp3 = temp3|merge({'0': temp2}) %}
{% set content = content|merge({'field_c_button_link': temp3}) %}
Note the |without which is a Drupal/twig filter. I had to use it to remove the empty '0' element to avoid having the link print twice.
Please tell me there is an easier way.

Related

How to replace a placeholder string stored in an object/array property in a Drupal Twig template with the current year?

I have a custom block which returns an array with a text-field.
How can I replace the string %current_year% in the #text property of the array with the current year in my twig template?
'0' => array(4)
'#type' => string(14) "processed_text"
'#text' => string UTF-8(119) "The current year is %current_year%."
I'm assuming your array/object is passed to the template as the variable myObject.
You can render the string in the #text property while replacing the placeholder as follows:
{{ attribute(myObject, '#text') | replace({"%current_year%": ("now"|date("Y"))}) }}
... or use an intermediate variable ...
{% set currentYear = "now"|date("Y") %}
{{ attribute(myObject, '#text') | replace({"%current_year%": currentYear}) }}

Sort direction in each column in Sonata Admin

In the list view, when I first click in the sort button, the default direction is ASC for all the fields. Is there any way to set the direction for each field? Something like:
$listMapper
->add('name', null, [
'sort_order' => 'ASC'
])
->add('date', null, [
'sort_order' => 'DESC'
])
Well, I managed to make it work although it's not very fancy. In the SonataAdminBundle/views/CRUD/base_list.html.twig template, right after the sort parameters are created
{% set sort_parameters = admin.modelmanager.sortparameters(field_description, admin.datagrid) %}
I added this code:
{% set sortFilters = sort_parameters['filter'] %}
{% set sortFilters = sortFilters|merge({'_sort_order': field_description.options._sort_order}) %}
{% set sort_parameters = sort_parameters|merge({'filter': sortFilters}) %}
now the only thing I have to do is tell the field in the Admin the sort_order, like this:
$listMapper->
->add('sent', null, [
'_sort_order' => 'DESC',
...
there is no need to put ASC, since it's the default value.
As I said before: not fancy nor I like it very much, but it works for me.

Symfony - pass custom data from Form Builder to form theme

I would like to set a special div surrounding a bunch of my fields. For that I want to add something to the form builder that I could detect in my form_theme, and set the div when it's there.
I tried to add
->add('field', new myCustomType(), array('inherit_data' => true, "label" => false, "required" => false, 'attr' => array("test" => "aaa")))
to the form builder, setting an custom attr, it's actually rendered in the html as an attribute... But I'm unable to detect it in the form theme.
{{ block('widget_container_attributes') }}
Only gives the widget attributes, and
{{ block('row_container_attributes') }}
doesn't work. I actually have a hard time finding any source online about what variables are available in the blocks of the form theme and how to use them (it was already difficult to know how to call blocks).
I looked for some more information on the official site, here mostly but without any success...
Thanks ahead for any help !
If you put it in your form builder, then you might as well permanently set in your template. If there is some logic required to set the data, then that belongs in your controller anyway, so just put it there to start with.
Controller:
public function someAction()
{
// ....
return $this->render('some_twig_template.twig.html', array(
'attr' => array("test" => "aaa")
);
}
Then in your twig template
{{ dump(attr) }}
{{ dump(attr.test) }}
EDIT:
To render in your template every time, you can set a class on the rendered field directly:
{{ form_label(form.field, 'My label', { 'label_attr': {'class': 'js-hidden-row'} }) }}
{{ form_widget(form.field, { 'attr': {'class': 'js-hidden-row'} }) }}
Then in my javascript you can hide with some simple jQuery:
<script>
jQuery(document).ready(function() {
$('.js-hidden-row').hide();
});
</script>

Grouped checkboxes in Symfony / twig

I have 2 entities: Projects and Categories. I have a ManyToMany relation between these two.
The Categories has ManytoOne relation with the entity "industry"
At this moment, there is no direct relation between Projects and industry and I would like to keep this like so, for further search functionality. So in the category table, the list includes categories from all industries.
When I build the form to edit the project (using the form widget), I have a list of checkboxes representing all the categories listed in my category table.
I would like to group the category choices by industry. How can this be done on the form layout only? How can I extract the industry value from the twig widget form data and group the checkboxes by the industry entity?
Thanks Leevi,
I could not find how to implement the suggestion above using both industry and category related entities... I finally found this way of going around the issue, tell me if there is a simpler way, but this works perfect now.
This is my form in the controller
$form = $this->createFormBuilder($project)
->add('categories', 'entity', array(
'class' => 'ACMEProjectBundle:Category',
'property' => 'name',
'expanded' => true,
'multiple' => true,
->getForm();
I also pass to the rendered form the array of industries which has each a list of related categories
$industries = $this->getDoctrine()->getManager()->getRepository('ACMEProjectBundle:Industry')->findall();
In the form.html.twig template
{{ form_errors(form) }}
<form method="post" {{ form_enctype(form) }}>
{% for industry in industries %}
<h4>{{industry.name}}</h4>
<ul class="unstyled">
{% for category in industry.categories %}
{% set key = category.id %}
<li>{{ form_widget(form.categories[key]) }}{{category.name}}</li>
{% endfor %}
</ul>
{% endfor %}
{{form_rest(form)}}
Which gives me the wanted results.
Hopefully this will be enough direction without giving you exact code examples :).
You'll have to setup your form with an expanded, multiple, entity field like so:
<?php
// src/Acme/ProjectBundle/Controller/DefaultController.php
namespace Acme\ProjectBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Acme\ProjectBundle\Entity\Project;
use Symfony\Component\HttpFoundation\Request;
class DefaultController extends Controller
{
public function newAction(Request $request)
{
// create a project and give it some dummy data for this example
$project = new Project();
$form = $this->createFormBuilder($project)
->add('categories', 'entity', array(
'expanded' => true,
'multiple' => true,
'group_by' => 'industry.title'
))
->add('save', 'submit')
->getForm();
return $this->render('AcmeProjectBundle:Default:new.html.twig', array(
'form' => $form->createView(),
));
}
}
The group_by parameter groups the options based on the property path:
See: http://symfony.com/doc/current/reference/forms/types/entity.html#group-by
Now group_by renders a select tag but you should be able to override that with a custom twig theme or manually in the template.
Given the form above you can access the choices in {{ form.categories.vars.choices }} and iterate over them manually.
See: {% block choice_widget_collapsed %} in form_div_layout.html.twig to see how the select box is rendered.
Here's some more information of form theming: http://symfony.com/doc/current/cookbook/form/form_customization.html

Format for time display?

I am making application with symfony2 and sonata-admin bundle.
public function configureListFields(ListMapper $listMapper)
{
$listMapper
->addIdentifier('id')
->add('fromDate');
it shows time like this
September 1, 2013 02:00
so I changed
- ->add('fromDate');
+ ->add('fromDate',null,array('format' => 'yyyy-MM-dd HH:mm:ss'))
but it still show the same.
please give me how to use format for time display?
Try using
->add('fromDate','datetime',array('date_format' => 'yyyy-MM-dd HH:mm:ss'))
By the way, the relevant code is here. I think your format option gets overwritten by the system, so it's important to use date_format instead. For an application-wide solution, have a look at this question too.
If you use SonataIntlBundle then date formats are:
$list->add('createdAt', 'date', array(
'pattern' => 'yyyy-MM-dd',
))
described in https://docs.sonata-project.org/projects/SonataIntlBundle/en/3.x/reference/datetime/#php-usage
and its formats here: https://www.php.net/manual/en/class.intldateformatter.php
Nothing from the above had worked for me, so I ventured to inspect the page source, which pointed me towards template used:
<!-- START
fieldName: date
template: SonataAdminBundle:CRUD:list_date.html.twig
compiled template: SonataAdminBundle:CRUD:list_date.html.twig
-->
<td class="sonata-ba-list-field sonata-ba-list-field-date" objectId="1">11.03.17</td>
<!-- END - fieldName: date -->
And after inspecting the template I've found the correct option filed name:
{%- elseif field_description.options.format is defined -%}
So I made my Admin code like this
->add('date', null, ['format' => 'd/m/Y'])
and it worked.
Note that format is the regular date() format, and one have to use just a single placeholder mark, like y for year, as yyyy produces 2017201720172017.
I know it's an old thread, but I hope it will help someone...
Try to add this, like carzogliore said (but quotes are missed from datetime):
->add('fromDate', 'datetime', array('format' => 'yyyy-MM-dd HH:mm:ss'))
You have to indicate that "DateTime" is the type you watn to use and then use the format key, for instance:
->add('fromDate',datetime,array('format' => 'yyyy-MM-dd HH:mm:ss'))
Internally, Sonata will use list_datetime.html.twig as you are refering "Datetime" as type and that contains format options. Below you can see the list_datetime.html.twig sonata base implementation:
{% extends admin.getTemplate('base_list_field') %}
{% block field %}
{%- if value is empty -%}
{%- elseif field_description.options.format is defined -%}
{{ value|date(field_description.options.format) }}
{%- else -%}
{{ value|date }}
{%- endif -%}
{% endblock %}
my 'problem' was different.
Because I have the sonata intl bundle active, it uses it to format the datetime list.
->add('startAt', 'datetime', array(
'dateType' => IntlDateFormatter::LONG,
'timeType' => IntlDateFormatter::SHORT
))
In the modern versions of Sonata I have managed to make it work like this:
$listMapper->add('dateadd', 'datetime', array('format' => 'y-m-d H:m:s'));

Resources