Modern Custom Block Using manifest.php in edit.js — attributes not saving in Database

admin2025-05-31  0

import { __ } from "@wordpress/i18n";
import { InspectorControls, useBlockProps } from "@wordpress/block-editor";
import {
    Button,
    CheckboxControl,
    PanelBody,
    SelectControl,
    TextControl,
    ToggleControl,
} from "@wordpress/components";
import { useEffect, useState } from "@wordpress/element";
import apiFetch from "@wordpress/api-fetch";

export default function Edit({ attributes, setAttributes }) {
    const {
        heading = "",
        menuItems = [],
        useCategories = false,
        categoryOrderBy = "name",
        categoryOrder = "asc",
        hideEmpty = false,
        selectedCategories = [],
        useSelectedCategoriesOnly = false,
    } = attributes;

    const [categories, setCategories] = useState([]);
    const [isLoading, setIsLoading] = useState(false);

    // Fetch categories
    useEffect(() => {
        if (!useCategories) return;

        let isMounted = true;
        setIsLoading(true);

        const queryParams =
            `?per_page=100&orderby=${categoryOrderBy}&order=${categoryOrder}` +
            (hideEmpty ? "&hide_empty=true" : "");

        apiFetch({ path: "/wp/v2/categories" + queryParams })
            .then((fetchedCategories) => {
                if (isMounted) {
                    setCategories(fetchedCategories);
                    setIsLoading(false);
                }
            })
            .catch((error) => {
                if (isMounted) {
                    console.error("Error fetching categories:", error);
                    setIsLoading(false);
                }
            });

        return () => {
            isMounted = false;
        };
    }, [useCategories, categoryOrderBy, categoryOrder, hideEmpty]);

    function addMenuItem() {
        setAttributes({ menuItems: [...menuItems, { text: "", url: "" }] });
    }

    function updateMenuItem(index, field, value) {
        const newItems = [...menuItems];
        newItems[index][field] = value;
        setAttributes({ menuItems: newItems });
    }

    function removeMenuItem(index) {
        const newItems = [...menuItems];
        newItems.splice(index, 1);
        setAttributes({ menuItems: newItems });
    }

    function toggleCategorySelection(categoryId) {
        const updated = selectedCategories.includes(categoryId)
            ? selectedCategories.filter((id) => id !== categoryId)
            : [...selectedCategories, categoryId];
        setAttributes({ selectedCategories: updated });
    }

    let previewItems = [];

    if (useCategories) {
        if (isLoading) {
            previewItems.push(<li key="loading">Loading categories...</li>);
        } else if (categories.length === 0) {
            previewItems.push(<li key="none">No categories found</li>);
        } else {
            let displayCategories = categories;

            if (useSelectedCategoriesOnly && selectedCategories.length > 0) {
                displayCategories = categories.filter((cat) =>
                    selectedCategories.includes(cat.id),
                );
            }

            previewItems = displayCategories.slice(0, 5).map((cat) => (
                <li key={cat.id}>
                    <a href="#">
                        {cat.name} ({cat.count})
                    </a>
                </li>
            ));

            if (displayCategories.length > 5) {
                previewItems.push(<li key="more">...</li>);
            }
        }
    } else {
        if (menuItems.length === 0) {
            previewItems.push(<li key="add">Add menu items in the sidebar</li>);
        } else {
            previewItems = menuItems.map((item, index) => (
                <li key={`menu-item-${index}`}>
                    <a href={item.url || "#"}>{item.text || "Menu Item"}</a>
                </li>
            ));
        }
    }

    return (
        <>
            <InspectorControls>
                <PanelBody
                    title={__("Menu Settings", "woracious-suite")}
                    initialOpen={true}
                >
                    <TextControl
                        label={__("Heading", "woracious-suite")}
                        value={heading}
                        onChange={(value) => setAttributes({ heading: value })}
                    />

                    <ToggleControl
                        label={__("Use Categories", "woracious-suite")}
                        checked={useCategories}
                        onChange={(value) => setAttributes({ useCategories: value })}
                    />

                    {!useCategories && (
                        <div className="menu-items-controls">
                            <h3>{__("Menu Items", "woracious-suite")}</h3>
                            {menuItems.map((item, index) => (
                                <div className="menu-item" key={`menu-item-control-${index}`}>
                                    <TextControl
                                        label={__("Text", "woracious-suite")}
                                        value={item.text}
                                        onChange={(value) => updateMenuItem(index, "text", value)}
                                    />
                                    <TextControl
                                        label={__("URL", "woracious-suite")}
                                        value={item.url}
                                        onChange={(value) => updateMenuItem(index, "url", value)}
                                    />
                                    <Button
                                        isDestructive
                                        variant="secondary"
                                        onClick={() => removeMenuItem(index)}
                                    >
                                        {__("Remove", "woracious-suite")}
                                    </Button>
                                </div>
                            ))}
                            <Button isPrimary onClick={addMenuItem}>
                                {__("Add Menu Item", "woracious-suite")}
                            </Button>
                        </div>
                    )}

                    {useCategories && (
                        <div className="category-settings">
                            <SelectControl
                                label={__("Order By", "woracious-suite")}
                                value={categoryOrderBy}
                                options={[
                                    { label: __("Name", "woracious-suite"), value: "name" },
                                    { label: __("Count", "woracious-suite"), value: "count" },
                                    { label: __("ID", "woracious-suite"), value: "id" },
                                ]}
                                onChange={(value) => setAttributes({ categoryOrderBy: value })}
                            />

                            <SelectControl
                                label={__("Order", "woracious-suite")}
                                value={categoryOrder}
                                options={[
                                    { label: __("Ascending", "woracious-suite"), value: "asc" },
                                    { label: __("Descending", "woracious-suite"), value: "desc" },
                                ]}
                                onChange={(value) => setAttributes({ categoryOrder: value })}
                            />

                            <ToggleControl
                                label={__("Hide Empty Categories", "woracious-suite")}
                                checked={hideEmpty}
                                onChange={(value) => setAttributes({ hideEmpty: value })}
                            />

                            <ToggleControl
                                label={__("Show Only Selected Categories", "woracious-suite")}
                                checked={useSelectedCategoriesOnly}
                                onChange={(value) =>
                                    setAttributes({ useSelectedCategoriesOnly: value })
                                }
                            />

                            {useSelectedCategoriesOnly && categories.length > 0 && (
                                <div className="category-selection">
                                    <h4>{__("Select Categories", "woracious-suite")}</h4>
                                    {categories.map((category) => (
                                        <CheckboxControl
                                            key={category.id}
                                            label={`${category.name} (${category.count})`}
                                            checked={selectedCategories.includes(category.id)}
                                            onChange={() => toggleCategorySelection(category.id)}
                                        />
                                    ))}
                                </div>
                            )}
                        </div>
                    )}
                </PanelBody>
            </InspectorControls>

            <div {...useBlockProps({ className: "menu" })}>
                {heading && <h6>{heading}</h6>}
                <ul>{previewItems}</ul>
            </div>
        </>
    );
}

Issue: Attributes are not saving in the Database, and same can be verified when viewed in Code Editor Mode.

转载请注明原文地址:http://conceptsofalgorithm.com/Algorithm/1748638437a313702.html

最新回复(0)