How to pass a variable to a twig block in Symfony2 - symfony

I am displaying a date time widget in a web page I am developing. By default time part only show hours and minutes. I need to show seconds too.
I have found that the date time wtdget has a variable called with_seconds, but I need to pass true from the form.
This is what I have but it did not work:
{{ form_widget(edit_form.fechhoramarcada, { 'attr': {'class': 'input-text no-border'}, 'with_seconds': true }) }}
Any help will be appreciated,
Thanks
Jaime

You can change default options when you creating them.
$builder->add('fechhoramarcada', 'datetime', array(
'with_seconds' => true,
));

Related

call twig function from custom twig function

I created a custom twig function in AppExtension Class. I need to call form_label() from this new function. ¿Is it posible? I tried but does not work:
from template I call:
{{ myFunc(form.someField) }}
public function myFunc( $field )
{
$html = form_label($field);
}
The idea is to render each form field in a different order/way than the form_widget(form) twig function. The "form_label()" function it's not reconized.
Thx for any suggestion.
I feel like this is the wrong approach to handle this. Extensions are for transforming data not really to manipulate the form definition itself.
First of all the order is defined as in the form type, so you can swap those around. To render the fields differently you can use form themes, or even rendering a custom form type.
Alternatively if its a one time thing (you could also create a macro for this) you can also instead of form_widget(form) order them in the way you like.
{{ form_start(form) }}
{{ form_row(form.field3) }}
{{ form_row(form.field1, { attr: { class: 'im-different' } }) }}
{{ form_row(form.field2) }}
{{ form_end(form) }}
Or even go deeper.
{{ form_start(form) }}
{{ form_row(form.field3) }}
<div>
{{ form_label(form.field1) }}
{{ form_widget(form.field1) }}
{{ form_errors(form.field1) }}
</div>
{{ form_row(form.field2) }}
{{ form_end(form) }}
To see these functions and how they all rendered by default you can look at form_div_layout.html.twig.
I agree with Jenne van der Meer and Nico Haase that your approach isn't particularly optimal. If I had the choice, I would go a different route: Instead of rendering in your function, render in twig, then pass the result to the function (like {{ myFunc(form_label(form), form) }}). Since you omit what your function actually needs and/or does, it's hard to provide further advice. However, I'm absolutely sure, that rendering can be done in twig before or after entering your function, via a macro/block, maybe even a form theme).
However, if you really really require your function to render the form field ... the following will possibly help you. I strongly advise against doing this, there's probably a better suited solution.
The form_label function is slightly more complex than a simple function. Instead, it uses twig's compile mechanisms to generate specific php code. It will eventually call:
FormRenderer::searchAndRenderBlock(FormView $view, string $blockNameSuffix, array $variables = [])
Diving deep into the compiler, the template call form_label(form, options) would be turned into:
$this->env->getRuntime('Symfony\Component\Form\FormRenderer')->searchAndRenderBlock(
$form, 'label', $options
);
where the $this->env seems to be the twig environment. That means, to call this in your twig extension you need to have access to the proper Twig environment, and then it should already work with the recipe I just provided. Especially if you can omit the options argument, I didn't take a deeper look into how that one's assembled (but it's probably just straight forward).
So your twig function must be defined via:
public function getFunctions(): array
{
return [
new TwigFunction('myFunc', [&$this, 'myFunc'], [
'needs_environment' => true, // <--- this!
'is_safe' => ['html'],
]),
];
}
public function myFunc(\Twig\Environment $env, $field) {
// other stuff
$html = $env->getRuntime(\'Symfony\Component\Form\FormRenderer\')->searchAndRenderBlock(
$field, 'label', $options
);
return $html;
}

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>

How to apply Twig filters to form_label(form.name), e.g. 'capitalize'?

My problem concerns just applying Twig filter inside a form without getting a 500 server error. Here is the code, which is in the view 'Room/new.html.twig':
{{ form_label(form.name) }}
or
{{ form_label(form.name, 'room.name') }}
Both will output: 'nom de salle' ('room name' in French). That is because, in my translation file 'messages.fr.yml', I have:
room.name: "nom de salle"
Also, I activated the translation in my form type 'RoomType.php' with this code:
->add('name', 'text', array(
'label' => 'room.name'
))
I tried every possible combination I thought of with |capitalize and got either a 500 server error or no change at all. Some examples:
{{ form_label(form.name)|capitalize }}
{{ form_label(form.name, 'room.name'|capitalize) }}
and so many more...
Does anyone know how to do it, it doesn't seem to be in the Symfony doc. Of course, I thought about duplicating the translation to have one in lower case and one starting with a capital letter but that would defeat the object. Plus there are other Twig filters I would like to use with this form_label() function.
Help greatly appreciated, thank you.
I just found the solution. It's so easy that it is embarrassing. I thought I didn't need the |trans as it was already translated but without it, 'room.name' = 'nom de salle' would transform to 'Room.name' instead of 'Nom de salle'. So the correct code is just:
{{ form_label(form.name, 'room.name'|trans|capitalize) }}

Symfony2 Form Anchors

I have a number of forms on the one page under different tabs
After the form is processed, I would like to return to the same tab as the form was sent from.
Basically, I would like to modify the target_route to go to the current page with an Anchor at the end of the URL. (EG company/view/6#editdetails)
Could someone provide or link to an example that I can put in my controller or into twig?
The answer is simply:
$form = $this->createForm(new ContactType($contact), $contact, array(
'method' => 'POST',
'action' => '#editdetails'
));
You may also set this in the template itself as an attribute. See example:
{{ form_start(form, {attr: { novalidate: "novalidate", class: 'requiredStar', action: '#form' }}) }}

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