theme()
Plantillas twigtemplate_process_hook()
desaparece!Render arrays are nested and thus form a tree. Consider them Drupal's «render tree» — Drupal's equivalent of the DOM.+info
$element = [
'#type' => 'my_element',
'#config_one' => 'blue',
];
$element['#attributes'] = [
'id' => 'my_blue_element_1',
'class' => ['my-element','blue'],
];
summer_theme
Crearemos una carpeta summer_theme
en la carpeta/themes
NUNCA en la carpeta /core/themes
Briconsejo: crear subcarpetas:
/themes/contrib
/themes/custom
summer_theme.info.yml
name: My theme
type: theme
base theme: classy
description: 'My custom theme for the DrupalSummer'
core: 8.x
regions:
header: Header
content: Content # the content region is required
sidebar_first: 'Sidebar first'
footer: Footer
Para crear un nuevo tema podemos escoger entre dos temas base (ocultos) incluidos en core.
Favorite horses
Black Stallion
Shadowfax
Hidalgo
Favorite horses
Black Stallion
Shadowfax
Hidalgo
Imprimir variable
<h2{{ title_attributes }}>{{ label }}</h2>
{{ foo.bar }}
Ejecuta la siguiente cadena para obtener el valor
// Elemento de una array.
$foo['bar'];
// Propiedad de un objeto.
$foo->bar;
// Método de un objeto.
$foo->bar();
// Get de un objeto.
$foo->getBar();
// Existencia del valor.
$foo->isBar();
null
Asignar valores a variable
{%
set classes = [
'block',
'block-' ~ configuration.provider|clean_class,
'block-' ~ plugin_id|clean_class,
]
%}
{% if not page %}
<h2{{ title_attributes }}>
<a href="{{ url }}" rel="bookmark">{{ label }}</a>
</h2>
{% endif %}
{% if user_name %}
Hi {{ user_name|default('Bartolo') }}
{% endif %}
{% if (summary is not empty) or (description is not empty) %}
<details>
{% if summary is not empty %}
<summary>{{ summary }}</summary>
{% endif %}
{% if description is not empty %}
{{ description }}
{% endif %}
</details>
{% endif %}
Estructura for simple
{% for content in column.content %}
{{- content.separator }}{{ content.field_output -}}
{% endfor %}
Iterando por clave y valor
{% for key, column in row.columns %}
<a href="#{{ key }}>{{ column }}</a>
{% endfor %}
Variable loop
{% for content in node if content.published %}
{% if loop.first %}
{# primer elemento #}
{% elseif loop.last %}
{# último elemento loop #}
{% elseif loop.index == "2" %}
{# segundo elemento #}
{% elseif loop.revindex == "2" %}
{# segundo elemento contando alrevés #}
{% else %}
{{- content.separator }}{{ content.field_output -}}
{% endif %}
{% endfor %}
Imprimir atributos de una etiqueta
Hello Drupaleros!
<div{{ attributes }}>
O bien imprimir solamente aquellos atributos que nos interesen
<div class="myclass {{ attributes.class }}"{{ attributes|without('class') }}>
Manipular los valores; añadiendo o quitando elementos.
<div{{ attributes.addClass('hello').removeClass('bye') }}>
Realizando comprobaciones.
{% if attributes.hasClass('field-label-inline') %}
{# My inline custom code #}
{% endif %}
Establecer valores
<div{{ attributes.setAttribute('id', 'menu-link') }}>
Borrar valores
<div{{ attributes.removeAttribute('id') }}>
Se pueden usar para manipular las variables...
{{ ponies|safe_join(", ")|lower}}
...o para traducir cadenas
<span class="marker">{{ 'New'|t }}</span>
Aunque para traducir cadenas que incluyan variables se puede usar
{% trans %}
Submitted by {{ author_name }} on {{ date }}
{% endtrans %}
clean_class
, format_date
, without
, drupal_escape
,...
Se pueden definir zonas en las plantillas que sean modificadas (extendidas) en otras plantillas.
Definimos una «zona variante»
page.html.twig
{% block variante %}
{% endblock %}
Heredamos toda la página,
modificando solamente ese trozo page--front.html.twig
{% extends "page.html.twig" %}
{% block variante %}
Contenido específico de la página principal.
{% endblock %}
Aprovechar código para regiones iguales
{% include('sidebar.twig') %}
block.html.twig
<div{{ attributes.addClass(classes) }}>
{{ title_prefix }}
{% if label %}
<h2{{ title_attributes }}>{{ label }}</h2>
{% endif %}
{{ title_suffix }}
{% block content %}
{{ content }}
{% endblock %}
</div>
block--local-actions-block.html.twig
{% extends "block.html.twig" %}
{#
/**
* @file
* Theme override for local actions (primary admin actions.)
*/
#}
{% block content %}
{% if content %}
<nav class="action-links">{{ content }}</nav>
{% endif %}
{% endblock %}
services.yml:
parameters:
twig.config:
debug: true
Obtenemos información adicional
<!-- THEME DEBUG -->
<!-- THEME HOOK: 'block' -->
<!-- FILE NAME SUGGESTIONS:
* block--bartik-powered.html.twig
* block--system-powered-by-block.html.twig
* block--system.html.twig
x block.html.twig
-->
<!-- BEGIN OUTPUT from 'core/modules/block/templates/block.html.twig' -->
<div class="block block-system contextual-region" id="block-bartik-powered" role="complementary">
<div data-contextual-id="block:block=bartik_powered:"></div>
<div class="content">
<span>Powered by <a href="http://drupal.org">Drupal</a></span>
</div>
</div>
<!-- END OUTPUT from 'core/modules/block/templates/block.html.twig' -->
Usando el módulo Devel y Kint search
{{ kint(content) }}
Ejemplo
Configurar la visibilidad de los filtros contextuales y la toolbar de Drupal
Ahora todos los ficheros a cargar se definen en
summer_theme.libraries.yml
my-library:
version: 1.x
css:
theme:
css/my-library.css: {}
js:
js/my-library.js: {}
global-styling:
version: 1.x
css:
component:
css/components/action-links.css: { weight: -10 }
css/components/breadcrumb.css: { weight: -10 }
css/components/button.css: { weight: -10 }
layout:
css/layout.css: {}
theme:
css/style.css: {}
css/colors.css: {}
css/print.css: { media: print }
Drupal 8 no carga jQuery, por ejemplo, si no lo especificamos.
my-library:
version: 1.x
css:
theme:
css/my-library.css: {}
js:
js/my-library.js: {}
dependencies:
- core/jquery
De forma global
name: My theme
type: theme
base theme: classy
description: 'My custom theme for DrupalSummer'
core: 8.x
libraries:
- my_theme/my-library
En un template de Twig
{{ attach_library(active_theme()'/my-library') }}
<div>Some markup {{ message }}</div>
En una página concreta, tenemos que crear el archivo summer_theme.theme
function summer_theme_preprocess_page(&$variables) {
$variables['#cache']['contexts'][] = 'route';
if (\Drupal::routeMatch()->getRouteName() === 'entity.node.preview') {
$variables['#attached']['library'][] = 'summer_theme/my-library';
}
}
my_theme.breakpoints.yml
my_theme.mobile:
label: mobile
mediaQuery: ''
weight: 0
multipliers:
- 1x
my_theme.narrow:
label: narrow
mediaQuery: 'all and (min-width: 560px) and (max-width: 850px)'
weight: 1
multipliers:
- 1x
my_theme.wide:
label: wide
mediaQuery: 'all and (min-width: 851px)'
weight: 2
multipliers:
- 1x
Gracias a
{% import _self as menus %}
{{ menus.menu_links(items, attributes, 0) }}
{% macro menu_links(items, attributes, menu_level) %}
{% import _self as menus %}
{% if items %}
{% if menu_level == 0 %}
{% else %}
{% endif %}
{% for item in items %}
-
{{ link(item.title, item.url) }}
{% if item.below %}
{{ menus.menu_links(item.below, attributes, menu_level + 1) }}
{% endif %}
{% endfor %}
{% endif %}
{% endmacro %}