Crear un bloque personalizado con Advanced Custom Fields

Crear bloques personalizados para páginas web de clientes es una opción muy práctica y para la que no es imprescindible saber React.


por

En el artículo de hoy vamos a preparar el mismo bloque que veíamos hace unos días para mostrar un webinar con Genesis Custom Blocks, pero lo haremos utilizando Advanced Custom Fields.

ACF es el plugin más popular para trabajar con campos personalizados, y en su versión PRO nos permite crear también bloques de forma sencilla sin necesidad casi de tocar código.

Descripción del bloque

En este caso el objetivo es el mismo que ya veíamos, un bloque donde mostrar título del webinar, fecha, embed del video y descripción, además de poder mostrarlo en una ventana modal y restringirlo a usuarios que han iniciado sesión, como habíamos visto.

Genesis custom blocks example

Paso 1: Crear el bloque

Lo primero que haremos es registrar el bloque mediante acf_register_block_type, indicando el nombre, título, descripción, etc…

Esta es la parte que más difiere de lo que ya habíamos visto, ya que con Genesis Custom Blocks lo hacemos mediante la interfaz gráfica en el administrador y con ACF debemos añadir el código, pero por contra nos da opciones adicionales como añadir la ruta para nuestro CSS y JS personalizado o datos de ejemplo para la vista previa del bloque.

En el momento de registrar el bloque, le indicaremos la ruta al php donde tendremos el renderizado del HTML y los campos creados.

template-parts/blocks/webinar/webinar.php

Y en ese caso la ruta para los archivos adicionales necesarios:

'enqueue_style' => get_stylesheet_directory_uri() . '/template-parts/blocks/webinar/webinar.css',

'enqueue_script' => get_stylesheet_directory_uri() . '/template-parts/blocks/webinar/webinar.js',

Nota: aunque en este ejemplo le hemos puesto el mismo nombre a los 3 archivos, no es necesario que el .js y .css tengan se llamen igual, ni que estén en la misma carpeta que el bloque, pero se aconseja para tener el código bien organizado en el caso de tener varios bloques.

2. Crear los campos en ACF necesarios

Si estás acostumbrado a utilizar ACF este paso te va a ser muy sencillo ya que se trata de ir creando los campos personalizados que necesitamos para el bloque, cada uno con su formato y características.

ACF Blocks webinar

Lo único que deberemos tener en cuenta, es que en Location asignaremos estos campos a un condicional para que se muestren si el Block es igual al que hemos creado:

ACF Blocks

Recuerda que debemos registrar antes el bloque como hemos visto en el punto 1 para que nos aparezca en el desplegable como opción

3- Crear los archivos de plantilla PHP, CSS y JS necesarios para mostrar el bloque

Una vez registrado el bloque y creados los campos necesarios, crearemos los archivos que indicábamos como parámetros para renderizarlo y mostrarlo como queramos en la web.

En este ejemplo, tendremos que crear dentro de nuestro tema o tema hijo, las carpetas /template-parts/blocks/webinar, y dentro los siguientes archivos:

1- webinar.php

En este archivo lo que haremos es recoger los valores de los campos que hemos creado, con get_field() de igual forma que con campos personalizados normales, y mostrarlos dentro de la estructura HTML/PHP que queramos.

Por una parte le asignamos una capa que englobará todo el bloque, al que le asignaremos el ID y la clase que podrá indicar el usuario a través del editor de WP, además de la alineación que le interese.

...
// Create id attribute allowing for custom "anchor" value.
$id_block = 'webinar-' . $block['id'];
if ( ! empty( $block['anchor'] ) ) {
	$id_block = $block['anchor'];
}
// Create class attribute allowing for custom "className" and "align" values.
$class_name = 'webinar';
if ( ! empty( $block['className'] ) ) {
	$class_name .= ' ' . $block['className'];
}
if ( ! empty( $block['align'] ) ) {
	$class_name .= ' align' . $block['align'];
}
?>
<div id="<?php echo esc_attr( $id_block ); ?>" class="esl-webinar-block <?php echo esc_attr( $class_name );
...

Y luego recogeremos y mostraremos los valores de los campos, ya sea para mostrarlos, como para utilizar su valor posteriormente:

...
<h3><?php echo esc_html( get_field( 'titulo-webinar' ) ); ?></h3>
<p class="fecha"><?php echo esc_html( get_field( 'fecha-webinar' ) ); ?></p>
<?php
$previa      = get_field( 'imgprevia' );
$restringido = get_field( 'restringido' );
$codigo      = get_field( 'codigo-video' );
....

(Al final del artículo tenéis el código completo de los 3 archivos utilizados)

ACF Bloque

2 – webinar.css y webinar.js

Estos dos archivos que hemos creado para este ejemplo, contendrían los estilos y scripts necesarios para que el bloque tenga la funcionalidad que buscamos, que en este caso sería mostrar una imagen previa del video, y al clicar se mostrara en una ventana modal.

Nota: según qué tipo de bloques estés preparando, en la mayoría de ocasiones no vas a requerir código JavaScript adicional, por lo que ese archivo .js no va a ser necesario.

4- Revisar y completar

Una vez ya tengamos el PHP, CSS y JS si es necesario, listos, ya podremos probar nuestro bloque y ver que funciona correctamente en el editor y se muestra en el front como queremos.

Os dejo el código completo del ejemplo para que podáis probarlo.

webinar.php
<?php
/**
 * WEBINAR Block Template.
 *
 * @param   array $block The block settings and attributes.
 * @param   string $content The block inner HTML (empty).
 * @param   bool $is_preview True during AJAX preview.
 * @param   (int|string) $post_id The post ID this block is saved to.
 */
// Create id attribute allowing for custom "anchor" value.
$id_block = 'webinar-' . $block['id'];
if ( ! empty( $block['anchor'] ) ) {
	$id_block = $block['anchor'];
}
// Create class attribute allowing for custom "className" and "align" values.
$class_name = 'webinar';
if ( ! empty( $block['className'] ) ) {
	$class_name .= ' ' . $block['className'];
}
if ( ! empty( $block['align'] ) ) {
	$class_name .= ' align' . $block['align'];
}
?>
<div id="<?php echo esc_attr( $id_block ); ?>" class="esl-webinar-block <?php echo esc_attr( $class_name ); ?>">
<h3><?php echo esc_html( get_field( 'titulo-webinar' ) ); ?></h3>
<p class="fecha"><?php echo esc_html( get_field( 'fecha-webinar' ) ); ?></p>
<?php
$previa      = get_field( 'imgprevia' );
$restringido = get_field( 'restringido' );
$codigo      = get_field( 'codigo-video' );
if ( '' !== $codigo ) {
	if ( $restringido && ! is_user_logged_in() ) {
		echo 'Contenido restringido';
	} else {
		if ( '' !== $previa ) {
			?>
			<img src="<?php echo esc_url( get_field( 'imgprevia' ) ); ?>" id="previewvideo" />
			<?php
		} else {
			?>
			<img src="http://img.youtube.com/vi/<?php echo esc_attr( get_field( 'codigo-video' ) ); ?>/maxresdefault.jpg" id="previewvideo" />
			<?php
		}
		?>

	<div id="videoModal" class="modal">
	<div class="modal-content">
	<iframe src="https://www.youtube.com/embed/<?php echo get_field( 'codigo-video' ); ?>" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" id="ifrmVideo"></iframe>
	<span class="close" onclick="cerrarVideo();">&times;</span>
	</div>
	</div>
	<?php } ?>
<div class="review">Resumen: <?php echo esc_html( get_field( 'resumen' ) ); ?></div>
</div>
	<?php
}
?>
webinar.css
.esl-webinar-block {
    background:#f7f7f7;
    padding: 20px 40px;
    margin-bottom: 20px;
}
.esl-webinar-block img {
    width: 100%; 
    margin: 20px auto;
    cursor: pointer;
}
.esl-webinar-block .fecha {
    font-size: 15px; 
    margin: 5px;
}
.esl-webinar-block .review {
    font-size: 15px;
    padding: 20px;
}
/* ------------------------------------------------ */
/* VENTANA MODAL VIDEO*/
/* ------------------------------------------------ */
/* ------------------------------------------------ */
 
 .modal {
    display: none; /* Hidden by default */
    position: fixed; /* Stay in place */
    z-index: 1; /* Sit on top */
    left: 0;
    top: 0;
    width: 100%; /* Full width */
    height: 100vh; /* Full height */
    min-height: 500px;
    overflow: auto; /* Enable scroll if needed */
    background-color: rgb(0,0,0); /* Fallback color */
    background-color: rgba(0,0,0,0.4); /* Black w/ opacity */
  }
   
  .modal-content {
    background-color: #000;
    margin: 5% auto; /* 15% from the top and centered */
    padding: 20px;
    border: 1px solid #888;
    width: 80%; 
    height: 100vh;
    text-align: center;
  }
  
  .modal iframe {
    border: none;
    margin: 50px auto 0 auto;
    width: 700px;
    height: 500px;
    max-height: 100vh;
 }
 @media only screen and (max-width: 600px) {
    .modal iframe {
        width: auto;
        height: 100vh;
        margin: 10px auto;
    }
}

webinar.js
var previewvideo = document.getElementById('previewvideo');
var modal = document.getElementById("videoModal"); 
var video = document.getElementById("ifrmVideo");  
var span = document.getElementsByClassName("close")[0];
var srcVideo = video.getAttribute("src", video);

 
previewvideo.onclick = function(event) {
    jQuery('#videoModal').toggle('slow');
}
 
function cerrarVideo() {
  video.setAttribute("src", srcVideo);
  jQuery('#videoModal').toggle('slow');
}
 
window.onclick = function(event) {
  if (event.target == modal) { 
    video.setAttribute("src", srcVideo);
    jQuery('#videoModal').toggle('slow');
  }
} 

Como podrás comprobar, el CSS y el JS son exactamente los mismos que habíamos visto para el ejemplo de Genesis Custom Blocks, lo único que cambia es la forma de recoger el valor de los campos en el php.

¿Eres implementador o desarrollador WordPress?

En la Zona DPW encontrarás más recursos, tutoriales, plantillas, y una biblioteca de snippets para poder utilizar en tu día a día y ganar tiempo en tu trabajo:

ACCEDER AHORA

Comentarios

4 respuestas a «Crear un bloque personalizado con Advanced Custom Fields»

  1. Avatar de Carlos M. Díaz Honrado

    |

    Hola Esther y gracias por el post. Dos dudas:
    1.- He seguido las instrucciones y todo va correctamente, en el Backoffice se ve el bloque, se edita y todo es correcto en modo «formulario» pero al darle a la visualización previa no sale nada 🙁 Tampoco se ve el bloque en el front :'( Nota: he temido que crear las carpetas /template-parts/blocks/webinar ya que mi child, el htheme de asithemes, no las tenía.
    2.- ¿Cómo se añadiría un color picker?

    Gracias
    Seguimos!!!
    Feliz jueves y Feliz Navidad

    1. Avatar de esther

      |

      Hola Carlos!

      1. ¿Has creado el archivo webinar.php con el renderizado del bloque para mostrarlo en el front con la estructura que necesitas?
      2. ACF tiene un campo específico para poder añadir un color picker: https://www.advancedcustomfields.com/resources/color-picker/

      Felices Fiestas!!

  2. Avatar de Jose Alberto Arruego

    |

    Gracias por tu artículo Esther.
    Creo que en el código, al tomar el valor de la ruta de la imagen, debería añadirse get_field( ‘imgprevia’ )[‘url’]
    En mi versión actual de ACF devuelve el valor de imagen como un array y hay que extraer la url
    Un saludo

    1. Avatar de esther

      |

      Hola Jose Alberto,
      El campo imagen puedes escoger que quieres que devuelva, si url, array, objeto…. como bien dices, en el ejemplo está configurado para que devuelva directamente la URL, pero si lo tienes como array, hay que indicarle el [‘url’] para que funcione correctamente.

      Saludos!