Does twig support grandchildren inheritance? - php

My web application is structured as follows:
master.html (contains the master layout for the page)
page.html (contains the content of an individual page)
child.html (contains some data that may or may not be loaded)
I've got javascript in the child.html that needs to go beneath my jQuery link in master.html. Does Twig have a tag such that this is possible?
Clarifying with an example of sample output:
<!DOCTYPE html>
<html>
<head>
...
</head>
<body>
<!-- Content of page.html, which has content from child.html within it -->
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script>
<!-- Scripts from child.html -->
</body>
</html>

You create blocks in the master.html template and you can override these in page.html, as in child.html
master.html
<!DOCTYPE html>
<html>
<head>
<title>{{ title | default('Hello World') }}</title>
<link rel="stylesheet" type="text/css" href="theme.css">
{% block css %}
{% endblock %}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
{% block javascript_sources %}
{% endblock %}
</head>
<body>
<script>
//default code
</script>
</body>
</html>
page.html
{% extends "master.html" %}
{% block javascript_sources %}
<script src="my.jquery.plugin.min.js"></script>
{% endblock %}
{% block javascript %}
<script>
$(function(){
console.log('-- page loaded --');
});
</script>
{% endblock %}
child.html
{% extends "page.html" %}
{% block javascript %}
{{ parent() }}
<script>
$(function(){
console.log('-- child loaded --');
});
</script>
{% endblock %}

Okay, for anyone who stumbles upon this post at a later date, this is what I ended up doing:
Outsource all necessary javascript to another file, called child.js.
In the same conditional that determined whether to load child.html, load child.js into a variable.
Use twig variables to turn $js in PHP into {{ js }} in twig. (Be sure to use {{ js|raw }} to avoid escaping it) Use this variable in your page.html file.
If child.html is not loaded, $js contains an empty string.

Related

CSS and javascript not working in Symfony project

I recently started a new project in Symfony and I did everything here
but it didn't help.
I work for first time with Symfony and this is my first project. I strictly follow the documentation and I am trying to add some CSS but its now working. I use Encore and downloaded Yarn as the documentation says to do.
Below I will upload some of my code. It seems fine but it's not.
html.twig
<!DOCTYPE html>
<html lang="en" xmlns:th="http:thymeleaf.org">
<head>
<title>Events & People</title>
<meta charset="UTF-8">
{% block stylesheets %}
{#{% stylesheets '#AppBundle/public/build/app.css' %}#}
{{ encore_entry_link_tags('app') }}
<link src="/build/app.css" rel="stylesheet"/>
{#{% endstylesheets %}#}
{% endblock %}
</head>
webpack.config.js
var Encore = require('#symfony/webpack-encore');
Encore
// directory where compiled assets will be stored
.setOutputPath('public/build/')
// public path used by the web server to access the output path
.setPublicPath('/build')
// only needed for CDN's or sub-directory deploy
//.setManifestKeyPrefix('build/')
/*
* ENTRY CONFIG
*
* Add 1 entry for each "page" of your app
* (including one that's included on every page - e.g. "app")
*
* Each entry will result in one JavaScript file (e.g. app.js)
* and one CSS file (e.g. app.css) if you JavaScript imports CSS.
*/
.addEntry('app', './assets/js/app.js')
//.addEntry('page1', './assets/js/page1.js')
//.addEntry('page2', './assets/js/page2.js')
// will require an extra script tag for runtime.js
// but, you probably want this, unless you're building a single-page app
.enableSingleRuntimeChunk()
/*
* FEATURE CONFIG
*
* Enable & configure other features below. For a full
* list of features, see:
* https://symfony.com/doc/current/frontend.html#adding-more-features
*/
.cleanupOutputBeforeBuild()
.enableBuildNotifications()
.enableSourceMaps(!Encore.isProduction())
// enables hashed filenames (e.g. app.abc123.css)
.enableVersioning(Encore.isProduction())
//11111111111
// .enableSassLoader()
//
// // processes files ending in .less
// .enableLessLoader()
//
// // processes files ending in .styl
// .enableStylusLoader()
//11111111111
// enables Sass/SCSS support
//.enableSassLoader()
// uncomment if you use TypeScript
//.enableTypeScriptLoader()
// uncomment if you're having problems with a jQuery plugin
//.autoProvidejQuery()
;
module.exports = Encore.getWebpackConfig();
Here is an image of my tree of files:
If it's done right it should load the files from my /build/app.css, but it's not loading it.
For me, it was just a caching problem.
let's try to delete the cache.
I didn't search deeply, but one bad think is your link tag...
Replace (src by href)
<link src="/build/app.css" rel="stylesheet"/>
By
<link href="/build/app.css" rel="stylesheet"/>
Have you tried this:
<link src="build/app.css" rel="stylesheet"/>
removing the leading "/" only and see if that works? not certain though.
I solved my problem I just have an error in my CSS and yarn didn't compile it
Move your link tag outside of the stylesheet block's. And use twig asset() function instead of the absolute path.
PS: use href instead of src in link tag
<!DOCTYPE html>
<html lang="en" xmlns:th="http:thymeleaf.org">
<head>
<title>Events & People</title>
<meta charset="UTF-8">
<link href="{{ asset('build/app.css') }}" type="text/css" rel="stylesheet"/>
{% block stylesheets %} {% endblock %}
</head>
If you really want the place the link tag inside your stylesheet block's, you must call this by using twig parent() function's in each template view
{% extends 'base.html.twig' %}
{% block stylesheets %}
{# call the parent content inside stylesheet block #}
{{ parent() }}
{# other css code here #}
{% endblock %}
the script & stylesheets should be outside the body tag like this!
> <!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>{% block title %}Welcome!{% endblock %}</title>
</head>
<body>
{% block body %}{% endblock %}
</body>
{% block stylesheets %}
{{ encore_entry_link_tags('app') }}
{% endblock %}
{% block javascripts %}
{{ encore_entry_script_tags('app') }}
{% endblock %}
</html>
The script and stylesheets should be outside the body tag, like this:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>{% block title %}Welcome!{% endblock %}</title>
</head>
<body>
{% block body %}{% endblock %}
</body>
{% block stylesheets %}
{{ encore_entry_link_tags('app') }}
{% endblock %}
{% block javascripts %}
{{ encore_entry_script_tags('app') }}
{% endblock %}
</html>

Symfony : how to dynamically include assets and defer their loading at the end of the page?

working on a Symfony PHP CMS-based project, I'm having assets loading questions.
We created several types of widgets available in content management. That allows contributors to add one or several widget on their pages. Each type of widget has its own styles and scripts.
In actual state, we load every widgets assets at the end of the page even if the page does not contain each type of widget.
In order to optimize page weight and loading, we'd like to have a mecanism that add a call to one widget assets (during the widget rendering) and defer their loading at the end of the page.
Do you know a tool that could do the job ?
Not possible to show the whole code, but in short, here is what I'd like to do :
<body>
<article>
<widget_one>// I need #widget_one assets</widget_one>
<widget_two>// I need #widget_two assets</widget_one>
.....
.....
</article>
<assets>// now I load all needed assets</assets>
</body>
I came up with you can use Using Named Assets:
# app/config/config.yml
assetic:
assets:
widget_one:
inputs:
- '#AppBundle/Resources/public/js/widget_one_first_js.js'
- '#AppBundle/Resources/public/js/widget_one_second_js.js'
widget_two:
inputs:
- '#AppBundle/Resources/public/js/widget_two_first_js.js'
- '#AppBundle/Resources/public/js/widget_two_second_js.js'
After that in your template you use it -> if you have widget_one
{% javascripts
'#widget_one'
<script src="{{ asset_url }}"></script>
{% endjavascripts %}
if you have widget_one
{% javascripts
'#widget_two'
<script src="{{ asset_url }}"></script>
{% endjavascripts %}
You should use template inheritance: For example base.html.twig
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>{% block title %}Welcome!{% endblock %}</title>
{% block stylesheets %}{% endblock %}
</head>
<body>
{% block body %}{% endblock %}
{% block javascripts %}{% endblock %}
</body>
</html>
After that:
{% extends '::base.html.twig' %}
{% block javascripts %}
{% for widget in widgets %}
INCLUDE ASSETS
{% endfor %}
{% endblock %}
{% block body %}
{% for widget in widgets %}
SHOW WIDGET!
{% endfor %}
{% endblock %}

Include function in Twig template Symfony

Hello Guys I'm new to symfony and twig and what i'm trying to achiv is this:
In my base.html.twig file I try to include('article.html.twig') all works fine until I try to override(extend) the stylesheets block that resides in base.html.twig from article.html.twig.
I get an error message that this can only be achived if I extend base.html.twig (I know it works like that but its not what I want)
I want in fact to attach to article.html.twig the css and the javascript related to the html in this template and that they only get linked (loaded by the browser) in the section of the page whenever I include the template in any other template. It should work like a standalone component (webpart) or whatever this is called.
Do any of you know if such a thing is possible?
Thanks in advance.
Here is the base.html.twig:
<!DOCTYPE html>
<head>
<meta charset="UTF-8" />
{% block stylesheets %}
<link rel="stylesheet" type="text/css" media="all" href="{{ asset('style.css') }}" />
{% endblock %}
</head>
<body>
<p>Test include:</p>
{{ include('article.html.twig') }}
</body>
Here is the article.html.twig
{% block stylesheets %}
{{ parent() }}
<link rel="stylesheet" type="text/css" media="all" href="{{ asset('custom.css') }}" />
{% endblock %}
<div id="article">
This is an Article!
</div>
Sorry, I just read your question again, and now I fully understand what you are trying to achieve.
Unfortunately it is not possible to override a block from within an include. It's exactly like the error message already states... It is only possible to override a block if you extend the original template.

Theme assets management in Symfony2

I have a Symfony2 app that must serve different themes. These themes are essentially directories containing CSS files (eventually other files and minified into a single one).
In Phalcon, I could dynamically set the asset location of my assets in the controller. In Symfony, assets are explicitly defined. My current solution is as follows, but it doesn't look great. This is the HTML of my base.html.twig. I have a property theme in my entity and I define the theme object in my controller.
Basically I'm looking for the proper way to do this in Symfony. Otherwise, I'll just do it like this.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>{% block title %}Welcome!{% endblock %}</title>
<link rel="icon" type="image/x-icon" href="{{ asset('favicon.ico') }}" />
{% if theme is defined %}
{% for asset in theme.css %}
<link rel="stylesheet" href="{{ asset.url }}"/>
{% endfor %}
{% endif %}
</head>
<body>
{% block page %}
Welcome to the default page!
{% endblock %}
{% block javascripts %}
{% if theme is defined %}
{% for asset in theme.js %}
<script src="{{ asset.url }}"></script>
{% endfor %}
{% endif %}
{% endblock %}
</body>
</html>
I think the most elegant way is to define a default theme, and put the diffrent themes into a root folder, just like this:
themes/
default/
css|js|images...
blue/
css|js|images...
yellow/
css|js|images...
then in Twig template engine, you can use it like this way:
<link rel="stylesheet" href="themes/{{ theme_name|default("default") }}/css/app.css"/>
<script src="themes/{{ theme_name|default("default") }}/js/app.js">

symfony 2 template inheritance and assets management in multi app environment

I have a problem,
An exception has been thrown during the rendering of a template ("Unable to generate a URL for the named route "_assetic_3625095_0" as such route does not exist.") in #base_templates/base.html.twig at line 9.
Sturcture of my app directory:
Resources // Contains common layouts and assets for all of my apps
config // Contains common configs
current_app // yes, this is a current application directory
So. I have a base.html.twig in my Rosurces/views/ directory with such markup:
<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') }}"/>
{% block javascripts %}
{% javascripts
'#jquery'
'#global' %}
<script type="text/javascript" src="{{ asset_url }}"></script>
{% endjavascripts %}
{% endblock %}
</head>
<body>
{% block body %}{% endblock %}
</body>
</html>
And my current_app/Resources/views/base.html.twig inherit this Resources/views/base.html.twig
And I experience that problem I was talking about in the beginning.
Has anyone experienced such kind of problems already ? Do you have a solution ?
I know if I put javascripts code block inside my current_app/Resources/views/base.html.twig it works, but I need to keep common javascripts inside common layout. And I don't want to use symlink

Categories