I am creating a Query Loop block that retrieves post type, similar to Gutenberg's, but for various reasons I need to create one.
Currently the code I am using is as follows and it works, but I would prefer the various internal blocks to use their own edit.js file.
Currently they use what is given in this file instead.
edit.js
/** * WordPress dependencies */ import { __ } from "@wordpress/i18n"; import { useBlockProps, useInnerBlocksProps, store as blockEditorStore, } from "@wordpress/block-editor"; import { useSelect } from "@wordpress/data"; import { store as coreStore } from "@wordpress/core-data"; import QueryInspectorControls from "./inspector-controls"; import React from "react"; /** * Edit component * * @param {Object} props * @param {Object} props.attributes * @param {Object} props.setAttributes * @param {string} props.clientId */ export default function Edit({ attributes, setAttributes, clientId }) { const { query } = attributes; const blockProps = useBlockProps(); // Get Posts const { posts, isResolving, templateBlock } = useSelect( (select) => { const { getEntityRecords, isResolving } = select(coreStore); const { getBlocks } = select(blockEditorStore); // Find block const innerBlocks = getBlocks(clientId); const template = innerBlocks.find( (block) => block.name === "prismatic/post-type-template", ); return { posts: getEntityRecords("postType", query.postType, { per_page: query.perPage, offset: query.offset, orderby: query.orderBy, order: query.order, _embed: true, ...(query.authors?.length && { author: query.authors.join(","), }), ...(query.search?.length && { search: query.search.join(" "), }), ...(query.postType === "page" && query.parents?.length && { parent: query.parents[0], }), ...(query.taxQuery && { tax_query: Object.entries(query.taxQuery) .filter(([key]) => !key.includes("_relation")) .map(([taxonomy, terms]) => ({ taxonomy, terms, operator: query.taxQuery[`${taxonomy}_relation`] === "AND" ? "AND" : "IN", })), }), }), isResolving: isResolving("getEntityRecords", [ "postType", query.postType, ]), templateBlock: template, }; }, [query, clientId], ); // Template const innerBlocksProps = useInnerBlocksProps( { style: { display: "none" }, }, { template: [["prismatic/post-type-template"]], allowedBlocks: ["prismatic/post-type-template"], }, ); // Item rendering function QueryPostTypeItem({ post, templateBlock }) { if (!templateBlock || !post) return null; return ( <div className={templateBlock.attributes.className || ""} data-id={post.id} > {templateBlock.innerBlocks.map((block) => { if (block.name === "prismatic/post-type-featured-image") { const imageUrl = post._embedded?.["wp:featuredmedia"]?.[0]?.source_url; const imageAlt = post._embedded?.["wp:featuredmedia"]?.[0]?.alt_text || ""; if (!imageUrl) return null; return ( <img key={block.clientId} src={imageUrl} alt={imageAlt} className={block.attributes.className || ""} /> ); } if (block.name === "prismatic/post-type-title") { const TagName = block.attributes.tagName || "p"; return ( <TagName key={block.clientId} className={block.attributes.className || ""} > {post.title.rendered} </TagName> ); } if (block.name === "prismatic/post-type-excerpt") { const excerpt = post.excerpt?.rendered || ""; const words = block.attributes.words || 25; const strippedExcerpt = excerpt.replace(/<\/?[^>]+(>|$)/g, ""); const trimmedExcerpt = strippedExcerpt.split(" ").slice(0, words).join(" ") + "..."; return ( <p key={block.clientId} className={block.attributes.className || ""} dangerouslySetInnerHTML={{ __html: trimmedExcerpt }} /> ); } if (block.name === "prismatic/post-type-button") { const text = block.attributes.text || __("Leggi tutto", "prismatic"); return ( <a key={block.clientId} className={block.attributes.className || ""} href={post.link} > {text} </a> ); } return null; })} </div> ); } // Loop function QueryPostTypeLoop({ posts, templateBlock }) { if (!posts) return null; return ( <> {posts.map((post) => ( <QueryPostTypeItem key={post.id} post={post} templateBlock={templateBlock} /> ))} </> ); } return ( <> <QueryInspectorControls attributes={attributes} setAttributes={setAttributes} /> <div {...blockProps}> {isResolving ? ( <p>{__("Loading...", "prismatic")}</p> ) : !posts?.length ? ( <p>{__("No content.", "prismatic")}</p> ) : ( <> <div {...innerBlocksProps} /> <QueryPostTypeLoop posts={posts} templateBlock={templateBlock} /> </> )} </div> </> ); }