Pasar al contenido principal
programming code

Cómo cambiar la salida de un campo con extensiones de TWIG

En algunas ocasiones que necesitamos una salida de un campo y las opciones de formateador no son las que requerimos o bien solo necesitamos una salida personalizada; sea cual sea el uso por el cual vamos a requerir usar esta forma de implementación, vamos a ver que necesitamos para hacerlo.

En este ejemplo vamos a renderizar la salida de un campo de un tipo de contenido para darle formato de moneda.

Creamos un nuevo módulo para este ejemplo.

type: module
name: ex_twig_extension
description: 'Provides an example for a twig extension'
core: 8.x

En nuestro módulo vamos a crear un servicio el cual usaremos para hacer nuestra extensión de twig. así que creamos nuestro archivo /ex_twig_extension.services.yml.

services:
  twig.number_format:
    class: Drupal\ex_twig_extension\NumberFormat
    tags:
        - { name: twig.extension }

Teniendo nuestro servicio, vamos a crear la función a la que hace mención el servicio, la cuál será nuestra extensión de TWIG. En la ruta /src/ vamos a crear el archivo con el nombre de la clase NumberFormat.php.

<?php
namespace Drupal\ex_twig_extension;
/**
 * Class NumberFormat
 * @package Drupal\ex_twig_extension
 */
class NumberFormat extends \Twig_Extension
{
    public function getName()
    {
        return 'twig.number_format';
    }
    public function getFilters()
    {
        return array(
            'number_format'   => new \Twig_Filter_Method($this, 'numberFormat')
        );
    }
    public function numberFormat($string)
    {
        $re = '/([0-9]*)([0-9]{3})/';
        $str = $string;
        $subst = '$$1.$2,00';

        $result = preg_replace($re, $subst, $str);
        return $result;
    }
}

En la definición de nuestra función nos encontramos con getName() que será la función que retorne el nombre del servicio.

La función getFilters() creará una instancia llamada number_format la cual llamará a nuestra anhelada función, que se encargará de hacer el proceso final. Es importante tener en cuenta que el nombre de la instancia será usado para llamarse como función en TWIG.

Por último la función numberFormat($string) espera un parámetro que debe ser enviado desde la plantilla como el dato a formatear, dentro de la función nos encontramos con una expresión regular, la cual toma el dato ej: 500000 y le da formato para volverlo ej: $500.000,00 en el caso de moneda.

Si en algún momento requiere usar expresiones regulares para solucionar algún problema, recomiendo esta página para crearlas: https://regex101.com

Ahora tenemos todo listo para nuestra extensión de TWIG, lo que necesitamos ahora es enfocarnos en el objetivo principal y es nuestro campo. TWIG nos permite sobreescribir la salida de vistas, páginas, bloques y también entre nodos, necesitamos para este caso sólo nuestro campo de un tipo de contenido. Para poder ver el nombre del template que debemos usar podemos habilitar en nuestro archivo services.yml la opción:

parameters:
  twig.config:
    debug: true

Al inspeccionar elemento y seleccionando el campo deseado, podremos ver en orden de prioridad los nombres de archivo que podemos usar.

Otra ayuda que podemos tener es la documentación que Drupal nos ofrece en las convenciones de los nombres: https://www.drupal.org/docs/8/theming/twig/twig-template-naming-conventions

Para nuestro caso usaremos este nombre de máquina, debido a que es un campo, en la ruta: themes/custom/custom_theme/templates/field/field--node--field-name--content-type.html.twig

En nuestro archivo vamos a tomar las opciones que traería normalmente este archivo en la documentación https://api.drupal.org/api/drupal/core!modules!system!templates!field.html.twig/8.2.x y vamos a dar unos ajustes.

{% if label_hidden %}
  {% if multiple %}
    <div{{attributes}}>
      {% for item in items %}
        <div{{ item.attributes }}>{{ item.content }}</div>
      {% endfor %}
    </div>
  {% else %}
    {% for item in items %}
      <div{{ attributes }}>{{ item.content }}</div>
    {% endfor %}
  {% endif %}
{% else %}
  <div{{ attributes }}>
    <div{{ title_attributes }}>{{ label }}</div>
    {% if multiple %}
      <div>
    {% endif %}
    {% for item in items %}
      {% set value = item.content | number_format %}
      <div{{ item.attributes }>{{ value }}</div>
    {% endfor %}
    {% if multiple %}
      </div>
    {% endif %}
  </div>
{% endif %}

En la línea 20 creamos una variable value la cual tendrá el valor formateado, ya que se si observamos el contenido que es nuestro valor sin formato se llama como parámetro en la función number_format que es nuestra extensión.

Con esto podemos usar funciones de PHP fuera de TWIG usadas como servicios, puede ser útil en algunos casos usado como formateador o según un requerimiento.

Espero les ayude.

Añadir nuevo comentario