Im using gulp-twig: https://github.com/zimmen/gulp-twig
I have a twig file for my container component:
{# container.twig #}
<div class="container">
{% for item in items %}
<div class="container__item">
{{ item }}
</div>
{% endfor %}
</div>
I also have a snippet file:
{# snippet.twig #}
<div class="snippet">
<h2>{{ title }}</h2>
</div>
Im demoing these in page.twig. I need to render the snippet as the {{ item }} within the container. So when viewing page.twig this should be the output:
<div class="container">
<div class="container__item">
<div class="snippet">
<h2>title</h2>
</div>
</div>
<div class="container__item">
<div class="snippet">
<h2>title</h2>
</div>
</div>
<div class="container__item">
<div class="snippet">
<h2>title</h2>
</div>
</div>
</div>
Now here is where it gets tricky. container.twig and snippet.twig are being pulled into another application. As such {{ item }} within container.twig cant be changed to something like {{ itemRenderer(item) }}.
However page.twig is not being used anywhere else so I can edit it however I like. Is there a way in page.twig to render container.twig with snippet.twig as it's item, without modifying container.twig or snippet.twig?
This is my gulp task:
var gulp = require('gulp'),
config = require('../config'),
utilities = require('../build-utilities'),
src = config.path.src,
dest = config.path.dest,
opts = config.pluginOptions,
env = utils.getEnv(),
plugins = require('gulp-load-plugins')(opts.load);
var compile = function() {
var notProdOrTest = env.deploy && !env.prod && !env.test,
deployPath = env.deployPath,
sources = (env.deploy) ? ((env.styleguide) ? src.twig.styleguide: src.twig.testing): src.twig.all;
return gulp.src(sources, {base: 'src/'})
.pipe(plugins.twig({
data: {
component: utils.getDirectories('src/component/'),
deploy : env.deploy,
test : env.test,
prod : env.prod
}
}))
.pipe(plugins.htmlmin(opts.htmlmin))
.pipe(plugins.tap(function(file){
file.path = file.path.replace('testing/', '');
}))
.pipe((notProdOrTest) ? plugins.replace(/src="\//g, 'src="/' + deployPath.root + '/'): plugins.gutil.noop())
.pipe((notProdOrTest) ? plugins.replace(/href="\//g, 'href="/' + deployPath.root + '/'): plugins.gutil.noop())
.pipe((notProdOrTest) ? plugins.replace(/srcset="\//g, 'srcset="/' + deployPath.root + '/'): plugins.gutil.noop())
.pipe((notProdOrTest) ? plugins.replace(/url\('\//g, 'url(\'/' + deployPath.root + '/'): plugins.gutil.noop())
.pipe(gulp.dest((env.deploy) ? deployPath.markup: dest.markup));
},
watch = function() {
gulp.watch(src.twig.watch, ['twig:compile']);
};
module.exports = {
compile: compile,
watch : watch
};
to print variable in twig file just use {{ my_variable }}.
Template names For example, to include a snippet template you would include the snippet folder in the template name. If the template is a Twig template then you don't need to include the . twig file extension. You can also dynamically set the template name because template names can be any valid Twig expression.
Twig is a template engine for PHP and it is part of the Symfony2 framework. In Drupal 8 Twig replaces PHPTemplate as the default templating engine. One of the results of this change is that all of the theme_* functions and PHPTemplate based *.
This could be done with macros:
{# macros.html.twig #}
{% macro thisItem(item) %}
<div class="this-snippet">
<h2>{{ item.title }}</h2>
</div>
{% endmacro %}
{% macro thatItem(item) %}
<div class="other-snippet">
<h2>{{ item.title }}</h2>
</div>
{% endmacro %}
{% macro container(itemRenderer, items) %}
<div class="container">
{% for item in items %}
<div class="container__item">
{{ itemRenderer(item) }}
</div>
{% endfor %}
</div>
{% endmacro %}
And then in the template:
{# template.html.twig #}
{% from "macros.html.twig" import thisItem as itemRenderer, container %}
{% container(itemRenderer, items) %}
And in another template:
{# template2.html.twig #}
{% from "macros.html.twig" import thatItem as itemRenderer, container %}
{% container(itemRenderer, items) %}
The same thing can be achieved with regular includes, although both offer the same possibilities, I think the macro solution is cleaner.
{# snippet.html.twig #}
<div class="this-snippet">
<h2>{{ item.title }}</h2>
</div>
{# container.html.twig #}
<div class="container">
{% for item in items %}
<div class="container__item">
{% include snippetTmpl with { 'item': item } only %}
</div>
{% endfor %}
</div>
{# page.html.twig #}
{% include "container.html.twig" with { 'snippetTmpl': 'snippet.html.twig', 'items': items } only %}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With