Twig template parent() caused double parent block - symfony

I have a base.html.twig template.html.twig and dashboard.html.twig.
Dashboard extends template which extends base.
Base:
{% block javascripts %}
<script src="1.js"></script>
{% endblock %}
Template:
{% block javascripts %}
{{ parent() }}
<script src="2.js"></script>
{% endblock %}
Dashboard:
{% block javascripts %}
{{ parent() }}
<script src="3.js"></script>
{% endblock %}
This templating setup resulted in redundant script tags where everything is doubled like this
<script src="1.js"></script>
<script src="2.js"></script>
<script src="3.js"></script>
<script src="1.js"></script>
<script src="2.js"></script>
<script src="3.js"></script>
Am I missing something? Why is it happening?
Edit1:
base.html.twig:
extends nothing
template.html.twig:
{% extends 'base.html.twig' %}
default/dashboard.html.twig:
{% extends '::template.html.twig' %}

In my opinion your {% extends "file" %} is bad.
The fix :
Template :
{% extends "base_path" %}
{% block javascripts %}
{{ parent() }}
<script src="2.js"></script>
{% endblock %}
Dashboard :
{% extends "template_path" %}
{% block javascripts %}
{{ parent() }}
<script src="3.js"></script>
{% endblock %}

A bit late but since there's no accepted answer yet, I'll give it a go.
I was experiencing the same and this solved it for me, in my case it had to do with the structure of the base template and the current template from where you're trying to extend the base file, in my case, it was, in a similar situation as yours as far I can tell from your code.
Basically the structure in this example is wrong:
base:
{% block notAddedInTemplate %}
{% block javascripts %}
<script src="1.js"></script>
{% endblock javascripts%}
{% endblock notAddedInTemplate %}
Template:
{% extends 'base.html.twig' %}
{% block javascripts %}
{{ parent() }}
<script src="2.js"></script>
{% endblock javascripts%}
And should be:
base:
{% block notAddedInTemplate %}
{% block javascripts %}
<script src="1.js"></script>
{% endblock javascripts%}
{% endblock notAddedInTemplate %}
Template:
{% extends 'base.html.twig' %}
{% block notAddedInTemplate %}
{% block javascripts %}
{{ parent() }}
<script src="2.js"></script>
{% endblock notAddedInTemplate %}
I hope this will help you solve your issue.

Related

How to exclude a twig partial from a base extend in Symfony on some pages only?

Is there a way to specify an "extend" in Twig to exclude one of its included partials ?
To better explain myself, here is my base.html.twig
<body>
{% include '/main/_navbar.html.twig' %}
{% block body %}
{% for flashError in app.flashes('success') %}
<div class="alert alert-success" role="alert">{{ message }}</div>
{% endfor %}
{% endblock %}
{% include '/main/_footer.html.twig' %}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="{{ asset('script/app.js') }}"></script>
</body>
On my login page, I do not need my _navbar.html.twig partial. Is there a way to not include (exclude) it knowing my view extends from this base template ? Are there any "options" I could pass behind that extends ?
This is the code I use to extend my base template on my login page :
{% extends 'base.html.twig' %}
Just wrap the include you don't want to include in a seperate block, then override the block with empty content, e.g.
base.html.twig
<body>
{% block nav %}
{% include '/main/_navbar.html.twig' %}
{% endblock %}
{% block body %}
{% for flashError in app.flashes('success') %}
<div class="alert alert-success" role="alert">{{ message }}</div>
{% endfor %}
{% endblock %}
{% include '/main/_footer.html.twig' %}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="{{ asset('script/app.js') }}"></script>
</body>
login.html.twig
{% extends "base.html.twig" %}
{% block nav %}{% endblock %}
demo

Influence the twig included file on parent

I have a problem like this
But i can not use {% use %}
for example:
{# file1.twig #}
{% extends "main.twig" %}
{% block content %}content text{% endblock %}
{# main.twig #}
{% block content %}{% endblock %}
{% for widget in widgets %}
{% embed widget %}{% endembed %}
{% endfor %}
{% block js %}{% endblock %}
{# widget1.twig #}
{% block js %}
script1
{% endblock %}
{# widget2.twig #}
{% block js %}
script1
{% endblock %}
I want to be the result:
content text
script1
script2
I have a lot of files like file1.twig and widget1.twig
I can not use all the widgets in the all files.
Also, {{ parent() }} does not work for me
Is there another way?

Twig javascript in included child

I have a question regarding adding javascript to child elements. How do you do that?
I have this setup:
base.html.twig:
{% block content %}
{% endblock content %}
{% block script %}
{% endblock script %}
index.html.twig:
{% extends base.html.twig %}
{% include intro.html.twig %}
{% block content %}
<html></html>
{% endblock content %}
{% block script %}
<script></script>
{% endblock script %}
intro.html.twig:
{% block script %}
<script></script>
{% endblock script %}
I want to add more javascript files into the intro.html.twig file, but it doesn't append it to the script block in index.html.twig.
All help appreciated!
UPDATE
I want to send some parameters with intro.html.twig:
{% extends 'intro.html.twig' with {
'title': 'title',
'type': 'test',
} %}
is this possible using extends, or can I only use with with include?
index.html.twig
{% extends intro.html.twig %}
{% block content %}
<html></html>
{% endblock content %}
{% block script %}
{{ parent() }}
<script></script>
{% endblock script %}
intro.html.twig
{% extends base.html.twig %}
{% block script %}
<script></script>
{% endblock script %}

Cleanly including css/js required by content in a macro?

I have a page template like so:
{# page.twig #}
{% import "_widgets.twig" as widgets %}
{% include '_header.twig' %}
<body>
{{ widgets.fancy_widget(record.items) }}
{# more content goes here #}
</body>
_header.twig contains the <head> tag and some blocks for css and javascript:
{# _header.twig #}
<!DOCTYPE html>
<head>
{% block javascripts %}
{% endblock %}
{% block stylesheets %}
{% endblock %}
</head>
_widgets.twig contains a macro which generates some markup
{# _widgets.twig #}
{% macro fancy_widget(fanciful_items) %}
{# insert special css and js into <head> only if the macro is used #}
{% block stylesheets %}
<link rel="stylesheet" href="css/some_fancy_widget.css">
{% endblock %}
{% block javascripts %}
<script src="js/some_fancy_widget.js"></script>
{% endblock %}
{% for item in fanciful_items %}
{# output some fancy markup #}
{% endfor %}
{% endmacro %}
What I'd like to do is add the widget css/js to the blocks in _header.twig if the macro is called. Ideally they'll only be added once, so multiple calls won't create extra <link> and <script> tags.
Is this possible? Or is there a better way to accomplish this?
I would say that you are not using Twig correctly.
In fact your page.twig must extends base.html.twig.
{# app/Resources/views/base.html.twig #}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>{% block title %}Welcome!{% endblock %}</title>
{% block stylesheets %}{% endblock %}
<link rel="icon" type="image/x-icon" href="{{ asset('favicon.ico') }}" />
</head>
<body>
{% block body %}{% endblock %}
{% block javascripts %}{% endblock %}
</body>
</html>
Then your page.html.twig must extends this base.html.twig
You cannot define or overide blocks in macros.
The simplest way will be:
In your page.html.twig:
{% extends 'base.html.twig' %}
{% import "_widgets.twig" as widgets %}
{% block stylesheets %}
{{ parent() }}
<link rel="stylesheet" href="css/some_fancy_widget.css">
{% endblock %}
{% block javascripts %}
{{ parent() }}
<script src="js/some_fancy_widget.js"></script>
{% endblock %}
{% block body %}
{% endblock %}
and the rest (Your macro) :
_widgets.twig :
{# _widgets.twig #}
{% macro fancy_widget(fanciful_items) %}
{% for item in fanciful_items %}
{# output some fancy markup #}
{% endfor %}
{% endmacro %}

Twig: head blocks control from different controllers

I use symfony 2.0.9.
Code of base.html.twig:
<html>
<head>
<title>title</title>
{% block stylesheets %}
<link href="{{ asset('css/main.css') }}" type="text/css" rel="stylesheet" />
{% endblock %}
{% block javascript %}
{% endblock %}
</head>
<body>
<div class="sidebar">{% block sidebar %}{% endblock %}</div>
<div class="content">{% block content %}{% endblock %}</div>
</body>
My Bundle have own layout.html.twig, which being extended by Controllers, for example PostController.php with action showAction.
Code of layout.html.twig
{% extends '::base.html.twig' %}
{% block stylesheets %}
{{ parent() }}
...something
{% endblock %}
{% block navigation %}
...list of menus
{% endblock %}
{% block sidebar %}
{% render "DevMyBundle:Page:sidebar" %}
{% endblock %}
How can access to block 'javascript' in base.html.twig from sidebar.html.twig, which rendered by PageController like this in layout.html.twig: {% render "DevMyBundle:Page:sidebar" %} or How can i reorganize structure of my templating.
What for?: There are more blocks in sidebar may be. Each block call its own js. How? Thanks for advance.
Update: please, guys, help. There should be a simple answer. I have read twig docs, but im newbe in it. If i post this question not correctly, ask me.
One way would be to move the sidebar javascrpt to it's own template.
Something like this in layout.html.twig
{% block sidebar %}
{% render "ZaysoArbiterBundle:Test1\\Main:sidebar" %}
{% endblock %}
{% block javascript %}
{{ parent() }}
<script>Some layout javascript</script>
{% render "ZaysoArbiterBundle:Test1\\Main:sidebarjs" %}
{% endblock javascript %}

Resources