I want to execute a javascript in when user enter in this page : page1.twig.html
{% extends "Test1Bundle::layout1.html.twig" %}
// block code javascript here
{% block content %}
<div>
<span>Alexa .</span>
</div>
{% endblock %}
layout1.html.twig :
{% extends 'Test1Bundle::layout2.html.twig' %}
<p>
My name is : {% block content %}{% content %}
</p>
layout2.html.twig :
<!DOCTYPE html>
<html lang="fr">
<head>
// call block javascript here
</head>
.
.
.
I don't know what I do for this and which function to use ! please help !
You need to define empty blocks in your parents, where you want to see your stuffs rendered:
page1.html.twig:
{% extends "layout1.html.twig" %}
{% block script %}
<script type="text/javascript">
// whatever
</script>
{% endblock %}
{% block name %}
<div>
<span>Alexa .</span>
</div>
{% endblock %}
layout1.html.twig:
{% extends 'layout2.html.twig' %}
{% block content %}
<p>
My name is : {% block name %}{% endblock %}
</p>
{% endblock %}
layout2.html.twig:
<!DOCTYPE html>
<html lang="fr">
<head>
{# btw, scripts are better at the bottom of the body #}
{% block script %}{% endblock %}
</head>
<body>
{% block content %}{% endblock %}
</body>
</html>
See fiddle
Related
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
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 %}
I'm following a tutorial about symfony2 framework ..
I've already managed to render a template which inherits from the base layout as follows
# ::layout.html.twig > MyvendorBlogBundle:blog:index.html.twig
# then inside the controller action, call
$this->render('MyvendorBlogBundle:Blog:index.html.twig', ['foo'=>'bar']);
I decided to add an intermediate template in between but I'm having trouble to make twig templating engine to render my 3 layouts cascaded templates: As mentioned above, i'm not able to get any output using the following schem but a blank page instead (no raised exceptions and the source only contains the base.html.twig code)
# ::layout.html.twig > MyvendorBlogBundle::layout.html.twig > MyvendorBlogBundle:blog:index.html.twig
Here are my templates
base (app/Ressources/views):
<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>
<div id="app-container">
<header id="app-header">
</header>
<div id="app-page-content">
{% block body %}{% endblock %}
</div>
</div>
{% block javascripts %}{% endblock %}
{# FLASH BAG HANDLING #}
{% for label, flashes in app.session.flashbag.all %}
{% for flash in flashes %}
<div class="alert alert-{{ label }}">
{{ flash }}
</div>
{% endfor %}
{% endfor %}
</body>
</html>
Then the blog bundle layout (src/Myvendor/BlogBundle/Resources/views):
{% extends "::base.html.twig" %}
{% block body %}
{% block side %}
<div id="blog-side">
<nav>
1rst link
</nav>
</div>
{% endblock %}
{% block main %}{% endblock %}
{% endblock %}
Now the index page template (src/Myvendor/BlogBundle/Resources/views/Blog):
{% extends "MyvendorBlogBundle::layout.html.twig" %}
{% block main %}
<h1>{{ caption }} !</h1>
{% if caption is not empty %}
{{ caption }}
{% endif %}
{% endblock %}
And finally the controller
namespace Myvendor\BlogBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
class BlogController extends Controller
{
public function indexAction()
{
return $this->render('MyvendorBlogBundle:Blog:index.html.twig', ['caption'=>'hello!']);
}
}
May someone spot what's going on here ?
The pb maybe obvious but I've been stuck for a couple of hours now and blocks nesting seems perfect to me :/
Need to use a variable that is in the parent template.
I have layout:
<html>
<head>
</head>
<body>
{%block content %}
{% set com = 0 %}
DEFALUT CONTENT
{% endblock %}
</body>
</html>
And children template:
{% extends '::layout.html.twig' %}
{% block content %}
HOW USE LAYOUT VARIABLE HERE? LIKE: {{ com }}
{% endblock %}
Thanks in advance!
Use the parent() twig function.
{% extends '::layout.html.twig' %}
{% block content %}
{{ parent() }}
{{ com }}
{% endblock %}
The above code will render a template like :
<html>
<head>
</head>
<body>
{% block content %}
{% set com = 0 %}
DEFAULT CONTENT
{{ com }}
{% endblock %}
</body>
</html>
I would like to use a kind of global array to define what javascripts should be loaded at the end of the page. This way, I can dynamically add javascript files.
The problem is that the base template is being rendered first. Imagine this base html:
{% set javascriptList = [ 'js/vendor/jquery-1.10.1.min.js', 'js/vendor/bootstrap.min.js', 'js/main.js' ] %}
<!DOCTYPE html>
<head>
<title>my project</title>
</head>
<body>
{% block container %}
content goes here
{% endblock %}
{% block javascripts %}
{% for js in javascriptList %}
<script src="{{ asset(js) }}"></script>
{% endfor %}
{% endblock %}
</body>
</html>
Then I would have a page, something like this:
{% extends base.html.twig %}
{% block container %}
<h1>Demo</h1>
Bla bla
Code I want to reuse:
{% include 'code-with-js.html.twig' %}
{% endblock %}
Then my code-with-js.html.twig would be:
<div id="DemoContent">
Some content, with a tooltip thingy maybe.
</div>
{% set javascriptList = javascriptList|merge(['js/tooltip.js']) %}
So, using this setup, I can make sure that the correct javascript is being added, when the piece of html is being included.
But, this doesn't work of course. The base html is rendered first, so the element will be added to the javascriptList array after it has been rendered. My approach must be wrong.
In my project this reusable code is actually a form with some extra buttons that insert content to the textarea's (so a tinyMCE, but much much much more simplistic). I would like to reuse this code on several pages (create, update).
Any thoughts are welcome!
First of all I recommend you to add a javascript block in your base.html.twig :
You can add a block in your base.html.twig after your script load :
{% block javascripts %}
{% for js in javascriptList %}
<script src="{{ asset(js) }}"></script>
{% endfor %}
{% endblock %}
<script type="text/javascript">
{% block afterJavascriptLoad %}
{% endblock %}
</script>
With inheritance you'll be able to execute javascript after all script load in nested template :
{% extends base.html.twig %}
{% block afterJavascriptLoad %}
//Your code to be executed after base.html script load
{% endblock %}
Having html code and javascript code is not a very good practice. For exemple if you have 3 tinyMCE redactor in your page, you'll load 3 times tinyMCE.
For me the best way is to have your template like this :
base.html.twig:
{% block container %}
content goes here
{% endblock %}
{% block javascripts %}
{% for js in javascriptList %}
<script src="{{ asset(js) }}"></script>
{% endfor %}
{% endblock %}
{% block afterJavascriptLoad %}
//Your code to be executed after base.html script load
{% endblock %}
pageWithTinyMCE.html.twig :
{% extends base.html.twig %}
{% block container %}
<h1>Demo</h1>
Bla bla
Code I want to reuse:
{% include 'code-without-js.html.twig' %}
{% set javascriptList = javascriptList|merge(['js/tooltip.js']) %}
{% endblock %}
{% block afterJavascriptLoad %}
//Custom javascript for the page
{% endblock %}