Use twig in asset sentence - symfony

It's possible to use a Twig result in asset sentence? See what I'm trying below:
{% for entity in entities %}
<li title="{{ entity.getName }}" data-id="{{ entity.getId }}" class="categories-first"><img src="{{ asset('bundles/dashboard/img/categories/{{ entity.getName|lower|replace("ó":"o") }}.gif') }}"></li>
{% endfor %}
But it's not loading the image since this {{ entity.getName|lower|replace("ó":"o") }} isn't evaluated, it's possible? How?
Also related to this same topic, it's possible to remove special characters from output? Let said á, é, í, ó, ú and so on?

It will work if you use twig's concatenation.
{% for entity in entities %}
<li title="{{ entity.getName }}" data-id="{{ entity.getId }}" class="categories-first"><img src="{{ asset('bundles/dashboard/img/categories/' ~ entity.getName|lower|replace({"ó":"o"}) ~ '.gif') }}"></li>
{% endfor %}

You can't put your twig result inside asset. If you put this code below
bundles/dashboard/img/categories/{{ entity.getName|lower|replace("ó":"o") }}.gif
to your asset, then the result for image source is exactly as this code above.

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 %}

Slice Twig path

I would like to delete the first occurrence of '/' in my twig path. I need it to show image in my pdf. I don't know how to deal with it and need help from someone smarter.
<p>{% path(project.mainImage), 'reference' %}</p>
Gives me:
/upload/media/img/a6ab300301dd8e5de89bac068a16aaa9e90b2a1b.jpeg
I need:
upload/media/img/a6ab300301dd8e5de89bac068a16aaa9e90b2a1b.jpeg
Ok guys, I am just stupid.
Here is the answer:
{% set rendered %}{% path project.mainImage, 'reference' %}{% endset %}
<img src="{{ rendered|replace({'/upload':'upload'}) }}">
Works like a charm.
You could use the slice Twig filter, like this:
{% set rendered %}{% path project.mainImage, 'reference' %}{% endset %}
<img src="{{ rendered|slice(1) }}">
UPDATE:
And if you only want to do it on routes starting with /, you could do like this:
{% set rendered %}{% path project.mainImage, 'reference' %}{% endset %}
{% if rendered|slice(1) == '/' %}
<img src="{{ rendered|slice(1) }}">
{% else %}
<img src="{{ rendered }}">
{% endif %}

Dynamic path symfony

I have this code:
href="{{ path('new') }}"
Now is necessary use one variable in this section:
href="{{ path(item.ruta) }}"
But this show a error:
An exception has been thrown during the rendering of a template
("Unable to generate a URL for the named route "" as such route does
not exist.").
How can solution this problem?
It seems that item.ruta is empty, so no route could be generated.
You could specifiy a fallback like this {{ path(item.ruta ? item.ruta : 'new') }} or if you want to stay on the current page you need to do something like descripted here: get current url in twig template?
{% if item.ruta %}
href="{{ path(item.ruta) }}"
{% else %}
href="{{ path(app.request.attributes.get('_route'), app.request.attributes.get('_route_params')) }}"
{% endif %}
or if you really want # only, then remove the path function call
{% if item.ruta %}
href="{{ path(item.ruta) }}"
{% else %}
href="#"
{% endif %}

How to use variables in Assetic

I searched a lot but could not find a solution to achieve this:
{% for i in 1..6 %}
<li>
{% image '#MyBundle/Resources/public/images/college/demo/facilities/thumbs/laboratory/'~i~'.jpg' %}
<img class="facThumb" src="{{ asset_url }}" alt="Facilitiy"/>
{% endimage %}
</li>
{% endfor %}
Name of the images should be dynamic. Please help.
The above code throws error:
Unexpected token "operator" of value "~"
Solution:
According to what #Nic posted (accepted answer), the only workaround seems to be this:
{% for i in 1..6 %}
<li>
<img src="{{ asset('bundles/digicreekil/images/college/demo/facilities/thumbs/laboratory/t'~i~'.jpg') }}" alt='demo'/>
</li>
{% endfor %}
You can't use variables in Assetic (and therefore in the {% image %} tag).
The reason is, according to Kris Wallsmith (creator of Assetic):
(...) that Assetic needs to be able to parse a Twig template and extract any assets that are defined there. This is not possible if you use a variable in the tag.
Christophe Coevoet adds:
The assets are dumped when using the CLI command for this, not when rendering the page. So you cannot use variables as you don't have their values.
See this GitHub issue for the complete conversation.
Remember that Assetic creates and optimizes the assets when you run app/console assetic:dump, not when the page is actually rendered. Therefore, it cannot know of any values, it can only work with static assets.
So if you want to work with dynamic assets, you'll have to do something like this:
{% for i in 1..6 %}
<li>
<img class="facThumb" src="{{ asset('images/college/demo/facilities/thumbs/laboratory/'~i~'.jpg') }}" alt="Facilitiy"/>
</li>
{% endfor %}
In this case, you can iterate through the numbers 1-6 and use the variable in the asset's URL because you're not using Assetic, but Twig's asset() function. asset() simply returns the full URL of the asset, it doesn't do any optimizations so it can be executed during runtime.
But if you want to use Assetic's optimizations and filters, you can also give it the static assets:
<li>
{% image '#MyBundle/Resources/public/images/college/demo/facilities/thumbs/laboratory/1.jpg' %}
<img class="facThumb" src="{{ asset_url }}" alt="Facilitiy"/>
{% endimage %}
</li>
<li>
{% image '#MyBundle/Resources/public/images/college/demo/facilities/thumbs/laboratory/2.jpg' %}
<img class="facThumb" src="{{ asset_url }}" alt="Facilitiy"/>
{% endimage %}
</li>
<li>
{% image '#MyBundle/Resources/public/images/college/demo/facilities/thumbs/laboratory/3.jpg' %}
<img class="facThumb" src="{{ asset_url }}" alt="Facilitiy"/>
{% endimage %}
</li>
(etc.)
This way, you'll have to copy the same code 6 times, but it allows you to use Assetic.

How to prevent this code duplication? - Twig

I use this piece of code in a big part of my templates:
{% if app.session.hasFlash('error') %}
<div class="error">
{{ app.session.flash('error') }}
</div>
{% endif %}
but the word error is changing. Could you give me idea how to avoid code duplication?
With include or macro I can change only the div class, but what about the word error in app.session.flash? And is there sense in doing this, or it's better to leave it that way?
You can include this with the "with" option. For example:
{% include 'AcmeDemoBundle:Tools:flash.html.twig' with {'flash':'error'} %}
And then in flash.html.twig do:
{% if app.session.hasFlash(flash) %}
<div class="{{flash}}">
{{ app.session.flash(flash) }}
</div>
{% endif %}

Resources