Esse post é o terceiro de uma série de posts sobre o blocos Gutenberg customizados. Nesse tutorial vamos abordar como trabalhar com atributos em posts customizados. Nos posts anteriores vimos como registrar o nosso bloco customizado e adicionar um estilo ao nosso markup. Agora vamos entender como os atributos funcionam dentro do WordPress. Caso ainda não viu os posts anteriores você confere aqui:

Atributos

Até o momento, nos posts anteriores, quando registramos o nosso primeiro bloco passamos apenas um paragrafo estático, mas caso queiramos dar a possibilidade para o usuário cadastrar uma informação dinamicamente através do editor como serão os próximos passos? Vimos durante a chamada da função edit podemos receber um objeto com propriedades relacionadas ao nosso bloco e uma dessas informações é a propriedade attributes. Para trabalhar com a edição de conteúdo vamos trabalhar com alguns componentes do WordPress.

Componentes

Os blocos muitas vezes repetem a mesma complexidade, isso nos permite aplicar a reutilização de certos recursos, para simplificar a edição de conteúdo, o core do WordPress tem uma série componentes React que realizam tarefas específicas, mas não se assuste você não precisa aprender React para utilizar esse recursos. Mas meu conselho se você que trabalhar de forma mais produtiva é uma tecnologia que ajuda bastante, mas o foco desse tutorial vamos trabalhar com EcmaScript5, Dentro dos componentes vamos abordar dois componentes:

RichText

Ele irá renderizar para nos um input editável com a possibilidade de inclusa de texto e links. Dentro do componente RichText temos as seguintes propriedades:

  • value: espera um valor do tipo string, será o conteúdo armazenado ate o momento, podendo ser texto ou markup valido.
  • onChange: esse atributo espera uma função, será o callback responsável quando o valor do atributo sofre uma alteração
  • placeholder: O valor do campo quando estiver vazio. isso é válido tanto para o input text ou textarea o valor será o mesmo
  • multiline: Se o bloco irá permitir que o usuário cadastre multiplas linhas quando presionar enter, quando desabilitado o cada enter irá criar um novo bloco.

BlockControls

Quando nosso bloco é renderizado dentro do editor, uma barra de ferramentas é exibida com algumas opções relacionadas ao bloco selecionado, por exemplo, caso queiramos exibir opções de alinhamento de texto ao nosso bloco passamos o elemento responsável por alinhamento. O BlockControls espera o seguinte:

  • icon: slug do dashicon para ser mostrado na barra de controle
  • title: um título será exibido em forma de tooltip para o usuário
  • subscript: Um texto opcional para ser exibido adjacente ao ícone da barra de controle
  • isActive: um booleano para definir se o barra de controle será selecionada ou não por default.

Para esse tutorial vamos registrar dois blocos, primeiro exemplo(script.js) apenas com um richText component e o segundo bloco fazendo o uso do blockControl e richText(script-controls.js).

script.js

/**
 * 1 - Criando primeiro bloco Gutenberg com ES5: parte 03
 * 	-	 carregando atributos
 */
( function( blocks, element, editor ) {
	var el = element.createElement,
	RichText = editor.RichText;

	//registrando nosso bloco
	blocks.registerBlockType( 'fellyph/tutorial-03', {
		title: 'Primeiro bloco Gutenberg: Parte 03',
		icon: 'smiley',
		category: 'layout',
		
		//registrando o tipo de bloco que iremos trabalhar
		attributes: {
			content: {
				type: 'string',
				source: 'html',
				selector: 'p',
			}
		},
		
		// função responsável por exibir nosso bloco no editor
		edit: function(props) {
			var content = props.attributes.content;

			// função responsável por acompanhar as mudanças do nosso atributo
			function onChangeContent( newContent ) {
					props.setAttributes( { content: newContent } );
			}
			
			// agora retornamos um elemento RichText ao invés de um parâgrafo
			return el(
				RichText,
				{
					tagName: 'p',
					className: props.className,
					onChange: onChangeContent,
					value: content,
				}
			);
		},

		save: function(props) {
			return el(
				RichText.Content , {
					tagName: 'p',
					className: props.className,
					value: props.attributes.content,
				}
			);
		},
	});
}(
	window.wp.blocks,
	window.wp.element,
	window.wp.editor
) );

Como podemos ver no código acima, vamos ter mais uma dependência a classe editor do WordPress presente no script wp-editor, nela vamos encontrar os componentes relacionados a edição de conteúdo. Próximo passo adicionamos em uma variável nosso RichText, seguindo nosso código dentro do registerBlockType temos algumas alterações, adicionamos uma nova propriedade attributes ele é responsável pela configuração do nosso atributo. Ela merece um post específico só falando sobre

Mas voltando para o nosso tutorial definimos a configuração do atributo content esse nome pode ser qualquer um, por exemplo, “conteúdo”. Para esse atributo passamos um objeto de configuração como o tipo do dado(type), a fonte que iremos receber do editor(source), valores padrões(default) entre outras informações.

Dentro da função do edit, o nosso elemento RichText definimos os atributos tagName, className, onChange, value. Também criamos uma função onChangeContent ela é necessária por conta de um conceito do React de controle de estado, precisamos implementar um controlled component para isso, um resumo bem grosseiro, precisamos conectar o valor do input com o estado do component.

Index.php

Algumas diferenças na implementação do index.php, são o registro de dois blocos e quando registramos nosso script precisar adicionar a dependência ao ‘wp-editor’.

<?php

/**
 * Plugin Name: Gutenberg tutorial
 * Plugin URI: https://github.com/fellyph/gutenberg-tutorials
 * Description: Este tutorial ensina como criar um bloco gutenberg https://blog.fellyph.com.br/wordpress-2/criando-seu-proprio-bloco-gutenberg/.
 * Version: 1.3
 * Author: fellyph
 */

defined( 'ABSPATH' ) || exit;

/**
 * 1 - Criando nosso primeiro bloco: Parte 03
 *    1.1 - Adicionando o recurso de cadastrar atributos
 * 		1.2 - Adicionando o bloco com block control
 */

function meu_primeiro_bloco_gutenberg_parte_03 () {

	if ( ! function_exists( 'register_block_type' ) ) {
		// Checamos se temos suporte a função register_block_type antes de tudo.
		return;
	}

	wp_register_script(
		'tutorial-03',
		plugins_url( 'script.js', __FILE__ ),
		array( 'wp-blocks', 'wp-element', 'wp-editor' ),
		filemtime( plugin_dir_path( __FILE__ ) . 'script.js' )
	);

	wp_register_script(
		'tutorial-03-alinhamento',
		plugins_url( 'script-controls.js', __FILE__ ),
		array( 'wp-blocks', 'wp-element', 'wp-editor' ),
		filemtime( plugin_dir_path( __FILE__ ) . 'script-controls.js' )
	);

	wp_register_style(
		'style-editor',
		plugins_url( 'editor-style.css', __FILE__ ),
		array('wp-edit-blocks'),
		filemtime( plugin_dir_path( __FILE__ ) . 'editor-style.css' )
	);

	wp_register_style(
		'style-frontend',
		plugins_url( 'style.css', __FILE__ ),
		filemtime( plugin_dir_path( __FILE__ ) . 'style.css' )
	);

	register_block_type( 'fellyph/tutorial-03', array(
		'style' => 'style-frontend',
		'editor_script' => 'tutorial-03',
		'editor_style' => 'style-editor'
	));

	register_block_type( 'fellyph/tutorial-03-alinhamento', array(
		'style' => 'style-frontend',
		'editor_script' => 'tutorial-03-alinhamento',
		'editor_style' => 'style-editor'
	));
}

add_action( 'init', 'meu_primeiro_bloco_gutenberg_parte_03' );

Um ponto importante em nosso script, quando registramos um novo id(fellyph/tutorial-03-alinhamento e fellyph/tutorial-03) para nosso bloco precisamos atualizar o nosso seletores CSS:

.wp-block-fellyph-tutorial-03-alinhamento,
.wp-block-fellyph-tutorial-03 {
  background: #12c2e9;
  border: 3px solid #666;
  box-shadow: 0 0 0 #666;
}

.wp-block-fellyph-tutorial-03-alinhamento:hover,
.wp-block-fellyph-tutorial-03:hover {
  transform: rotate3d(0, 0, 0, 0);
}

script-controls.js

/**
 * 1 - Criando primeiro bloco Gutenberg com ES5: parte 03
 * 	-	 carregando atributos com BlockControls
 */
( function( blocks, element, editor ) {
	var el = element.createElement,
	RichText = editor.RichText,
	AlignmentToolbar = editor.AlignmentToolbar,
	BlockControls = editor.BlockControls;

	//registrando nosso bloco
	blocks.registerBlockType( 'fellyph/tutorial-03-alinhamento', {
		title: 'Bloco com controle de alinhamento',
		icon: 'welcome-view-site',
		category: 'layout',
		
		//registrando os atributos que iremos trabalhar
		attributes: {
			content: {
				type: 'string',
				source: 'html',
				selector: 'p'
			},
			alinhamento: {
				type: 'string',
				default: 'none'
			},
		},
		
		// unção responsável por exibir nosso bloco no editor
		edit: function(props) {
			var content = props.attributes.content;
			var alinhamento = props.attributes.alinhamento;

		// função responsável por acompanhar as mudanças do nosso atributo
		function onChangeContent( newContent ) {
					props.setAttributes( { content: newContent } );
			}

			function onChangeAlignment (nextAlign ) {
				props.setAttributes( { alinhamento: nextAlign } );
			}

		// agora retornamos um array por que estamos utilizando dois componentes
		return [
			el( BlockControls, 
				{ key: 'controls' },
				el( AlignmentToolbar, {
							value: alinhamento,
							onChange: onChangeAlignment
					})
        ),
				el(
					RichText,
					{
						key: 'richtext',
						tagName: 'p',
						style: { textAlign: alinhamento },
						className: props.className,
						onChange: onChangeContent,
						value: content,
						placeholder: 'Insira seu nome aqui'
					}
			),
			];
		},

		save: function(props) {

			return el(
				RichText.Content , {
					tagName: 'p',
					className: props.className,
					style: { textAlign: props.attributes.alinhamento },
					value: props.attributes.content,
				}
			);
		},
	});
}(
	window.wp.blocks,
	window.wp.element,
	window.wp.editor
) );

No código acima temos alguns pontos importantes diferente do primeiro código, em atributos adicionamos um novo valor, “alinhamento” ele será do tipo string e terá um valor padrão ‘none’.

Dentro da função edit adicionamos uma função para acompanhar as mudanças desse componente onChangeAlignment onde atualizamos o valor do atributo referente ao alinhamento.

Agora quando retornamos o nosso bloco utilizamos um array para passar mais de um componente, por que precisamos de um blockControls para passar as configurações necessárias e um RichText para o usuário cadastrar um texto.

Dentro do nosso blockControls podemos também passar uma série de outros componentes relacionados a configurações mas para esse caso vamos utilizar apenas o AlignmentToolbar :

Em seguida conectamos o valor do aligmentToolbar ao nosso RichText, tanto no preview na função edit quando no nosso front-end na função save, definindo o atributo style: { textAlign: alinhamento }.

E esse será o resultado dos dois blocos que criamos aqui:

Exemplo de RichText
bloco utilizando placeholder
Exemplo com BlockControls e AligmentToolbar

O código desse tutorial você irá encontrar no meu git, para cada tutorial estou criando uma branch:

https://github.com/fellyph/Gutenberg-tutorials/tree/tutoriais/gutenberg-03

Qualquer feedback deixe aqui seu comentário e até o próximo tutorial

Referências:

Participe da discussão

4 comentários

    1. Olá Ramon, você quer dizer como código é exibido ou colocar mais comentários nos códigos? Sobre a exibição eu estou usando o bloco default de exibição de código do WordPress, já dei uma olhada pra ver um bom compatível com WordPress
      . Sobre o código Alguns elementos que já comentei em posts anteriores aí eu não repito a explicação nesse caso. Só dar uma conferida nos primeiros posts

      1. Eu gosto de cadastrar os códigos como Gists e fazer o embed, foi o melhor meio de syntax highlight que encontrei, e ainda me ajudou a ficar organizado, já que dá para cadastrar os vários trechos de um tutorial em um Gist com vários arquivos.

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *