Usar componentes web en WordPress es más fácil de lo que piensas | Programar Plus

Ahora que hemos visto que los componentes web y los componentes web interactivos son más fáciles de lo que cree, echemos un vistazo a agregarlos a un sistema de administración de contenido, a saber, WordPress.

Hay tres formas principales en que podemos agregarlos. Primero, a través de la entrada manual en el sitio.colocándolos directamente en widgets o bloques de texto, básicamente en cualquier lugar donde podamos colocar otro HTML. En segundo lugar, podemos agregarlos como salida de un tema en un archivo de tema. Y, finalmente, podemos agregarlos como salida de un bloque personalizado.

Cargando los archivos del componente web

Ahora, de cualquier manera que terminemos agregando componentes web, hay algunas cosas que debemos asegurarnos:

  1. la plantilla de nuestro elemento personalizado está disponible cuando la necesitamos,
  2. cualquier JavaScript que necesitemos esté correctamente en cola, y
  3. cualquier estilo no encapsulado que necesitemos se pone en cola.

Estaremos agregando el <zombie-profile> componente web de mi artículo anterior sobre componentes web interactivos. Echa un vistazo al código en CodePen.

Vayamos a ese primer punto. Una vez que tenemos la plantilla, es bastante fácil agregarla al tema de WordPress. footer.php archivo, pero en lugar de agregarlo directamente en el tema, sería mejor conectarlo wp_footer para que el componente se cargue independientemente del footer.php archivo e independiente del tema general, suponiendo que el tema utiliza wp_footer, que la mayoría hace. Si la plantilla no aparece en su tema cuando lo prueba, verifique que wp_footer se llama en tu tema footer.php archivo de plantilla.

<?php function diy_ezwebcomp_footer() { ?>
  <!-- print/echo Zombie profile template code. -->
  <!-- It's available at https://codepen.io/undeadinstitute/pen/KKNLGRg -->
<?php } 
add_action( 'wp_footer', 'diy_ezwebcomp_footer');

Lo siguiente es poner en cola el JavaScript de nuestro componente. Podemos agregar el JavaScript a través de wp_footer también, pero poner en cola es la forma recomendada de vincular JavaScript a WordPress. Así que pongamos nuestro JavaScript en un archivo llamado ezwebcomp.js (ese nombre es totalmente arbitrario), pegue ese archivo en el directorio JavaScript del tema (si lo hay), y póngalo en cola (en el functions.php Archivo).

wp_enqueue_script( 'ezwebcomp_js', get_template_directory_uri() . '/js/ezwebcomp.js', '', '1.0', true );

Querremos asegurarnos de que el último parámetro esté configurado en true , es decir, carga el JavaScript antes de la etiqueta del cuerpo de cierre. Si lo cargamos en la cabeza, no encontrará nuestra plantilla HTML y se pondrá de mal humor (provocará un montón de errores).

Si puede encapsular completamente su componente web, puede omitir el siguiente paso. Pero si usted (como yo) no puede hacerlo, deberá poner en cola esos estilos no encapsulados para que estén disponibles donde sea que se use el componente web. (De manera similar a JavaScript, podríamos agregar esto directamente al pie de página, pero la forma recomendada de hacerlo es poner en cola los estilos). Así que pondremos en cola nuestro archivo CSS:

wp_enqueue_style( 'ezwebcomp_style', get_template_directory_uri() . '/ezwebcomp.css', '', '1.0', 'screen' );

Eso no fue demasiado difícil, ¿verdad? Y si no planea que otros usuarios que no sean administradores lo usen, debe estar listo para agregarlos donde los desee. Pero ese no es siempre el caso, ¡así que seguiremos adelante!

No filtre su componente web

WordPress tiene algunas formas diferentes de ayudar a los usuarios a crear HTML válido y evitar que su tío Eddie pegue esa imagen “divertida” que obtuvo de Shady Al directamente en el editor (completa con scripts para pwnear a cada uno de sus visitantes).

Entonces, al agregar componentes web directamente en bloques o widgets, debemos tener cuidado con el filtrado de código incorporado de WordPress. Deshabilitarlo todo junto permitiría que el tío Eddie (y, por extensión, Shady Al) se vuelva loco, pero podemos modificarlo para permitir que nuestro increíble componente web atraviese la puerta que (afortunadamente) mantiene al tío Eddie fuera.

Primero, podemos usar el wp_kses_allowed filter para agregar nuestro componente web a la lista de elementos que no se deben filtrar. Es como si estuviéramos en la lista blanca del componente, y lo hacemos al agregarlo a la matriz de etiquetas permitidas que se pasa a la función de filtro.

function add_diy_ezwebcomp_to_kses_allowed( $the_allowed_tags ) {
  $the_allowed_tags['zombie-profile'] = array();
}
add_filter( 'wp_kses_allowed_html', 'add_diy_ezwebcomp_to_kses_allowed');

Estamos agregando una matriz vacía a la <zombie-profile> porque WordPress filtra los atributos además de los elementos, lo que nos lleva a otro problema: el slot atributo (así como part y cualquier otro atributo de componente web que pueda usar) no están permitidos de forma predeterminada. Por lo tanto, tenemos que permitirlos explícitamente en cada elemento en el que anticipe usarlos y, por extensión, en cualquier elemento al que su usuario decida agregarlos. (Espera, esas listas de elementos no son las mismas a pesar de que las repasaste seis veces con cada usuario… ¿quién sabía?) Por lo tanto, a continuación he establecido slot a true sobre <span>, <img> y <ul>, los tres elementos que estoy poniendo en ranuras en el <zombie-profile> componente. (también puse part a true en elementos span para que yo también pudiera dejar pasar ese atributo).

function add_diy_ezwebcomp_to_kses_allowed( $the_allowed_tags ) {
  $the_allowed_tags['zombie-profile'] = array();
  $the_allowed_tags['span']['slot'] = true;
  $the_allowed_tags['span']['part'] = true;
  $the_allowed_tags['ul']['slot'] = true;
  $the_allowed_tags['img']['slot'] = true;
  return $the_allowed_tags;
}
add_filter( 'wp_kses_allowed_html', 'add_diy_ezwebcomp_to_kses_allowed');

También podríamos habilitar el slot (y part) atributo en todos los elementos permitidos con algo como esto:

function add_diy_ezwebcomp_to_kses_allowed($the_allowed_tags) {
  $the_allowed_tags['zombie-profile'] = array();
  foreach ($the_allowed_tags as &$tag) {
    $tag['slot'] = true;
    $tag['part'] = true;
  }
  return $the_allowed_tags;
}
add_filter('wp_kses_allowed_html', 'add_diy_ezwebcomp_to_kses_allowed');

Lamentablemente, hay una posible arruga más con esto. Es posible que no se encuentre con esto si todos los elementos que está colocando en sus ranuras son elementos en línea/frases, pero si tiene un elemento de nivel de bloque para colocar en su componente web, probablemente tendrá una pelea a puñetazos con el analizador de bloques. en el Editor de código. Puede que seas mejor luchador que yo, pero yo siempre perdía.

El editor de código es una opción que le permite inspeccionar y editar el marcado de un bloque.

Por razones que no puedo explicar completamente, el analizador del lado del cliente asume que el componente web solo debe tener elementos en línea dentro de él, y si coloca un <ul> o <div>, <h1> o algún otro elemento de nivel de bloque allí, moverá la etiqueta del componente web de cierre justo después del último elemento en línea/frase. Peor aún, según una nota en el Manual para desarrolladores de WordPress, actualmente “no es posible reemplazar el analizador del lado del cliente”.

Si bien esto es frustrante y es algo en lo que tendrá que capacitar a sus editores web, hay una solución. Si colocamos el componente web en un bloque HTML personalizado directamente en el Editor de bloques, el analizador del lado del cliente no nos dejará llorando en la acera, balanceándonos de un lado a otro y cuestionando nuestra capacidad para codificar… No es que eso haya sucedido alguna vez. cualquiera… particularmente no las personas que escriben artículos…

Componente el tema

La salida de nuestro elegante componente web en nuestro archivo de tema es sencillo, siempre y cuando no se actualice fuera del bloque HTML. Lo agregamos de la forma en que lo haríamos en cualquier otro contexto y, asumiendo que tenemos la plantilla, los scripts y los estilos en su lugar, las cosas simplemente funcionarán.

Pero digamos que queremos generar el contenido de una publicación de WordPress o un tipo de publicación personalizada en un componente web. Ya sabes, escribe una publicación y esa publicación es el contenido del componente. Esto nos permite usar el editor de WordPress para generar un archivo de <zombie-profile> elementos. Esto es excelente porque el editor de WordPress ya tiene la mayor parte de la interfaz de usuario que necesitamos para ingresar el contenido para uno de los <zombie-profile> componentes:

  • El título de la entrada puede ser el nombre del zombi.
  • Un habitual bloque de párrafo en el contenido de la publicación se puede usar para la declaración del zombi.
  • El Foto principal se puede usar para la foto de perfil del zombi.

¡Eso es la mayor parte! Pero aún necesitaremos campos para la edad del zombi, la fecha de infección y los intereses. Los crearemos con la función de campos personalizados integrada de WordPress.

Usaremos la parte de la plantilla que maneja la impresión de cada publicación, por ejemplo content.php, para generar el componente web. Primero, imprimiremos la apertura <zombie-profile> etiqueta seguida de la miniatura de la publicación (si existe).

<zombie-profile>
  <?php 
    // If the post featured image exists...
    if (has_post_thumbnail()) {
      $src = wp_get_attachment_image_url(get_post_thumbnail_id()); ?>
      <img src="https://css-tricks.com/using-web-components-in-wordpress-is-easier-than-you-think/<?php echo $src; ?>" slot="profile-image">
    <?php
    }
  ?>

A continuación, imprimiremos el título para el nombre.

<?php
  // If the post title field exits...
  if (get_the_title()) { ?>
  <span slot="zombie-name"><?php echo get_the_title(); ?></span>
  <?php
  }
?>

En mi código, probé si estos campos existen antes de imprimirlos por dos razones:

  1. Es solo una buena práctica de programación (en la mayoría de los casos) ocultar las etiquetas y los elementos alrededor de los campos vacíos.
  2. Si terminamos dando salida a un vacío <span> por el nombre (ej. <span slot="zombie-name"></span>), el campo se mostrará vacío en el perfil final en lugar de usar el texto, la imagen, etc. predeterminados integrados de nuestro componente web (si desea, por ejemplo, que los campos de texto estén vacíos si no tienen contenido, debe puede poner un espacio en el campo personalizado u omitir el if declaración en el código).

A continuación, tomaremos los campos personalizados y los colocaremos en las ranuras a las que pertenecen. Nuevamente, esto va a la plantilla de tema que genera el contenido de la publicación.

<?php
  // Zombie age
  $temp = get_post_meta(the_ID(), 'Age', true);
  if ($temp) { ?>
    <span slot="z-age"><?php echo $temp; ?></span>
    <?php
  }
  // Zombie infection date
  $temp = get_post_meta(the_ID(), 'Infection Date', true);
  if ($temp) { ?>
    <span slot="idate"><?php echo $temp; ?></span>
    <?php
  }
  // Zombie interests
  $temp = get_post_meta(the_ID(), 'Interests', true);
  if ($temp) { ?>
    <ul slot="z-interests"><?php echo $temp; ?></ul>
    <?php
  }
?>

Una de las desventajas de usar los campos personalizados de WordPress es que no puede hacer ningún formato especial. Un editor web no técnico que esté completando esto necesitaría escribir el HTML para los elementos de la lista (<li>) para todos y cada uno de los intereses de la lista. (Probablemente pueda sortear esta limitación de la interfaz utilizando un complemento de campo personalizado más robusto, como Campos personalizados avanzados, Pods o similar).

Finalmente. añadimos la declaración del zombi y el cierre <zombie-profile> etiqueta.

<?php
  $temp = get_the_content();
  if ($temp) { ?>
    <span slot="statement"><?php echo $temp; ?></span>
  <?php
  }
?>
</zombie-profile>

Debido a que estamos usando el cuerpo de la publicación para nuestra declaración, obtendremos un pequeño código adicional en el trato, como etiquetas de párrafo alrededor del contenido. Poner la declaración del perfil en un campo personalizado mitigará esto, pero dependiendo de sus propósitos, también puede ser un comportamiento previsto/deseado.

¡Luego puede agregar tantas publicaciones/perfiles de zombis como necesite simplemente publicando cada uno como una publicación!

Block party: componentes web en un bloque personalizado

Crear un bloque personalizado es una excelente manera de agregar un componente web. Sus usuarios podrán completar los campos requeridos y obtener esa magia del componente web sin necesidad de ningún código o conocimiento técnico. Además, los bloques son completamente independientes de los temas, por lo que realmente podríamos usar este bloque en un sitio y luego instalarlo en otros sitios de WordPress, ¡algo así como esperaríamos que funcione un componente web!

Hay dos partes principales de un bloque personalizado: PHP y JavaScript. También agregaremos un poco de CSS para mejorar la experiencia de edición.

Primero, el PHP:

function ez_webcomp_register_block() {
  // Enqueues the JavaScript needed to build the custom block
  wp_register_script(
    'ez-webcomp',
    plugins_url('block.js', __FILE__),
    array('wp-blocks', 'wp-element', 'wp-editor'),
    filemtime(plugin_dir_path(__FILE__) . 'block.js')
  );

  // Enqueues the component's CSS file
  wp_register_style(
    'ez-webcomp',
    plugins_url('ezwebcomp-style.css', __FILE__),
    array(),
    filemtime(plugin_dir_path(__FILE__) . 'ezwebcomp-style.css')
  );

  // Registers the custom block within the ez-webcomp namespace
  register_block_type('ez-webcomp/zombie-profile', array(
    // We already have the external styles; these are only for when we are in the WordPress editor
    'editor_style' => 'ez-webcomp',
    'editor_script' => 'ez-webcomp',
  ));
}
add_action('init', 'ez_webcomp_register_block');

El CSS no es necesario, ayuda a evitar que la imagen de perfil del zombi se superponga al contenido en el editor de WordPress.

/* Sets the width and height of the image.
 * Your mileage will likely vary, so adjust as needed.
 * "pic" is a class we'll add to the editor in block.js
*/
#editor .pic img {
  width: 300px;
  height: 300px;
}
/* This CSS ensures that the correct space is allocated for the image,
 * while also preventing the button from resizing before an image is selected.
*/
#editor .pic button.components-button { 
  overflow: visible;
  height: auto;
}

El JavaScript que necesitamos es un poco más complicado. Me he esforzado por simplificarlo tanto como sea posible y hacerlo lo más accesible posible para todos, así que lo he escrito en ES5 para eliminar la necesidad de compilar nada.

Mostrar código

(function (blocks, editor, element, components) {
  // The function that creates elements
  var el = element.createElement;
  // Handles text input for block fields 
  var RichText = editor.RichText;
  // Handles uploading images/media
  var MediaUpload = editor.MediaUpload;
    
  // Harkens back to register_block_type in the PHP
  blocks.registerBlockType('ez-webcomp/zombie-profile', {
    title: 'Zombie Profile', //User friendly name shown in the block selector
    icon: 'id-alt', //the icon to usein the block selector
    category: 'layout',
    // The attributes are all the different fields we'll use.
    // We're defining what they are and how the block editor grabs data from them.
    attributes: {
      name: {
        // The content type
        type: 'string',
        // Where the info is available to grab
        source: 'text',
        // Selectors are how the block editor selects and grabs the content.
        // These should be unique within an instance of a block.
        // If you only have one img or one <ul> etc, you can use element selectors.
        selector: '.zname',
      },
      mediaID: {
        type: 'number',
      },
      mediaURL: {
        type: 'string',
        source: 'attribute',
        selector: 'img',
        attribute: 'src',
      },
      age: {
        type: 'string',
        source: 'text',
        selector: '.age',
      },
      infectdate: {
        type: 'date',
        source: 'text',
        selector: '.infection-date'
      },
      interests: {
        type: 'array',
        source: 'children',
        selector: 'ul',
      },
      statement: {
        type: 'array',
        source: 'children',
        selector: '.statement',
      },
  },
  // The edit function handles how things are displayed in the block editor.
  edit: function (props) {
    var attributes = props.attributes;
    var onSelectImage = function (media) {
      return props.setAttributes({
        mediaURL: media.url,
        mediaID: media.id,
      });
    };
    // The return statement is what will be shown in the editor.
    // el() creates an element and sets the different attributes of it.
    return el(
      // Using a div here instead of the zombie-profile web component for simplicity.
      'div', {
        className: props.className
      },
      // The zombie's name
      el(RichText, {
        tagName: 'h2',
        inline: true,
        className: 'zname',
        placeholder: 'Zombie Name…',
        value: attributes.name,
        onChange: function (value) {
          props.setAttributes({
            name: value
          });
        },
      }),
      el(
        // Zombie profile picture
        'div', {
          className: 'pic'
        },
        el(MediaUpload, {
          onSelect: onSelectImage,
          allowedTypes: 'image',
          value: attributes.mediaID,
          render: function (obj) {
            return el(
              components.Button, {
                className: attributes.mediaID ?
                  'image-button' : 'button button-large',
                onClick: obj.open,
              },
              !attributes.mediaID ?
              'Upload Image' :
              el('img', {
                src: attributes.mediaURL
              })
            );
          },
        })
      ),
      // We'll include a heading for the zombie's age in the block editor
      el('h3', {}, 'Age'),
      // The age field
      el(RichText, {
        tagName: 'div',
        className: 'age',
        placeholder: 'Zombie's Age…',
        value: attributes.age,
        onChange: function (value) {
          props.setAttributes({
            age: value
          });
        },
      }),
      // Infection date heading
      el('h3', {}, 'Infection Date'),
      // Infection date field
      el(RichText, {
        tagName: 'div',
        className: 'infection-date',
        placeholder: 'Zombie's Infection Date…',
        value: attributes.infectdate,
        onChange: function (value) {
          props.setAttributes({
            infectdate: value
          });
        },
      }),
      // Interests heading
      el('h3', {}, 'Interests'),
      // Interests field
      el(RichText, {
        tagName: 'ul',
        // Creates a new <li> every time `Enter` is pressed
        multiline: 'li',
        placeholder: 'Write a list of interests…',
        value: attributes.interests,
        onChange: function (value) {
          props.setAttributes({
            interests: value
          });
        },
        className: 'interests',
      }),
      // Zombie statement heading
      el('h3', {}, 'Statement'),
      // Zombie statement field
      el(RichText, {
        tagName: 'div',
        className: "statement",
        placeholder: 'Write statement…',
        value: attributes.statement,
        onChange: function (value) {
          props.setAttributes({
            statement: value
          });
        },
      })
    );
  },

  // Stores content in the database and what is shown on the front end.
  // This is where we have to make sure the web component is used.
  save: function (props) {
    var attributes = props.attributes;
    return el(
      // The <zombie-profile web component
      'zombie-profile',
      // This is empty because the web component does not need any HTML attributes
      {},
      // Ensure a URL exists before it prints
      attributes.mediaURL &&
      // Print the image
      el('img', {
        src: attributes.mediaURL,
        slot: 'profile-image'
      }),
      attributes.name &&
      // Print the name
      el(RichText.Content, {
        tagName: 'span',
        slot: 'zombie-name',
        className: 'zname',
        value: attributes.name,
      }),
      attributes.age &&
      // Print the zombie's age
      el(RichText.Content, {
        tagName: 'span',
        slot: 'z-age',
        className: 'age',
        value: attributes.age,
    }),
      attributes.infectdate &&
      // Print the infection date
      el(RichText.Content, {
        tagName: 'span',
        slot: 'idate',
        className: 'infection-date',
        value: attributes.infectdate,
    }),
      // Need to verify something is in the first element since the interests's type is array
      attributes.interests[0] &&
      // Pint the interests
      el(RichText.Content, {
        tagName: 'ul',
        slot: 'z-interests',
        value: attributes.interests,
      }),
      attributes.statement[0] &&
      // Print the statement
      el(RichText.Content, {
        tagName: 'span',
        slot: 'statement',
        className: 'statement',
        value: attributes.statement,
    })
    );
    },
  });
})(
  //import the dependencies
  window.wp.blocks,
  window.wp.blockEditor,
  window.wp.element,
  window.wp.components
);

Conexión a componentes web

Ahora, ¿no sería genial si una persona de buen corazón, escritora de artículos y totalmente increíble creara una plantilla en la que usted pudiera simplemente conectar su componente web y usarla en su sitio? Bueno, ese tipo no estaba disponible (estaba ayudando a una organización benéfica o algo así), así que lo hice. Está en github:

Hágalo usted mismo: componentes web sencillos para WordPress

El complemento es una plantilla de codificación que registra su componente web personalizado, pone en cola los scripts y diseña el componente que necesita, proporciona ejemplos de los campos de bloque personalizados que podría necesitar e incluso se asegura de que las cosas tengan un estilo agradable en el editor. Pon esto en una nueva carpeta en /wp-content/plugins como instalaría manualmente cualquier otro complemento de WordPress, asegúrese de actualizarlo con su componente web particular, luego actívelo en WordPress en la pantalla “Complementos instalados”.

No es tan malo, ¿verdad?

Aunque parece mucho código, realmente estamos haciendo algunas cosas bastante estándar de WordPress para registrar y renderizar un componente web personalizado. Y, dado que lo empaquetamos como un complemento, podemos colocarlo en cualquier sitio de WordPress y comenzar a publicar perfiles de zombis al contenido de nuestro corazón.

Yo diría que el acto de equilibrio es tratar de hacer que el componente funcione tan bien en el editor de bloques de WordPress como lo hace en la interfaz. Habríamos podido eliminar esto con mucho menos código sin esa consideración.

Aún así, logramos obtener exactamente el mismo componente que creamos en mis artículos anteriores en un CMS, lo que nos permite instalar tantos perfiles de zombis en el sitio. Combinamos nuestro conocimiento de los componentes web con los bloques de WordPress para desarrollar un bloque reutilizable para nuestro componente web reutilizable.

¿Qué tipo de componentes creará para su sitio de WordPress? Me imagino que hay muchas posibilidades aquí y estoy interesado en ver lo que terminas haciendo.

Serie de artículos

  1. Los componentes web son más fáciles de lo que cree
  2. Los componentes web interactivos son más fáciles de lo que cree
  3. Usar componentes web en WordPress es más fácil de lo que piensas
(Visited 7 times, 1 visits today)