Este post é a parte 14 de 15 da Série WordPress Extremo
Série
WordPress Extremo
WordPress Extremo
- Como Criar um Plugin WordPress com Composer e PSR-4 – WordPress Extremo Dia 1
- Como Usar Serviços em Plugins para Código Limpo e Desacoplado – WordPress Extremo Dia 2
- Como Usar Repositórios em Plugins para Separar Lógica de Dados – WordPress Extremo Dia 3
- Injeção de Dependência Manual em Plugins WordPress – WordPress Extremo Dia 4
- Hooks Avançados no WordPress: apply_filters, do_action e boas práticas
- Criando Comandos WP-CLI Personalizados para Plugins WordPress
- Criando Blocos Personalizados com Gutenberg e React
- Estilizando Blocos Gutenberg com CSS e Classes Dinâmicas
- Cor, Alinhamento e Estilo Dinâmico com Gutenberg + React
- Ícones, Imagens e Classes Personalizadas no Gutenberg
- Componentes Reutilizáveis e Atributos Compostos em Blocos Gutenberg
- Conectando Blocos com a REST API do WordPress
- Bloco Dinâmico com Renderização no Servidor
- Filtrando Posts por Categoria no Editor do Bloco
- Bloco de Posts com Filtro por Múltiplas Categorias
Hoje vamos aprimorar o bloco wp24h/posts
, adicionando um controle no editor para que o usuário possa selecionar categorias específicas dos posts que serão listados. Isso exige:
- Consultar as categorias via REST API
- Usar o componente
SelectControl
no painel lateral do editor - Passar essa informação como atributo
- Usar esse atributo no
render_callback
para exibir os posts filtrados
🧱 Estrutura esperada do bloco após esse dia:
blocks/
└── posts/
├── block.json
├── index.js
├── edit.js
├── save.js
└── components/
└── PostList.js
inc/
└── render/
└── render-posts.php
🧩 Código do bloco atualizado:
block.json
{
"apiVersion": 2,
"name": "wp24h/posts",
"title": "Lista de Posts WP24H",
"category": "widgets",
"icon": "list-view",
"description": "Um bloco que exibe os últimos posts via REST API.",
"attributes": {
"quantidade": { "type": "number", "default": 3 },
"categoria": { "type": "number", "default": 0 }
},
"supports": { "html": false }
}
edit.js
import { useBlockProps, InspectorControls } from '@wordpress/block-editor';
import { PanelBody, RangeControl, SelectControl } from '@wordpress/components';
import { useState, useEffect } from '@wordpress/element';
import apiFetch from '@wordpress/api-fetch';
import PostList from './components/PostList';
export default function Edit({ attributes, setAttributes }) {
const { quantidade = 3, categoria = 0 } = attributes;
const [posts, setPosts] = useState([]);
const [categorias, setCategorias] = useState([]);
// Busca categorias (uma vez só)
useEffect(() => {
apiFetch({ path: '/wp/v2/categories' })
.then((data) => setCategorias([{ id: 0, name: 'Todas' }, ...data]))
.catch((err) => {
console.error('Erro ao carregar categorias:', err);
setCategorias([{ id: 0, name: 'Todas' }]);
});
}, []);
// Busca posts sempre que quantidade ou categoria mudar
useEffect(() => {
const path = categoria === 0
? `/wp/v2/posts?per_page=${quantidade}`
: `/wp/v2/posts?per_page=${quantidade}&categories=${categoria}`;
apiFetch({ path })
.then((data) => setPosts(data))
.catch((err) => {
console.error('Erro ao carregar posts:', err);
setPosts([]);
});
}, [quantidade, categoria]);
return (
<>
<InspectorControls>
<PanelBody title="Configurações">
<RangeControl
label="Quantidade de posts"
min={1}
max={10}
value={quantidade}
onChange={(val) => setAttributes({ quantidade: val })}
/>
<SelectControl
label="Categoria"
value={categoria}
options={categorias.map((cat) => ({
label: cat.name,
value: cat.id
}))}
onChange={(val) => setAttributes({ categoria: parseInt(val) })}
/>
</PanelBody>
</InspectorControls>
<div {...useBlockProps()}>
<PostList posts={posts} />
</div>
</>
);
}
render-posts.php
function wp24h_render_block_posts($attributes) {
$qtd = isset($attributes['quantidade']) ? intval($attributes['quantidade']) : 3;
$cat = isset($attributes['categoria']) ? intval($attributes['categoria']) : 0;
$args = [
'post_type' => 'post',
'posts_per_page' => $qtd,
];
if ($cat > 0) {
$args['cat'] = $cat;
}
$query = new WP_Query($args);
if (!$query->have_posts()) {
return '<p>Sem posts recentes no momento.</p>';
}
ob_start();
echo '<ul class="wp24h-post-list-frontend">';
while ($query->have_posts()) {
$query->the_post();
echo '<li><a href="' . get_permalink() . '">' . get_the_title() . '</a></li>';
}
echo '</ul>';
wp_reset_postdata();
return ob_get_clean();
}