Własne bloki w WordPress Gutenberg #003 – atrybuty

Atrybuty w WordPress Gutenbergu, pozwalają nam definiować, jakie dane, będą przekazywane podczas edycji bloku, a później wyświetlane na front-endzie.

Są spoiwem, które mówi parserowi, na jakie dane ma zwrócić uwagę zapisując HTML konkretnego bloku do bazy danych i później go odczytując (bo tak, bloki Gutenberga są zapisywane w bazie danych, w formie HTMLa, o czym sobie jeszcze powiemy).

Psst! Jeśli wolisz oglądać, niż czytać, to ten artykuł ma też wersję wideo!

W takim razie, jak możemy je deklarować?

Robimy to w kodzie konkretnego bloku, deklarując je, jako osobną właściwość, nad głównymi metodami edit() oraz save(), w ten oto sposób:

attributes: {
  title: {
    type: 'string',
  },
},

W ten sposób, dajemy znać Gutenbergowi, że do customowego bloku, przekazywana będzie wartość o identyfikatorze title, o typie string.

Właśnie - typy atrybutów!

Jest to jedyna wartość, jaką musimy wrzucić do naszego atrybutu, aby całość zaczęła działać. O reszcie zaraz sobie powiemy, ale na ten moment, to jest jedyny niezbędny element.

Atrybuty, mają 7 typów (idąc za dokumentacją):

  • null;
  • array;
  • object;
  • string;
  • integer;
  • boolean;
  • number.

Dzięki temu, korzystając z konkretnego atrybutu, JavaScript od razu będzie wiedzieć jakiego typu jest dany parametr i w sposób właściwy dla danego typu, będzie go traktować.

I tu warto wspomnieć o jednej kwestii organizacyjnej - mianowicie ten artykuł jest bardzo teoretyczny. Opisuję w nim wszystko, co powinieneś wiedzieć o samych atrybutach, ale po działający kod, który wyświetli wartość

Poza tym, mamy również źródło konkretnego atrybutu

I tu dochodzimy do tego, o czym wspominałem na początku:

WordPress Gutenberg zapisuje wszystkie bloki, razem z wartościami, które są do nich wrzucane, w bazie danych w postaci kodu HTML.

Dopiero parser, w jego przypadku biblioteka HPQ, wyciąga dane wartości z kodu, aby poprawnie je wyświetlić.

Co to dla nas oznacza?

Otóż to, że przykładowy, mega prosty blok, w bazie będzie wyglądać w ten oto sposób:

<!-- wp:rob/table-of-contents {"title":"Pewien ładny tytuł"} -->
<nav class="table-of-contents" class="wp-block-rob-table-of-contents">
  <h2>Pewien ładny tytuł</h2>
</nav>
<!-- /wp:rob/table-of-contents -->

A przynajmniej tak będzie wyglądać, gdy nie sprecyzujemy źródła konkretnego atrybutu, czyli zapiszemy go tak, jak w pierwszym przykładzie.

Bo tak, możemy sprecyzować źródło danego atrybutu, na przykład określając je jako html, w ten sposób:

attributes: {
  title: {
    type: 'string',
    source: 'html',
    selector: "h2",
  },
},

...co w połączeniu z ostatnią właściwością selector, pozwoli parserowi, wyciągnąć konkretny atrybut Gutenberga, z kodu HTMLa, dokładnie z selektora h2.

Co w bazie danych, nie zapisze się już w taki sposób, jak widać powyżej, ale w taki:

<!-- wp:rob/table-of-contents -->
<nav class="table-of-contents" class="wp-block-rob-table-of-contents">
  <h2>Tytuł spisu treści</h2>
</nav>
<!-- /wp:rob/table-of-contents -->

W końcu Gutenberg nie potrzebuje już naszego atrybutu, zaszytego w obiekcie, wrzuconym w komentarzu, bo wie, że ma sobie go pobrać z kodu HTML, dokładnie z selektora <h2>, którego napotka podczas przetwarzania powyższego kodu.

Powiedzmy sobie jeszcze trochę o samych źródłach

Pozwolę sobie wyróżnić 5 atrybutów, bo to one przydają się najczęściej:

  • html (już pokazany na przykładzie);
  • text;
  • attribute;
  • children;
  • query;

A omówię 3 ostatnie, bo pierwsze zostały już wspomniane (i nie da się ukryć - są siłą rzeczy najprostsze).

Źródło - attribute

Tutaj jako wartość naszego gutenbergowego atrybutu, pobieramy atrybut danego elementu HTMLa, dla przykładu src z obrazka:

attributes: {
  title: {
    type: 'string',
    source: 'attribute',
    selector: "img",
    attribute: 'src',
  },
},

Wtedy również, poza zdefiniowaniem naszego selektora, musimy podać nazwę konkretnego atrybutu, z którego Gutenberg już pobierze sobie dane.

Źródło - children

Tutaj, wartością zwracaną jest tablica powtarzanych elementów, które są dziećmi konkretnego skrawka HTMLa, którego selektor podajemy:

attributes: {
  list: {
    type: "array",
    source: "children",
    selector: "ol",
  },
},

Taki atrybut, zwróci nam elementy listy numerowanej, na przykład takiej:

<ol class="list">
  <li class="list__item">Element 1</li>
  <li class="list__item">Element 2</li>
  <li class="list__item">Element 3</li>
</ol>

Źródło - query

Chyba najbardziej rozbudowana z opcji, bo nie zwracająca konkretnej wartości, ale obiekt lub tablicę, w zależności od tego, jaki typ atrybutu wpiszemy.

Mając listę podobnych elementów, na przykład takich oto postów z bloga:

<!-- wp:cgb/block-test-block -->
<ul class="posts-list">
  <li class="post">
    <h3 class="post__title">Artykuł 1</h3>
    <p class="post__content">Zawartość artkułu</p>
  </li>
  <li class="post">
    <h3 class="post__title">Artykuł 2</h3>
    <p class="post__content">Zawartość artkułu</p>
  </li>
  <li class="post">
    <h3 class="post__title">Artykuł 3</h3>
    <p class="post__content">Zawartość artkułu</p>
  </li>
</ul>
<!-- /wp:cgb/block-test-block -->

...jesteśmy w stanie pobrać tablicę z wszystkimi tytułami oraz zajawkami, za pomocą następującego kodu:

attributes: {
  content: {
    type: 'array',
    source: 'query',
    selector: '.post',
    query: {
      title: {
        type: 'text',
        selector: '.post__title',
        source: 'html',
      },
      description: {
        type: 'text',
        selector: '.post__content',
        source: 'html',
      },
    },
  },
},

I jak widać, przy okazji poprzednich przykładów, poznaliśmy kilka dodatkowych właściwości

A dokładnie:

  • selector - nazwa selektora, z którego chcemy pobrać zawartość;
  • attribute - atrybut danego selektora (jeśli tylko on zostanie wrzucony do atrybytów).

I dodatkowo, mamy jeszcze jedną, która może Ci się przydać:

  • multiline - przyjmuje za wartość tag HTMLa, w którym znajdzie się każda linia, którą dodamy w edytorze Gutenberga. Na przykład, gdybyśmy chcieli wyróżnić każdą z nich, tagami <p>, to moglibyśmy zapisać coś takiego:
attributes: {
  list: {
    type: "string",
    multiline: "p",
  }
}

I tak naprawdę, w tej chwili wiemy o atrybutach wszystko co najważniejsze!

Jedyne co nam pozostaje, to przekazać je do naszych funkcji edit() oraz save(), w następujący sposób:

edit({ attributes, setAttributes }) {
  return <p>Coś innego, niż "Hello world".</p>;
},

save({ attributes }) {}

I od tej chwili, wewnątrz tych funkcji, będziemy mieli dostęp do obiektu z wszystkimi zdefiniowanymi atrybutami oraz w przypadku funkcji edit(), do metody setAttributes(), która pozwala w ogóle edytować atrybuty (więcej na ten temat wspominam w nagraniu do tego artykułu, a jeszcze więcej powiemy sobie o tym w kolejnej części).

I jeszcze efekt końcowy naszego bloku (na obecny moment) ☀️

Wyświetlmy input, do którego będziemy w stanie wrzucić konkretny tekst, a później za pomocą atrybutów przekazać go do naszej funkcji save().

A później wyświetlić na front-endzie, jako nagłówek:

import './index.scss';
import { registerBlockType } from '@wordpress/blocks';

registerBlockType('rob/table-of-contents', {
  title: 'Spis treści',
  description: 'Sekcja z nagłówkiem oraz spisem treści, konkretnego artykułu',
  icon: 'editor-table',
  keywords: ['zawartość', 'lista', 'table of contents'],
  category: 'content',

  attributes: {
    title: {
      type: 'string',
      source: 'html',
      selector: 'h2',
    },
  },

  edit({ attributes, setAttributes }) {
    const { title } = attributes;

    function setTitle(event) {
      const newTitle = event.target.value;
      setAttributes({ title: newTitle });
    }

    return <input type="text" value={title} onChange={setTitle} />;
  },

  save({ attributes }) {
    const { title } = attributes;

    return <h2>{title}</h2>;
  },
});

Mamy to! Pora na zadanie domowe

Zadeklaruj 2 atrybuty - tytułu oraz listy, z których składać się będzie spis treści, (który tworzymy w ramach serii), nadając im odpowiednie właściwości.

Zapewne w następnej części, już od początku te atrybuty będą przeze mnie utworzone, natomiast mam nadzieję, że mimo tego nie będziesz brać zadania od kolegi - Roberta z kolejnego filmu lub artykułu, a zrobisz całość sam lub sama i dzięki temu przećwiczysz temat atrybutów 😏

Oczywiście nie zapomnij podzielić się rozwiązaniem w komentarzu!

Mogą Cię zainteresować:

Chętnie zaproponuję Ci coś jeszcze

Czy chcesz dodać coś od siebie?