Customize knp-menu-template in Symfony2 - symfony

I have a problem with customizing knp-menu template.
I simply extent the knp_menu.html.twig like in this site is explained.
If I try it like this I get this error:
My knp_menu.html.twig looked like this:
{% extends 'knp_menu.html.twig' %}
{% block linkElement %}{% import _self as knp_menu %}
<a href="{{ item.uri }}"{{ knp_menu.attributes(item.linkAttributes) }}>{{ block('label') }}</a>
{% endblock %}
I try to render the template like this:
{{ knp_menu_render('MainShowBundle:Builder:mainUserMenu', {'template': 'MainShowBundle:Menu:knp_menu.html.twig'}) }}
I hope someone can help me.
Thanks.
Michael

You need to import the macros from the parent template before you can use them.
{% block linkElement %}
{% import 'knp_menu.html.twig' as knp_menu %}
<a href="{{ item.uri }}"{{ knp_menu.attributes(item.linkAttributes) }}>
<span>{{ block('label') }}</span>
</a>
{% endblock %}
I already replied to this where you originally posted your question

Have you already tried clearing the cache?
php app/console cache:clear

I am working on Sonata project which is Symfony based CMS like.
In the admin area, I added custom template for the menu and in that template I did:
{% extends 'knp_menu.html.twig' %}
{% block linkElement %}
{% import 'knp_menu.html.twig' as knp_menu %}
<a href="{{ item.uri }}"{{ knp_menu.attributes(item.linkAttributes) }}>
<span>{{ block('label') }}</span>
</a>
{% endblock %}
{% block spanElement %}
{% import 'knp_menu.html.twig' as knp_menu %}
<a href="{{ item.uri }}"{ knp_menu.attributes(item.linkAttributes) }{ block('label') }</a>
{% endblock %}
Note that you might need to add "spanElement" as well as "linkElement".
Full template implementation https://github.com/sonata-project/sandbox-build/blob/2.4/vendor/knplabs/knp-menu/src/Knp/Menu/Resources/views/knp_menu.html.twig

Related

Reuseable blocks inside of custom form themes in symfony

I want to call a custom block inside an overwritten theme-block:
{% block file_widget %}
{% if image is not null %}
{{ block('imagePreview') }}
{% endif %}
{{ block('form_widget') }}
{% endblock %}
{% block imagePreview %}
<img src="{{ image.getFullPath | imagine_filter('medium_square') }}"
alt="{{ image.filename }}"/>
{% endblock %}
The imagePreview is not shown.
But it is working when I don't use a block.
And it is also working when I dont use a FormTypeExtension and create an ImageType instead.
So I guess the file_widgetblock still has the scope of the parent form_div_layout.html.twig and there in fact no imagePreview block exists.
So how can I solve this.
I mean now I solved it by removing the block.
But I just want to know if someone has a solution to this.
Maybe there is a way for using reuseable blocks inside of custom form themes in symfony?
Finally I found the solution:
I just did not 'use' the base template explicit.
The form theme worked without this - because symfony falls back the the base form theme when it does not find a block inside the new theme file.
But it seems then you also can not use custom blocks inside this new theme file.
So this works now:
{% use 'form_div_layout.html.twig' %}
{% block file_widget %}
{% if image is not null %}
{{ block('imagePreview') }}
{% endif %}
{{ block('form_widget') }}
{% endblock %}
{% block imagePreview %}
<img src="{{ image.getFullPath | imagine_filter('medium_square') }}"
alt="{{ image.filename }}"/>
{% endblock %}

symfony's form_errors displays list item instead of just text

[ Symfony 4 ]
I've this template code in Symfony:
{{ form_widget(registrationForm.username, {'attr': {'class': 'form-control'}}) }}
{{ form_errors(registrationForm.username) }}
Instead of just displaying error text, it's generating a list item like this:
<ul><li> Username already exists </li></ul>
How to not have it generate this list item and just get the text?
I guess it is correct behavior, cause you can have multiple errors for one field for example "Username is too short" and "Field Username contains inappropriate characters", but to get only first error you can use:
{{ form_errors(registrationForm.username|first) }}
Or you can customize your form_errors rendering, first create file for form_errors, for example your_form/custom_form_errors.html.twig :
{% block form_errors %}
{% spaceless %}
<div class="error">{{ errors|first }}</div>
{% endspaceless %}
{% endblock %}
And after that include it to your view file:
{% form_theme form 'your_form/custom_form_errors.html.twig' %}
...
{{ form_errors(registrationForm.username) }}
just to extend #Andrii Filenko 's answer. You can modify the output the form_errors or any other form twig function pretty easily. it's called custom theming in Symfony.
Consider this:
// templates/register.html.twig
{% extends "base.html.twig" %}
{% form_theme registrationForm _self %}
{% block form_errors %}
{% spaceless %}
{% if errors|length > 0 %}
<ul class="changed list">
{% for error in errors %}
<li>{{ error.message }}</li>
{% endfor %}
</ul>
{% endif %}
{% endspaceless %}
{% endblock form_errors %}
{% block body %}{% endblock %}
Output:
<ul class="changed list"><li> Username already exists </li></ul>

Control the way form validation errors are displayed in Symfony2

How do I globally change the way form validation errors are displayed in Symfony2? For example, if I want to wrap each one of my error messages in a <span class="error"> or something like that, how would that be done?
Note: I'm aware of this question/answer, but I'm not sure that it's the same question as mine, and I don't understand how to apply the selected answer.
Take a look at the docs: custom global theme, customizing error output
{# SomeBundle:Layout:fields.html.twig #}
{% block field_errors %}
{% spaceless %}
{% if errors|length > 0 %}
<span class="error">
{% for error in errors %}
{{ error.messageTemplate|trans(error.messageParameters, 'validators') }}<br />
{% endfor %}
</span>
{% endif %}
{% endspaceless %}
{% endblock field_errors %}
{# In your form template #}
{% form_theme form 'SomeBundle:Layout:fields.html.twig' %}

Symfony 2 custom themes folder

I'm designing a multi-tenant application with Symfony2, There will be common templates and each tenant could have custom templates. I would like create a theme folder like this(like wordpress with css,img,etc...) :
Themes/commons/base.twig.html
Themes/commons/css/styles.css
Themes/commons/js/script.js
Themes/tenantID/base.twig.html
Themes/tenantID/css/styles.css
Themes/tenantID/js/script.js
Perhaps I'm taking a wrong way...?
Any suggestion ?
Thanks.
There is nothing wrong with your design. I may name "commons" as "default" but thats up to you. Approach with tenantid looks good to me. Whats your question?
https://github.com/fabpot/Twig/issues/17 - no dynamic inheritance
LiipThemeBundle might be a solution: http://symfony2bundles.org/liip/LiipThemeBundle
You can achieve all this by following symfony standard . because if you follow structure you will make full stack full site in frame work and you can also learn how to use frame work.
like in
bundle folder:
userbulndle/css
userbulndle/js
adminbundle/css etc
and use theme forming
{% block gender_widget %}
{% spaceless %}
{% if expanded %}
{% for child in form %}
<div class="radio_ele">
{{form_widget(child) }}
{{form_label(child) }}
</div>
{% endfor %}
{% else %}
{{ block('choice_widget') }}
{% endif %}
{% endspaceless %}
{% endblock %}
{# ----------------------------------------------------------- #}
{% block field_errors %}
{% spaceless %}
{% if errors|length > 0 %}
<div class="error_list">
{% for error in errors %}
{{ error.messageTemplate|trans(error.messageParameters, 'validators') }}
{% endfor %}
</div>
{% endif %}
{% endspaceless %}
{% endblock field_errors %

How to customize a CollectionType() item?

This ยง of the Symfony2 documentation shows an awesome technique for customizing an individual field. I'm using it a lot but there is one particular Type for which I'm having a hard time doing the customization : the CollectionType() Customizing the collection itself is quite easy, you can do something like this:
{% block _mynamespace_mybundle_mytype_mycollectionfield_row %}
{% if prototype is defined %}
{% set attr = attr|merge({'data-prototype': form_widget(prototype) }) %}
{% endif %}
{% spaceless %}
<ul {{ block('widget_container_attributes') }}>
{% spaceless %}
{{ form_errors(form) }}
{% for child in form %}
<li>
{{form_widget(child)}}
</li>
{% endfor %}
{% endspaceless %}
{{ form_rest(form) }}
</ul>
{% endspaceless %}
{% endblock %}
But how can you customize each element of the collection ? And how can you customize the data-prototype using Twig (the data-prototype is a special attribute used to add new items with js)?
I tried doing something like this (for the data-prototype):
{% block _mynamespace_mybundle_mytype_mycollectionfield_$$name$$_row %}
customization ok!
{% endblock %}
But I get errors, because I don't know how to escape the $
Regarding the items, I tried many things:
{% block _mynamespace_mybundle_mytype_mycollectionfield_item_subfield_row %}
customization ok!
{% endblock %}
{% block _mynamespace_mybundle_mytype_mycollectionfield_element_subfield_row %}
customization ok!
{% endblock %}
None of them work.
I asked the question in symfony's bug tracker, and it seems there is no solution, but a good workaround is creating a custom type for each subfield you want to customize. See this issue

Resources