From 209751a5a43540ed9640a44bdd4565b000c2757c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Zieli=C5=84ski?= Date: Wed, 26 Jan 2022 17:28:32 +0100 Subject: [PATCH 01/51] First draft --- docs/how-to-guides/data-basics/1-setup.md | 127 +++++++ .../data-basics/2-building-a-list-of-pages.md | 343 ++++++++++++++++++ docs/how-to-guides/data-basics/README.md | 15 + .../data-basics/media/finished-app.jpg | Bin 0 -> 33691 bytes .../media/list-of-pages/fetch-the-data.jpg | Bin 0 -> 6027 bytes .../media/list-of-pages/filter-field.jpg | Bin 0 -> 13639 bytes .../media/list-of-pages/filter.jpg | Bin 0 -> 10651 bytes .../media/list-of-pages/indicator.jpg | Bin 0 -> 8135 bytes .../media/list-of-pages/make-a-table.jpg | Bin 0 -> 12740 bytes .../media/list-of-pages/no-results.jpg | Bin 0 -> 8575 bytes .../media/list-of-pages/part1-finished.jpg | Bin 0 -> 16060 bytes .../media/list-of-pages/simple-list.jpg | Bin 0 -> 2879 bytes .../media/list-of-pages/unclear-status.jpg | Bin 0 -> 9861 bytes .../data-basics/media/setup/hello-from-js.jpg | Bin 0 -> 4052 bytes 14 files changed, 485 insertions(+) create mode 100644 docs/how-to-guides/data-basics/1-setup.md create mode 100644 docs/how-to-guides/data-basics/2-building-a-list-of-pages.md create mode 100644 docs/how-to-guides/data-basics/README.md create mode 100644 docs/how-to-guides/data-basics/media/finished-app.jpg create mode 100644 docs/how-to-guides/data-basics/media/list-of-pages/fetch-the-data.jpg create mode 100644 docs/how-to-guides/data-basics/media/list-of-pages/filter-field.jpg create mode 100644 docs/how-to-guides/data-basics/media/list-of-pages/filter.jpg create mode 100644 docs/how-to-guides/data-basics/media/list-of-pages/indicator.jpg create mode 100644 docs/how-to-guides/data-basics/media/list-of-pages/make-a-table.jpg create mode 100644 docs/how-to-guides/data-basics/media/list-of-pages/no-results.jpg create mode 100644 docs/how-to-guides/data-basics/media/list-of-pages/part1-finished.jpg create mode 100644 docs/how-to-guides/data-basics/media/list-of-pages/simple-list.jpg create mode 100644 docs/how-to-guides/data-basics/media/list-of-pages/unclear-status.jpg create mode 100644 docs/how-to-guides/data-basics/media/setup/hello-from-js.jpg diff --git a/docs/how-to-guides/data-basics/1-setup.md b/docs/how-to-guides/data-basics/1-setup.md new file mode 100644 index 00000000000000..10a8cb2f902148 --- /dev/null +++ b/docs/how-to-guides/data-basics/1-setup.md @@ -0,0 +1,127 @@ +## Setup + +We will build the application as a WordPress plugin, which means you need to have the WordPress itself installed. One way to do it is by following the instructions on [Getting Started](/docs/contributors/code/getting-started-with-code-contribution.md) page. Once your setup is finished, you can follow along with the rest of this tutorial. + +To create a new plugin, create a `wp-content/plugins/first-gutenberg-app` directory in your local WordPress environment. We will need to create three files inside that directory: + +* first-gutenberg-app.php – to create a new admin page +* script.js – for our JavaScript application +* style.css – for the minimal stylesheet + +Go ahead and create these files using the following snippets: + +**app.js:** +```js +function MyFirstApp() { + return wp.element.createElement('span', {}, 'Hello from JavaScript!'); +} + +window.addEventListener( 'load', function() { + wp.element.render( + wp.element.createElement( MyFirstApp ), + document.querySelector( '#my-first-gutenberg-app' ) + ); +}, false ); +``` + +**style.css:** +```css +.toplevel_page_my-first-gutenberg-app #wpcontent { + background: #FFF; +} +#my-first-gutenberg-app { + max-width: 500px; +} +#my-first-gutenberg-app ul, +#my-first-gutenberg-app ul li { + list-style-type: disc; +} +#my-first-gutenberg-app ul { + padding-left: 20px; +} +#my-first-gutenberg-app .components-search-control__input { + height: 36px; + margin-left: 0; +} +``` + +**first-gutenberg-app.php:** +```php +Pages +
+ '; + }, + 'dashicons-schedule', + 3 + ); +} + +add_action( 'admin_menu', 'my_admin_menu' ); + +function load_custom_wp_admin_scripts( $hook ) { + // Load only on ?page=my-first-gutenberg-app + if ( $hook !== 'toplevel_page_my-first-gutenberg-app' ) { + return; + } + + // Load the style.css + wp_register_style( 'my-first-gutenberg-app', plugins_url( 'my-first-gutenberg-app/style.css' ) ); + wp_enqueue_style( 'wp-components' ); + wp_enqueue_style( 'my-first-gutenberg-app' ); + + // Load the required WordPress packages + wp_enqueue_script( 'wp-components' ); + wp_enqueue_script( 'wp-data' ); + wp_enqueue_script( 'wp-core-data' ); + + // Load the app.js + wp_register_script( + 'my-first-gutenberg-app', + plugins_url( 'my-first-gutenberg-app/app.js' ), + array( 'wp-components', 'wp-data', 'wp-core-data' ), + ); + wp_enqueue_script( 'my-first-gutenberg-app' ); +} + +add_action( 'admin_enqueue_scripts', 'load_custom_wp_admin_scripts' ); +``` + +If you now go to the Plugins page, you should see a plugin called **My first Gutenberg App**. Go ahead and activate it. A new menu position labeled _My first Gutenberg app_ should show up. Once you click it, you will see a page that says _Hello from JavaScript!_: + +![](./media/setup/hello-from-js.jpg) + +Congratulations! You are now ready to start building the app! + +## Trading readability for convenience +You don’t need any build tools to complete this tutorial. All the code examples work as provided even if you paste them into your browser’s developer tools. + +The price to pay is in readability. The way React components are usually depicted is with the JSX syntax that looks like this: + +```js +function MyFirstApp() { + return Hello from JavaScript! ; +} +``` + +It was tempting to use that syntax here, however, it would complicate the initial setup. We would need to install node.js, a build tool like webpack, and compile the app on each change. None of that is required for this tutorial. The trade-off is that we are restricted to the regular JavaScript syntax as below: + +```js +function MyFirstApp() { + return wp.element.createElement('span', {}, 'Hello from JavaScript!'); +} +``` diff --git a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md new file mode 100644 index 00000000000000..c73b68f688064d --- /dev/null +++ b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md @@ -0,0 +1,343 @@ +# Building a list of pages + +In this part, we will build a filterable list of all WordPress pages. This is what the app will look like at the end of this part: + +![](./media/list-of-pages/part1-finished.jpg) + +Let’s see how we can get there step by step + +## Step 1: Build the PagesList component +Let’s start by building a minimal React component to display the list of pages: + +```js +function MyFirstApp() { + const pages = [ { id: 'mock', title: 'Sample page' } ] + return ( + wp.element.createElement(PagesList, { pages }) + ) +} + +function PagesList({ pages }) { + return ( + wp.element.createElement('ul', {}, + pages?.map(page => ( + wp.element.createElement('li', {key: page.id}, page.title) + )) + ) + ) +} +``` + +Note this component does not fetch any data yet, only presents the hardcoded list of pages. When you refresh the page, you should see the following: + +![](./media/list-of-pages/simple-list.jpg) + +## Step 2: Fetch the data +The hardcoded sample page isn’t very useful, so let’s fetch the actual list of pages from the WordPress API. Instead of working directly with HTTP requests, we will use the [`getEntityRecords`](/docs/reference-guides/data/data-core/#getentityrecords) provided by Gutenberg’s `coreData`. In broad strokes, it will the correct API request, cache the results, and return the list of the entity records we need. Here’s how to use it: + +`wp.data.select('core').getEntityRecords( 'postType', 'page' ) ` + +If you run that following snippet in your browser’s dev tools, you will see it returns `null`. Why? The pages are only requested by `getEntityRecords` resolver after you first run the selector. If you wait a moment and run it again, it will return the list of all pages. + +Similarly, the `MyFirstApp` component needs to re-run the selector once the data is available. That’s exactly what the `useSelect` hook does: + +```js +function MyFirstApp() { + const pages = wp.data.useSelect( + select => + select( wp.coreData.store ).getEntityRecords( 'postType', 'page' ), + [] + ); + // ... +} +``` + +`useSelect` takes two arguments: a callback and dependencies. In broad strokes, it re-runs the callback whenever either the dependencies or the underlying data store changes. You can learn more about [useSelect](#) in the [data module documentation](/packages/data/README.md#useselect). + +Putting it together, we get the following code: + +```js +function MyFirstApp() { + const pages = wp.data.useSelect( + select => + select( wp.coreData.store ).getEntityRecords( 'postType', 'page' ), + [] + ); + return ( + wp.element.createElement(PagesList, { pages }) + ) +} + +function PagesList({ pages }) { + return ( + wp.element.createElement('ul', {}, + pages?.map(page => ( + wp.element.createElement('li', {key: page.id}, page.title.rendered) + )) + ) + ) +} +``` + +Refreshing the page should display a list similar to this one: + +![](./media/list-of-pages/fetch-the-data.jpg) + +## Step 3: Turn it into a table + +```js +function PagesList({ pages }) { + return wp.element.createElement( + 'table', + { className: 'wp-list-table widefat fixed striped table-view-list' }, + wp.element.createElement( 'thead', {}, + wp.element.createElement( 'tr', {}, + wp.element.createElement( 'td', {}, 'Title' ), + ), + ), + wp.element.createElement( 'tbody', {}, + pages?.map( page => ( + wp.element.createElement( 'tr', { key: page.id }, + wp.element.createElement( 'td', {}, page.title.rendered ), + ) + ) ), + ), + ); +} +``` + +![](./media/list-of-pages/make-a-table.jpg) + +## Step 4: Add a search Box +The list of pages is short for now, however the longer it grows the harder it is to work with. WordPress admins typically solves this problem with a search box – let’s implement one, too! + +Let’s start by adding a search field: + +```js +function MyFirstApp() { + const [searchTerm, setSearchTerm] = wp.element.useState(''); + + // ... + + return ( + wp.element.createElement('div', {}, + wp.element.createElement( wp.components.SearchControl, { + onChange: setSearchTerm, + value: searchTerm, + } ), + // ... + ) + ) +} +``` + +Note that instead of using an `input` tag, we took advantage of the [SearchControl](https://developer.wordpress.org/block-editor/reference-guides/components/search-control/) component. This is how it looks like: + +![](./media/list-of-pages/filter-field.jpg) + +The field starts empty and the contents are stored in the `searchTerm` state value. If you aren’t familiar with the [useState](https://reactjs.org/docs/hooks-state.html) hook, you can learn more in [React’s documentation](https://reactjs.org/docs/hooks-state.html). + +We can now request only the pages matching the `searchTerm`. + +After checking with the [WordPress API documentation]([https://developer.wordpress.org/rest-api/reference/pages/]), we see that the [/wp/v2/pages]([https://developer.wordpress.org/rest-api/reference/pages/]) endpoint accepts a `search` query parameter and uses it to _Limit results to those matching a string_. But how to use it? We can pass custom query parameters as the third argument to `getEntityRecords` as below: + +`wp.data.select('core').getEntityRecords( 'postType', 'page', { search: 'home' } )` + +Running that snippet in your browser’s dev tools will trigger a request to `/wp/v2/pages?search=home` instead of just `/wp/v2/pages`. + +Let’s update our `useSelect` call as follows: + +```js +function MyFirstApp() { + // ... + const { pages } = wp.data.useSelect(select => { + const query = {}; + if (searchTerm) { + query.search = searchTerm; + } + return { + pages: select(wp.coreData.store).getEntityRecords('postType', 'page', query) + } + }, [searchTerm]); + + // ... +} +``` + +The `searchTerm` is now used as a `search` query parameter when specified. Note that `searchTerm` is also specified inside the list of `useSelect` dependencies to make sure `getEntityRecords` is re-run when the `searchTerm` changes. + +Finally, here’s how `MyFirstApp` looks like once we wire it all together: + +```js +function MyFirstApp() { + const [searchTerm, setSearchTerm] = wp.element.useState(''); + const pages = wp.data.useSelect(select => { + const query = {}; + if (searchTerm) { + query.search = searchTerm; + } + return select(wp.coreData.store).getEntityRecords('postType', 'page', query); + }, [searchTerm]); + + return ( + wp.element.createElement('div', {}, + wp.element.createElement( wp.components.SearchControl, { + onChange: setSearchTerm, + value: searchTerm, + } ), + wp.element.createElement( PagesList, { pages } ), + ) + ) +} +``` + +Voila! We can now filter the results: + + +![](./media/list-of-pages/filter.jpg) + +### Gutenberg data vs working directly with the API + +Let’s take a pause for a moment to consider an alternative approach. Imagine we sent the API requests directly: + +```js +function MyFirstApp() { + // ... + const [pages, setPages] = useState( [] ); + useEffect( () => { + const url = '/wp-json/wp/v2/pages?search=' + searchTerm; + wp + .apiFetch({ url }) + .then( setPages ) + }, [searchTerm]); + // ... +} +``` + +We would need to solve two problems here. + +First, out-of-order updates. Searching for „About” would trigger five API requests filtering for A, Ab, Abo, Abou, and About. They could finish in a different order than they started. It is possible that _search=A_ would resolve after _ search=About_ and we’d display the wrong data. + +Gutenberg data helps by handling the asynchronous part behind the scenes. `useSelect` remembers the most recent call and returns only the data we expect. + +Second, every key stroke would trigger an API request. If you typed About, deleted it, and typed it again, it would issue 10 requests in total even though we could reuse the data. + +Gutenberg data helps by caching the responses to API requests triggered by `getEntityRecords()` and reuses them on subsequent calls. This is especially important when there’s more other components relying on `getEntityRecords()`. + +All in all, the built-in utilities are designed to solve the typical problems so that you can focus on your application instead. + +## Step 5: Loading Indicator + +There is one problem with our search feature. We can’t be quite sure whether it’s still searching or showing no results: + +![](./media/list-of-pages/unclear-status.jpg) + +A few messages like _Loading…_ or _No results_ would clear it up. Let’s implement them! First, `PagesList` has to be aware of the current status: + +```js + +function PagesList( { hasResolved, pages } ) { + if ( ! hasResolved ) { + return wp.element.createElement( wp.components.Spinner ); + } + if ( ! pages?.length ) { + return wp.element.createElement( 'div', {}, 'No results' ); + } + // ... +} + +function MyFirstApp() { + // ... + + return ( + wp.element.createElement( 'div', {}, + // ... + wp.element.createElement( PagesList, { hasResolved, pages } ), + ) + ) +} +``` + +Note that instead of building a custom loading indicator, we took advantage of the [Spinner](https://developer.wordpress.org/block-editor/reference-guides/components/spinner/) component. + +We still need to know whether the pages selector `hasResolved` or not. We can find out using the `hasFinishedResolution` selector: + +`wp.data.select('core').hasFinishedResolution( 'getEntityRecords', [ 'postType', 'page', { search: 'home' } ] )` + +It takes the name of the selector and the arguments, and returns either `true` if the data was already loaded or `false` it we’re still waiting. Let’s add it to `wp.data.useSelect`: + +```js +function MyFirstApp() { + // ... + const { pages, hasResolved } = wp.data.useSelect(select => { + // ... + return { + pages: // ... + hasResolved: select(wp.coreData.store).hasFinishedResolution( 'getEntityRecords', [ 'postType', 'page', query ] ), + } + }, [searchTerm]); + + // ... +} +``` + +All the pieces are in place, great! Here’s the complete JavaScript code of our app: + +```js + +function MyFirstApp() { + const [searchTerm, setSearchTerm] = wp.element.useState( '' ); + const { pages, hasResolved } = wp.data.useSelect( select => { + const query = {}; + if ( searchTerm ) { + query.search = searchTerm; + } + return { + pages: select( wp.coreData.store ).getEntityRecords( 'postType', 'page', query ), + hasResolved: select( wp.coreData.store ) + .hasFinishedResolution( 'getEntityRecords', ['postType', 'page', query] ), + }; + }, [searchTerm] ); + + return ( + wp.element.createElement( 'div', {}, + wp.element.createElement( wp.components.SearchControl, { + onChange: setSearchTerm, + value: searchTerm, + } ), + wp.element.createElement( PagesList, { hasResolved, pages } ), + ) + ); +} + +function PagesList( { hasResolved, pages } ) { + if ( !hasResolved ) { + return wp.element.createElement( wp.components.Spinner ); + } + if ( !pages?.length ) { + return wp.element.createElement( 'div', {}, 'No results' ); + } + + return wp.element.createElement( + 'table', + { className: 'wp-list-table widefat fixed striped table-view-list posts' }, + wp.element.createElement( 'thead', {}, + wp.element.createElement( 'tr', {}, + wp.element.createElement( 'td', {}, 'Title' ), + ), + ), + wp.element.createElement( 'tbody', {}, + pages?.map( page => ( + wp.element.createElement( 'tr', { key: page.id }, + wp.element.createElement( 'td', {}, page.title.rendered ), + ) + ) ), + ), + ); +} +``` + +All that’s left is to refresh the page and enjoy the brand new status indicator: + +![](./media/list-of-pages/indicator.jpg) +![](./media/list-of-pages/no-results.jpg) diff --git a/docs/how-to-guides/data-basics/README.md b/docs/how-to-guides/data-basics/README.md new file mode 100644 index 00000000000000..685c96c12a64c5 --- /dev/null +++ b/docs/how-to-guides/data-basics/README.md @@ -0,0 +1,15 @@ +# Creating your First App with Gutenberg Data + +The goal of this tutorial is to get you comfortable on how to use the Gutenberg data layer. It guides you through the process of building a React application that enables the user to manage their WordPress pages. The finished app will look like this: + +![](./media/finished-app.jpg) + +### Table of Contents + +1. [Setup](./1-setup) +2. [Building a basic list of pages](./2-building-a-list-of-pages.md) +3. (@TODO) Adding an „Edit page” feature +4. (@TODO) Adding a „Create a new page” feature +5. (@TODO) Adding a „Delete” feature +6. (@TODO) Advanced pages list (author column, Treegrid) + diff --git a/docs/how-to-guides/data-basics/media/finished-app.jpg b/docs/how-to-guides/data-basics/media/finished-app.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8a69a282feab08af7c12a01ec588cc3492a79217 GIT binary patch literal 33691 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 literal 0 HcmV?d00001 diff --git a/docs/how-to-guides/data-basics/media/list-of-pages/fetch-the-data.jpg b/docs/how-to-guides/data-basics/media/list-of-pages/fetch-the-data.jpg new file mode 100644 index 0000000000000000000000000000000000000000..58595b9d21219ee645441a17aeae72014d2dd77a GIT binary patch literal 6027 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 S0|zVB@FwLOw8#=8cV7y-NX|Iqla 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 literal 0 HcmV?d00001 diff --git a/docs/how-to-guides/data-basics/media/list-of-pages/indicator.jpg b/docs/how-to-guides/data-basics/media/list-of-pages/indicator.jpg new file mode 100644 index 0000000000000000000000000000000000000000..92da78df9aabccab81a73755e56a1052de8a7086 GIT binary patch literal 8135 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 literal 0 HcmV?d00001 diff --git a/docs/how-to-guides/data-basics/media/list-of-pages/make-a-table.jpg b/docs/how-to-guides/data-basics/media/list-of-pages/make-a-table.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3273da9965eeb27b8dc7087553f8306ad59a054b GIT binary patch literal 12740 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 literal 0 HcmV?d00001 diff --git a/docs/how-to-guides/data-basics/media/list-of-pages/part1-finished.jpg b/docs/how-to-guides/data-basics/media/list-of-pages/part1-finished.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0e138996630f9d28a81db9c6e1aa3b8d0e17b18d GIT binary patch literal 16060 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 literal 0 HcmV?d00001 diff --git a/docs/how-to-guides/data-basics/media/setup/hello-from-js.jpg b/docs/how-to-guides/data-basics/media/setup/hello-from-js.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0242ac91d19ef05cb23eca7df2b8233b5910bef7 GIT binary patch literal 4052 zcmeHHc~Fzr7XJcBfq)We(8r=RENVcMEi@olD`C@ALlRj+u*f11f=j>!QCfW}1c?F- zN?02fNdieh2!ar*$X>891R*SnfIuKp!mdDGY{xg#dGDV${qIeG-+Xt@{r&E__ndR* z9!0O>HK6O|=II82KmY(zet=>a_zHC~A`Ae~XaEiXfCd1%6#=LzEu{(=D1QJ@$yfQr zfVA>eKiR;OkD{UX|l{@DgK4UnpeQnl6vl;^5!Py?wc7yZ5fq@t>}K^^j$#^xPcedsUr ztUrex#F#*B^i6GpzE`?z0e!@$y*{}pg>8`El|P0*bkJtV4i#(6!62AI0%$9PP=TmI zfCIqzgYf-(mQ^>*`(7y$A8D-IroRfh_TJJ($PP2k|E>D9_7-8#VhVPj?6VsUz_)_r zO_huH~xB&@S8e#;-?R8to!G$ zKYjJxz7wch68pao`3vRRBj5F>`~Hs!)MfRoanhOf)suO!W;tOjj7T&S^tlHy$vF9u z<^p;hb&<_3NOwi!5AXC|J3IVv|1t8=LWo1Wm6+T*`%7_~UL?s9X;$71ZBwN~%t=tZ zQ72vx7sx1PiS7M@T#5+Cx_G_?pESU8b2chFF&y*W+oGtnkTjYiK32dKhD6re zhc);s0E6!b7Gf#~lCap%PgvCWb~})-*8aFo`jeUgWao8Ef23SLEEY_@HfHgrC@q2Nf}>BPD1NJK z7^@+#z2)Wfw{y3_lzoK*U3dss2tI$Wh*Pdn;T=*g%(J3!y zXV*$gI3id3E4dH%3*f8i)hie6vUa5-YCIb*7$#@kZ8UpP6s>o7C3y~oRe4PR!b8Y) zN7ipknd5AJWfO`dNkFubMGu7v{H4rd?>! z34wa`#HY0w`ZxJ7W5en(K7K2rB^vIx?HMO8ee=xzJ~?ga)Q=B`IAwS8YlieEBoPI1 z7JX>^gGDU!@qB_YmdoH?Z6GYy(@_5i|L=F9uK(f2NhGTI`Nh^*4!P^`c9wq!9)-6x zO}iP3*7pb)71M-z?C|`N9TYy{^l@nx>dm#>+M5+S4`I+4y%1{n00Vi4l!|F(2{B*Y z2qu6kd_(cZjhiH;{%r(uyc~l+=0AKh?$j?so<=QIb)7yAOl|`aEXk&-n!HXvI~U7+ zHg{#IdT`%V6$KuhZmV1Ppw-H5I@647xuhXR_W#neER6;i%zbd)=**A_9OC#Aq2Zy! z1TxiQ(mydVNe|!9!+@Em2<=>re;O@acS;%QO<`miH$}zhUnc4ycTbc=^r=}p%(#^& zCg#MgLHxe>@5TEotXAInYV+am-XVrwFp2Cv4k3>b0%~9Ml@L+s8MldhX^5Kl_U#;Y zf-^e4tG%{*?GpwC%S)ova9}+0Tzm9_#Y&F9>I}hmXCz9gO5=f4hv6gqt-FP$8GQ7P~B+> zQ*`oN`L@O-Tf63>7KD5}*^|Of{ztN@V2D$(J!_Vgv;X#GdWR~}F1z$C2~&2IFHP*m z^AAf8pGwK{(S6DKf$695IYvIs?ggnebRx z0@i1_rreU2zON~&k1W^?E3Q9=9oP|)_pbS{VPN<9yjqh=EaKd3O&l9uP1(`(jzGuz zth)>!4Q(qS{{R_y_mltRuHlSVXp0;(*TjYgIWt5EFOHK6v3uW>uyw|9;py_diqTmK z$?AN#ta6LS3aZ9w!7OTOPUWpJcLK%hT2rZ66hlirm#;J{I! z5Ck2sH6Yx`1rMUl!j2x*xg13AD2$nJZ;F>ATzrsFlW6XkI}+o%Jd%?Ox$9q1NsHJap&8W+dn+^t6;+skI#QRBCo(^tSN`X!*Juw_J2#(Td#wD^3|h5i)yo1U2TAs6V|^ z(6+ka;~hgp+FLvxYFXM$@Rj(EP`r@`%n{|Q6D90g6D%6)xF!vhpZ$^+YPchL48Niy zsThkb<~DRhvB_w=QqlxG9GQ_DZXd}+LZ{dVGCA`sCR_iC?}=Q&#QC@kgk+~6?2?YW zR(K`)t9Eu@5GsE1sHskp2@TO=!=811qY`lqs_GE=)x-s%FlW%SZu3p~AS5mkT!c(fs=_WdH2<{JL$T)VnV)_~h4X zp|l*KrI)e;O4p!1c$7GfTR2l6c=J9fbROG`U zh?cx3ZSEeEZFD|}InAO9UXK&XQO{uR&J4%Ydi6WRvvI?WQjr86z7G5Dk)Ul+Su^Cm9NdT1<98Hkj3Gs=AAyTjElEe6-Q4AOj` z8vO;XW#x29W|yCY=LS3H(Poy?)*((qI>rbe4`pVL%$)i1Z1dcQocA>=fd@mc@8Ulp z)p-+6eA6pses6Slodvr*GUm>PTX&Munal;T%cB#ye4DbH58B~-acz%Q$hA%BFf(Zz z8UtprQ-h<upm^8!!&l>$c)cCC8Xf$bw#<;_wGCZfe(y4p zi3C`2Sz6BRkZ2zZecuJzu3iO@G(Ap&Y*`W)?2)7}THw}MJ@5}Vns%Sg+_ai@p`cH0 zQy?EjQ2-Tb zB1dBI3W3RYa75H^<(`a8en~vRdvogjefNjm^R{D~m5m`yq>qoeHn$&F(O6`UH8yCU m2$-O^_GRh$FV+MwNFD7QmR+5%8}3if=kLk?Z3Pk(eg6Ut%u9R# literal 0 HcmV?d00001 From cf2478cca57f3e3940d1d0c86d23a110da1deae8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Zieli=C5=84ski?= Date: Wed, 26 Jan 2022 17:38:30 +0100 Subject: [PATCH 02/51] Explain we need to create a few pages first --- docs/how-to-guides/data-basics/1-setup.md | 4 ++++ .../data-basics/2-building-a-list-of-pages.md | 12 ++++++++++-- .../media/list-of-pages/pages-list.jpg | Bin 0 -> 96566 bytes 3 files changed, 14 insertions(+), 2 deletions(-) create mode 100644 docs/how-to-guides/data-basics/media/list-of-pages/pages-list.jpg diff --git a/docs/how-to-guides/data-basics/1-setup.md b/docs/how-to-guides/data-basics/1-setup.md index 10a8cb2f902148..628c3533e89f86 100644 --- a/docs/how-to-guides/data-basics/1-setup.md +++ b/docs/how-to-guides/data-basics/1-setup.md @@ -2,6 +2,8 @@ We will build the application as a WordPress plugin, which means you need to have the WordPress itself installed. One way to do it is by following the instructions on [Getting Started](/docs/contributors/code/getting-started-with-code-contribution.md) page. Once your setup is finished, you can follow along with the rest of this tutorial. +## Creating a new plugin + To create a new plugin, create a `wp-content/plugins/first-gutenberg-app` directory in your local WordPress environment. We will need to create three files inside that directory: * first-gutenberg-app.php – to create a new admin page @@ -108,6 +110,7 @@ If you now go to the Plugins page, you should see a plugin called **My first Gut Congratulations! You are now ready to start building the app! ## Trading readability for convenience + You don’t need any build tools to complete this tutorial. All the code examples work as provided even if you paste them into your browser’s developer tools. The price to pay is in readability. The way React components are usually depicted is with the JSX syntax that looks like this: @@ -125,3 +128,4 @@ function MyFirstApp() { return wp.element.createElement('span', {}, 'Hello from JavaScript!'); } ``` + diff --git a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md index c73b68f688064d..e838812aff656d 100644 --- a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md +++ b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md @@ -4,7 +4,7 @@ In this part, we will build a filterable list of all WordPress pages. This is wh ![](./media/list-of-pages/part1-finished.jpg) -Let’s see how we can get there step by step +Let’s see how we can get there step by step. ## Step 1: Build the PagesList component Let’s start by building a minimal React component to display the list of pages: @@ -33,7 +33,15 @@ Note this component does not fetch any data yet, only presents the hardcoded lis ![](./media/list-of-pages/simple-list.jpg) ## Step 2: Fetch the data -The hardcoded sample page isn’t very useful, so let’s fetch the actual list of pages from the WordPress API. Instead of working directly with HTTP requests, we will use the [`getEntityRecords`](/docs/reference-guides/data/data-core/#getentityrecords) provided by Gutenberg’s `coreData`. In broad strokes, it will the correct API request, cache the results, and return the list of the entity records we need. Here’s how to use it: +The hardcoded sample page isn’t very useful. We want to display your actual WordPress pages so let’s fetch the actual list of pages from the WordPress API. + +Before we start, let’s confirm there are some pages for us to fetch. Navigate to Pages using the sidebar menu and confirm it shows at least four or five positions: + +![](./media/list-of-pages/pages-list.jpg) + +If it doesn’t, go ahead and create a few pages – you can use the same titles as on the screenshot above. Be sure to _publish_ and not just _save_ them. + +Now that we have the data to work with, let’s dive into the code. Instead of working directly with HTTP requests, we will use the [`getEntityRecords`](/docs/reference-guides/data/data-core/#getentityrecords) provided by Gutenberg’s `coreData`. In broad strokes, it will the correct API request, cache the results, and return the list of the entity records we need. Here’s how to use it: `wp.data.select('core').getEntityRecords( 'postType', 'page' ) ` diff --git a/docs/how-to-guides/data-basics/media/list-of-pages/pages-list.jpg b/docs/how-to-guides/data-basics/media/list-of-pages/pages-list.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f597019bff27d94fed427c5203c5867cf8b6f5d9 GIT binary patch literal 96566 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 literal 0 HcmV?d00001 From f680f689d09572592524e6a79de6d8bfe02db194 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Zieli=C5=84ski?= Date: Wed, 26 Jan 2022 17:40:24 +0100 Subject: [PATCH 03/51] Update the asset loading order --- docs/how-to-guides/data-basics/1-setup.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/how-to-guides/data-basics/1-setup.md b/docs/how-to-guides/data-basics/1-setup.md index 628c3533e89f86..5694b7da554d60 100644 --- a/docs/how-to-guides/data-basics/1-setup.md +++ b/docs/how-to-guides/data-basics/1-setup.md @@ -2,7 +2,7 @@ We will build the application as a WordPress plugin, which means you need to have the WordPress itself installed. One way to do it is by following the instructions on [Getting Started](/docs/contributors/code/getting-started-with-code-contribution.md) page. Once your setup is finished, you can follow along with the rest of this tutorial. -## Creating a new plugin +## Creating a plugin To create a new plugin, create a `wp-content/plugins/first-gutenberg-app` directory in your local WordPress environment. We will need to create three files inside that directory: @@ -81,16 +81,16 @@ function load_custom_wp_admin_scripts( $hook ) { return; } - // Load the style.css - wp_register_style( 'my-first-gutenberg-app', plugins_url( 'my-first-gutenberg-app/style.css' ) ); - wp_enqueue_style( 'wp-components' ); - wp_enqueue_style( 'my-first-gutenberg-app' ); - // Load the required WordPress packages + wp_enqueue_style( 'wp-components' ); wp_enqueue_script( 'wp-components' ); wp_enqueue_script( 'wp-data' ); wp_enqueue_script( 'wp-core-data' ); + // Load the style.css + wp_register_style( 'my-first-gutenberg-app', plugins_url( 'my-first-gutenberg-app/style.css' ) ); + wp_enqueue_style( 'my-first-gutenberg-app' ); + // Load the app.js wp_register_script( 'my-first-gutenberg-app', From e2e4893b907c9f8a222bea24896985bd9ac02602 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Zieli=C5=84ski?= Date: Wed, 26 Jan 2022 17:50:11 +0100 Subject: [PATCH 04/51] explain that core-data builds on top of the data in order to facilitate easy querying of WP data. --- .../data-basics/2-building-a-list-of-pages.md | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md index e838812aff656d..311bd095529ff8 100644 --- a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md +++ b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md @@ -33,6 +33,7 @@ Note this component does not fetch any data yet, only presents the hardcoded lis ![](./media/list-of-pages/simple-list.jpg) ## Step 2: Fetch the data + The hardcoded sample page isn’t very useful. We want to display your actual WordPress pages so let’s fetch the actual list of pages from the WordPress API. Before we start, let’s confirm there are some pages for us to fetch. Navigate to Pages using the sidebar menu and confirm it shows at least four or five positions: @@ -41,9 +42,13 @@ Before we start, let’s confirm there are some pages for us to fetch. Navigate If it doesn’t, go ahead and create a few pages – you can use the same titles as on the screenshot above. Be sure to _publish_ and not just _save_ them. -Now that we have the data to work with, let’s dive into the code. Instead of working directly with HTTP requests, we will use the [`getEntityRecords`](/docs/reference-guides/data/data-core/#getentityrecords) provided by Gutenberg’s `coreData`. In broad strokes, it will the correct API request, cache the results, and return the list of the entity records we need. Here’s how to use it: +Now that we have the data to work with, let’s dive into the code. We will take advantage of the Gutenberg’s `coreData` package which provides resolvers, selectors, and actions to work with the WordPress core API. `coreData` builds on top of the [Gutenberg’s `data` package](https://github.com/WordPress/gutenberg/tree/trunk/packages/data). + +To fetch the list of pages, we will use the [`getEntityRecords`](/docs/reference-guides/data/data-core/#getentityrecords) selector. In broad strokes, it will issue the correct API request, cache the results, and return the list of the records we need. Here’s how to use it: -`wp.data.select('core').getEntityRecords( 'postType', 'page' ) ` +```js +wp.data.select('core').getEntityRecords( 'postType', 'page' ) +``` If you run that following snippet in your browser’s dev tools, you will see it returns `null`. Why? The pages are only requested by `getEntityRecords` resolver after you first run the selector. If you wait a moment and run it again, it will return the list of all pages. @@ -149,7 +154,9 @@ We can now request only the pages matching the `searchTerm`. After checking with the [WordPress API documentation]([https://developer.wordpress.org/rest-api/reference/pages/]), we see that the [/wp/v2/pages]([https://developer.wordpress.org/rest-api/reference/pages/]) endpoint accepts a `search` query parameter and uses it to _Limit results to those matching a string_. But how to use it? We can pass custom query parameters as the third argument to `getEntityRecords` as below: -`wp.data.select('core').getEntityRecords( 'postType', 'page', { search: 'home' } )` +```js +wp.data.select('core').getEntityRecords( 'postType', 'page', { search: 'home' } ) +``` Running that snippet in your browser’s dev tools will trigger a request to `/wp/v2/pages?search=home` instead of just `/wp/v2/pages`. @@ -224,7 +231,7 @@ function MyFirstApp() { We would need to solve two problems here. -First, out-of-order updates. Searching for „About” would trigger five API requests filtering for A, Ab, Abo, Abou, and About. They could finish in a different order than they started. It is possible that _search=A_ would resolve after _ search=About_ and we’d display the wrong data. +First, out-of-order updates. Searching for „About” would trigger five API requests filtering for A, Ab, Abo, Abou, and About. They could finish in a different order than they started. It is possible that _search=A_ would resolve after _search=About_ and we’d display the wrong data. Gutenberg data helps by handling the asynchronous part behind the scenes. `useSelect` remembers the most recent call and returns only the data we expect. From 3f867d083579a68e180f9bb942a421da9b3f7767 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Zieli=C5=84ski?= Date: Wed, 26 Jan 2022 17:55:22 +0100 Subject: [PATCH 05/51] Replace @TODO with Coming soon: --- docs/how-to-guides/data-basics/README.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/docs/how-to-guides/data-basics/README.md b/docs/how-to-guides/data-basics/README.md index 685c96c12a64c5..17400ea07b98fb 100644 --- a/docs/how-to-guides/data-basics/README.md +++ b/docs/how-to-guides/data-basics/README.md @@ -1,4 +1,4 @@ -# Creating your First App with Gutenberg Data +# Create your First App with Gutenberg Data The goal of this tutorial is to get you comfortable on how to use the Gutenberg data layer. It guides you through the process of building a React application that enables the user to manage their WordPress pages. The finished app will look like this: @@ -8,8 +8,10 @@ The goal of this tutorial is to get you comfortable on how to use the Gutenberg 1. [Setup](./1-setup) 2. [Building a basic list of pages](./2-building-a-list-of-pages.md) -3. (@TODO) Adding an „Edit page” feature -4. (@TODO) Adding a „Create a new page” feature -5. (@TODO) Adding a „Delete” feature -6. (@TODO) Advanced pages list (author column, Treegrid) + +Coming soon: +3. Adding an „Edit page” feature +4. Adding a „Create a new page” feature +5. Adding a „Delete” feature +6. Advanced pages list (author column, Treegrid) From 07cd084aee9a4d71f2f3183d1f164b3d0a5261e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Zieli=C5=84ski?= Date: Mon, 31 Jan 2022 12:41:02 +0100 Subject: [PATCH 06/51] Use both JSX and uncompiled snippets --- .../data-basics/2-building-a-list-of-pages.md | 370 +++++++++++++++--- 1 file changed, 305 insertions(+), 65 deletions(-) diff --git a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md index 311bd095529ff8..7631e5a025c3ea 100644 --- a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md +++ b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md @@ -1,71 +1,109 @@ # Building a list of pages -In this part, we will build a filterable list of all WordPress pages. This is what the app will look like at the end of this part: +In this part, we will build a filterable list of all WordPress pages. This is what the app will look like at the end of +this part: ![](./media/list-of-pages/part1-finished.jpg) Let’s see how we can get there step by step. ## Step 1: Build the PagesList component + Let’s start by building a minimal React component to display the list of pages: ```js function MyFirstApp() { - const pages = [ { id: 'mock', title: 'Sample page' } ] + const pages = [{ id: 'mock', title: 'Sample page' }] + return ; +} + +function PagesList( { pages } ) { return ( - wp.element.createElement(PagesList, { pages }) +
    + { pages?.map( page => ( +
  • + { page.title } +
  • + ) ) } +
+ ); +} +``` + +
Compiled snippet + +```js +function MyFirstApp() { + const pages = [{ id: 'mock', title: 'Sample page' }] + return ( + wp.element.createElement( PagesList, { pages } ) ) } -function PagesList({ pages }) { +function PagesList( { pages } ) { return ( - wp.element.createElement('ul', {}, - pages?.map(page => ( - wp.element.createElement('li', {key: page.id}, page.title) - )) + wp.element.createElement( 'ul', {}, + pages?.map( page => ( + wp.element.createElement( 'li', { key: page.id }, page.title ) + ) ) ) ) } ``` -Note this component does not fetch any data yet, only presents the hardcoded list of pages. When you refresh the page, you should see the following: +
+ +Note this component does not fetch any data yet, only presents the hardcoded list of pages. When you refresh the page, +you should see the following: ![](./media/list-of-pages/simple-list.jpg) ## Step 2: Fetch the data -The hardcoded sample page isn’t very useful. We want to display your actual WordPress pages so let’s fetch the actual list of pages from the WordPress API. +The hardcoded sample page isn’t very useful. We want to display your actual WordPress pages so let’s fetch the actual +list of pages from the WordPress API. -Before we start, let’s confirm there are some pages for us to fetch. Navigate to Pages using the sidebar menu and confirm it shows at least four or five positions: +Before we start, let’s confirm there are some pages for us to fetch. Navigate to Pages using the sidebar menu and +confirm it shows at least four or five positions: ![](./media/list-of-pages/pages-list.jpg) -If it doesn’t, go ahead and create a few pages – you can use the same titles as on the screenshot above. Be sure to _publish_ and not just _save_ them. +If it doesn’t, go ahead and create a few pages – you can use the same titles as on the screenshot above. Be sure to _ +publish_ and not just _save_ them. -Now that we have the data to work with, let’s dive into the code. We will take advantage of the Gutenberg’s `coreData` package which provides resolvers, selectors, and actions to work with the WordPress core API. `coreData` builds on top of the [Gutenberg’s `data` package](https://github.com/WordPress/gutenberg/tree/trunk/packages/data). +Now that we have the data to work with, let’s dive into the code. We will take advantage of the Gutenberg’s `coreData` +package which provides resolvers, selectors, and actions to work with the WordPress core API. `coreData` builds on top +of the [Gutenberg’s `data` package](https://github.com/WordPress/gutenberg/tree/trunk/packages/data). -To fetch the list of pages, we will use the [`getEntityRecords`](/docs/reference-guides/data/data-core/#getentityrecords) selector. In broad strokes, it will issue the correct API request, cache the results, and return the list of the records we need. Here’s how to use it: +To fetch the list of pages, we will use +the [`getEntityRecords`](/docs/reference-guides/data/data-core/#getentityrecords) selector. In broad strokes, it will +issue the correct API request, cache the results, and return the list of the records we need. Here’s how to use it: ```js -wp.data.select('core').getEntityRecords( 'postType', 'page' ) +wp.data.select( 'core' ).getEntityRecords( 'postType', 'page' ) ``` -If you run that following snippet in your browser’s dev tools, you will see it returns `null`. Why? The pages are only requested by `getEntityRecords` resolver after you first run the selector. If you wait a moment and run it again, it will return the list of all pages. +If you run that following snippet in your browser’s dev tools, you will see it returns `null`. Why? The pages are only +requested by `getEntityRecords` resolver after you first run the selector. If you wait a moment and run it again, it +will return the list of all pages. -Similarly, the `MyFirstApp` component needs to re-run the selector once the data is available. That’s exactly what the `useSelect` hook does: +Similarly, the `MyFirstApp` component needs to re-run the selector once the data is available. That’s exactly what +the `useSelect` hook does: ```js function MyFirstApp() { const pages = wp.data.useSelect( select => - select( wp.coreData.store ).getEntityRecords( 'postType', 'page' ), + select( wp.coreData.store ).getEntityRecords( 'postType', 'page' ), [] ); // ... } ``` -`useSelect` takes two arguments: a callback and dependencies. In broad strokes, it re-runs the callback whenever either the dependencies or the underlying data store changes. You can learn more about [useSelect](#) in the [data module documentation](/packages/data/README.md#useselect). +`useSelect` takes two arguments: a callback and dependencies. In broad strokes, it re-runs the callback whenever either +the dependencies or the underlying data store changes. You can learn more about [useSelect](#) in +the [data module documentation](/packages/data/README.md#useselect). Putting it together, we get the following code: @@ -73,25 +111,52 @@ Putting it together, we get the following code: function MyFirstApp() { const pages = wp.data.useSelect( select => - select( wp.coreData.store ).getEntityRecords( 'postType', 'page' ), + select( wp.coreData.store ).getEntityRecords( 'postType', 'page' ), [] ); + return ; +} + +function PagesList( { pages } ) { return ( - wp.element.createElement(PagesList, { pages }) +
    + { pages?.map( page => ( +
  • + { page.title.rendered } +
  • + ) ) } +
) } +``` + +
Compiled snippet -function PagesList({ pages }) { +```js +function MyFirstApp() { + const pages = wp.data.useSelect( + select => + select( wp.coreData.store ).getEntityRecords( 'postType', 'page' ), + [] + ); + return ( + wp.element.createElement( PagesList, { pages } ) + ) +} + +function PagesList( { pages } ) { return ( - wp.element.createElement('ul', {}, - pages?.map(page => ( - wp.element.createElement('li', {key: page.id}, page.title.rendered) - )) + wp.element.createElement( 'ul', {}, + pages?.map( page => ( + wp.element.createElement( 'li', { key: page.id }, page.title ) + ) ) ) ) } ``` +
+ Refreshing the page should display a list similar to this one: ![](./media/list-of-pages/fetch-the-data.jpg) @@ -99,7 +164,30 @@ Refreshing the page should display a list similar to this one: ## Step 3: Turn it into a table ```js -function PagesList({ pages }) { +function PagesList( { pages } ) { + return ( + + + + + + + + { pages?.map( page => ( + + + + ) ) } + +
Title
{ page.title.rendered }
+ ); +} +``` + +
Compiled snippet + +```js +function PagesList( { pages } ) { return wp.element.createElement( 'table', { className: 'wp-list-table widefat fixed striped table-view-list' }, @@ -119,21 +207,41 @@ function PagesList({ pages }) { } ``` +
+ ![](./media/list-of-pages/make-a-table.jpg) ## Step 4: Add a search Box -The list of pages is short for now, however the longer it grows the harder it is to work with. WordPress admins typically solves this problem with a search box – let’s implement one, too! + +The list of pages is short for now, however the longer it grows the harder it is to work with. WordPress admins +typically solves this problem with a search box – let’s implement one, too! Let’s start by adding a search field: ```js function MyFirstApp() { - const [searchTerm, setSearchTerm] = wp.element.useState(''); - + const [searchTerm, setSearchTerm] = wp.element.useState( '' ); // ... + return ( +
+ + {/* ... */ } +
+ ) +} +``` +
Compiled snippet + +```js +function MyFirstApp() { + const [searchTerm, setSearchTerm] = wp.element.useState( '' ); + // ... return ( - wp.element.createElement('div', {}, + wp.element.createElement( 'div', {}, wp.element.createElement( wp.components.SearchControl, { onChange: setSearchTerm, value: searchTerm, @@ -144,58 +252,94 @@ function MyFirstApp() { } ``` -Note that instead of using an `input` tag, we took advantage of the [SearchControl](https://developer.wordpress.org/block-editor/reference-guides/components/search-control/) component. This is how it looks like: +
+ +Note that instead of using an `input` tag, we took advantage of +the [SearchControl](https://developer.wordpress.org/block-editor/reference-guides/components/search-control/) component. +This is how it looks like: ![](./media/list-of-pages/filter-field.jpg) -The field starts empty and the contents are stored in the `searchTerm` state value. If you aren’t familiar with the [useState](https://reactjs.org/docs/hooks-state.html) hook, you can learn more in [React’s documentation](https://reactjs.org/docs/hooks-state.html). +The field starts empty and the contents are stored in the `searchTerm` state value. If you aren’t familiar with +the [useState](https://reactjs.org/docs/hooks-state.html) hook, you can learn more +in [React’s documentation](https://reactjs.org/docs/hooks-state.html). We can now request only the pages matching the `searchTerm`. -After checking with the [WordPress API documentation]([https://developer.wordpress.org/rest-api/reference/pages/]), we see that the [/wp/v2/pages]([https://developer.wordpress.org/rest-api/reference/pages/]) endpoint accepts a `search` query parameter and uses it to _Limit results to those matching a string_. But how to use it? We can pass custom query parameters as the third argument to `getEntityRecords` as below: +After checking with the [WordPress API documentation]([https://developer.wordpress.org/rest-api/reference/pages/]), we +see that the [/wp/v2/pages]([https://developer.wordpress.org/rest-api/reference/pages/]) endpoint accepts a `search` +query parameter and uses it to _Limit results to those matching a string_. But how to use it? We can pass custom query +parameters as the third argument to `getEntityRecords` as below: ```js -wp.data.select('core').getEntityRecords( 'postType', 'page', { search: 'home' } ) +wp.data.select( 'core' ).getEntityRecords( 'postType', 'page', { search: 'home' } ) ``` -Running that snippet in your browser’s dev tools will trigger a request to `/wp/v2/pages?search=home` instead of just `/wp/v2/pages`. +Running that snippet in your browser’s dev tools will trigger a request to `/wp/v2/pages?search=home` instead of +just `/wp/v2/pages`. Let’s update our `useSelect` call as follows: ```js function MyFirstApp() { // ... - const { pages } = wp.data.useSelect(select => { + const { pages } = wp.data.useSelect( select => { const query = {}; - if (searchTerm) { + if ( searchTerm ) { query.search = searchTerm; } return { - pages: select(wp.coreData.store).getEntityRecords('postType', 'page', query) + pages: select( wp.coreData.store ).getEntityRecords( 'postType', 'page', query ) } - }, [searchTerm]); + }, [searchTerm] ); // ... } ``` -The `searchTerm` is now used as a `search` query parameter when specified. Note that `searchTerm` is also specified inside the list of `useSelect` dependencies to make sure `getEntityRecords` is re-run when the `searchTerm` changes. +The `searchTerm` is now used as a `search` query parameter when specified. Note that `searchTerm` is also specified +inside the list of `useSelect` dependencies to make sure `getEntityRecords` is re-run when the `searchTerm` changes. Finally, here’s how `MyFirstApp` looks like once we wire it all together: ```js function MyFirstApp() { - const [searchTerm, setSearchTerm] = wp.element.useState(''); - const pages = wp.data.useSelect(select => { + const [searchTerm, setSearchTerm] = wp.element.useState( '' ); + const pages = wp.data.useSelect( select => { const query = {}; - if (searchTerm) { + if ( searchTerm ) { query.search = searchTerm; } - return select(wp.coreData.store).getEntityRecords('postType', 'page', query); - }, [searchTerm]); + return select( wp.coreData.store ).getEntityRecords( 'postType', 'page', query ); + }, [searchTerm] ); return ( - wp.element.createElement('div', {}, +
+ + +
+ ) +} +``` + +
Compiled snippet + +```js +function MyFirstApp() { + const [searchTerm, setSearchTerm] = wp.element.useState( '' ); + const pages = wp.data.useSelect( select => { + const query = {}; + if ( searchTerm ) { + query.search = searchTerm; + } + return select( wp.coreData.store ).getEntityRecords( 'postType', 'page', query ); + }, [searchTerm] ); + + return ( + wp.element.createElement( 'div', {}, wp.element.createElement( wp.components.SearchControl, { onChange: setSearchTerm, value: searchTerm, @@ -206,8 +350,9 @@ function MyFirstApp() { } ``` -Voila! We can now filter the results: +
+Voila! We can now filter the results: ![](./media/list-of-pages/filter.jpg) @@ -222,24 +367,30 @@ function MyFirstApp() { useEffect( () => { const url = '/wp-json/wp/v2/pages?search=' + searchTerm; wp - .apiFetch({ url }) + .apiFetch( { url } ) .then( setPages ) - }, [searchTerm]); + }, [searchTerm] ); // ... } ``` We would need to solve two problems here. -First, out-of-order updates. Searching for „About” would trigger five API requests filtering for A, Ab, Abo, Abou, and About. They could finish in a different order than they started. It is possible that _search=A_ would resolve after _search=About_ and we’d display the wrong data. +First, out-of-order updates. Searching for „About” would trigger five API requests filtering for A, Ab, Abo, Abou, and +About. They could finish in a different order than they started. It is possible that _search=A_ would resolve after _ +search=About_ and we’d display the wrong data. -Gutenberg data helps by handling the asynchronous part behind the scenes. `useSelect` remembers the most recent call and returns only the data we expect. +Gutenberg data helps by handling the asynchronous part behind the scenes. `useSelect` remembers the most recent call and +returns only the data we expect. -Second, every key stroke would trigger an API request. If you typed About, deleted it, and typed it again, it would issue 10 requests in total even though we could reuse the data. +Second, every key stroke would trigger an API request. If you typed About, deleted it, and typed it again, it would +issue 10 requests in total even though we could reuse the data. -Gutenberg data helps by caching the responses to API requests triggered by `getEntityRecords()` and reuses them on subsequent calls. This is especially important when there’s more other components relying on `getEntityRecords()`. +Gutenberg data helps by caching the responses to API requests triggered by `getEntityRecords()` and reuses them on +subsequent calls. This is especially important when there’s more other components relying on `getEntityRecords()`. -All in all, the built-in utilities are designed to solve the typical problems so that you can focus on your application instead. +All in all, the built-in utilities are designed to solve the typical problems so that you can focus on your application +instead. ## Step 5: Loading Indicator @@ -247,15 +398,40 @@ There is one problem with our search feature. We can’t be quite sure whether i ![](./media/list-of-pages/unclear-status.jpg) -A few messages like _Loading…_ or _No results_ would clear it up. Let’s implement them! First, `PagesList` has to be aware of the current status: +A few messages like _Loading…_ or _No results_ would clear it up. Let’s implement them! First, `PagesList` has to be +aware of the current status: ```js +function PagesList( { hasResolved, pages } ) { + if ( !hasResolved ) { + return + } + if ( !pages?.length ) { + return
No results
+ } + // ... +} +function MyFirstApp() { + // ... + + return ( +
+ // ... + +
+ ) +} +``` + +
Compiled snippet + +```js function PagesList( { hasResolved, pages } ) { - if ( ! hasResolved ) { + if ( !hasResolved ) { return wp.element.createElement( wp.components.Spinner ); } - if ( ! pages?.length ) { + if ( !pages?.length ) { return wp.element.createElement( 'div', {}, 'No results' ); } // ... @@ -273,24 +449,30 @@ function MyFirstApp() { } ``` -Note that instead of building a custom loading indicator, we took advantage of the [Spinner](https://developer.wordpress.org/block-editor/reference-guides/components/spinner/) component. +
-We still need to know whether the pages selector `hasResolved` or not. We can find out using the `hasFinishedResolution` selector: +Note that instead of building a custom loading indicator, we took advantage of +the [Spinner](https://developer.wordpress.org/block-editor/reference-guides/components/spinner/) component. + +We still need to know whether the pages selector `hasResolved` or not. We can find out using +the `hasFinishedResolution` selector: `wp.data.select('core').hasFinishedResolution( 'getEntityRecords', [ 'postType', 'page', { search: 'home' } ] )` -It takes the name of the selector and the arguments, and returns either `true` if the data was already loaded or `false` it we’re still waiting. Let’s add it to `wp.data.useSelect`: +It takes the name of the selector and the arguments, and returns either `true` if the data was already loaded or `false` +it we’re still waiting. Let’s add it to `wp.data.useSelect`: ```js function MyFirstApp() { // ... - const { pages, hasResolved } = wp.data.useSelect(select => { + const { pages, hasResolved } = wp.data.useSelect( select => { // ... return { - pages: // ... - hasResolved: select(wp.coreData.store).hasFinishedResolution( 'getEntityRecords', [ 'postType', 'page', query ] ), + pages: {/* ... */ }, + hasResolved: + select( wp.coreData.store ).hasFinishedResolution( 'getEntityRecords', ['postType', 'page', query] ), } - }, [searchTerm]); + }, [searchTerm] ); // ... } @@ -300,6 +482,62 @@ All the pieces are in place, great! Here’s the complete JavaScript code of our ```js +function MyFirstApp() { + const [searchTerm, setSearchTerm] = wp.element.useState( '' ); + const { pages, hasResolved } = wp.data.useSelect( select => { + const query = {}; + if ( searchTerm ) { + query.search = searchTerm; + } + return { + pages: select( wp.coreData.store ).getEntityRecords( 'postType', 'page', query ), + hasResolved: select( wp.coreData.store ) + .hasFinishedResolution( 'getEntityRecords', ['postType', 'page', query] ), + }; + }, [searchTerm] ); + + return ( +
+ + +
+ ); +} + +function PagesList( { hasResolved, pages } ) { + if ( !hasResolved ) { + return + } + if ( !pages?.length ) { + return
No results
; + } + + return ( + + + + + + + + { pages?.map( page => ( + + + + ) ) } + +
Title
{ page.title.rendered }
+ ); +} +``` + +
Compiled snippet + +```js + function MyFirstApp() { const [searchTerm, setSearchTerm] = wp.element.useState( '' ); const { pages, hasResolved } = wp.data.useSelect( select => { @@ -352,6 +590,8 @@ function PagesList( { hasResolved, pages } ) { } ``` +
+ All that’s left is to refresh the page and enjoy the brand new status indicator: ![](./media/list-of-pages/indicator.jpg) From 6ccef394dce032f0ca8d55ef68a6aabdf7ab907e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Zieli=C5=84ski?= Date: Mon, 31 Jan 2022 12:43:33 +0100 Subject: [PATCH 07/51] Don't use wp.components inside JSX syntax --- .../data-basics/2-building-a-list-of-pages.md | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md index 7631e5a025c3ea..6e07cff2d46987 100644 --- a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md +++ b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md @@ -219,12 +219,13 @@ typically solves this problem with a search box – let’s implement one, too! Let’s start by adding a search field: ```js +const { SearchControl } = wp.components; function MyFirstApp() { const [searchTerm, setSearchTerm] = wp.element.useState( '' ); // ... return (
- @@ -303,6 +304,7 @@ inside the list of `useSelect` dependencies to make sure `getEntityRecords` is r Finally, here’s how `MyFirstApp` looks like once we wire it all together: ```js +const { SearchControl } = wp.components; function MyFirstApp() { const [searchTerm, setSearchTerm] = wp.element.useState( '' ); const pages = wp.data.useSelect( select => { @@ -315,7 +317,7 @@ function MyFirstApp() { return (
- @@ -402,9 +404,10 @@ A few messages like _Loading…_ or _No results_ would clear it up. Let’s imp aware of the current status: ```js +const { Spinner } = wp.components; function PagesList( { hasResolved, pages } ) { if ( !hasResolved ) { - return + return } if ( !pages?.length ) { return
No results
@@ -481,6 +484,7 @@ function MyFirstApp() { All the pieces are in place, great! Here’s the complete JavaScript code of our app: ```js +const { SearchControl, Spinner } = wp.components; function MyFirstApp() { const [searchTerm, setSearchTerm] = wp.element.useState( '' ); @@ -498,7 +502,7 @@ function MyFirstApp() { return (
- @@ -509,7 +513,7 @@ function MyFirstApp() { function PagesList( { hasResolved, pages } ) { if ( !hasResolved ) { - return + return } if ( !pages?.length ) { return
No results
; From 8ab44c5b5b65e825bcda7b6afc08554b109a871d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Zieli=C5=84ski?= Date: Mon, 31 Jan 2022 15:46:34 +0100 Subject: [PATCH 08/51] Explain the JSX syntax vs compiled syntax --- docs/how-to-guides/data-basics/1-setup.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/docs/how-to-guides/data-basics/1-setup.md b/docs/how-to-guides/data-basics/1-setup.md index 5694b7da554d60..e556e06f3e9347 100644 --- a/docs/how-to-guides/data-basics/1-setup.md +++ b/docs/how-to-guides/data-basics/1-setup.md @@ -109,11 +109,11 @@ If you now go to the Plugins page, you should see a plugin called **My first Gut Congratulations! You are now ready to start building the app! -## Trading readability for convenience +## Readability vs Convenience -You don’t need any build tools to complete this tutorial. All the code examples work as provided even if you paste them into your browser’s developer tools. +You don’t need a build tool to complete this tutorial, but using one will make your core look nicer. -The price to pay is in readability. The way React components are usually depicted is with the JSX syntax that looks like this: +The examples in this tutorial use the JSX syntax: ```js function MyFirstApp() { @@ -121,7 +121,9 @@ function MyFirstApp() { } ``` -It was tempting to use that syntax here, however, it would complicate the initial setup. We would need to install node.js, a build tool like webpack, and compile the app on each change. None of that is required for this tutorial. The trade-off is that we are restricted to the regular JavaScript syntax as below: +It is succinct and readable, but the payoff is you need a build tool like webpack to use it. If that's what you prefer, the [Getting Started with JavaScript](/how-to-guides/javascript/) tutorial will guide you through setting up the build tool. + +There's also an another way. If you'd like to start building your app right away, every JSX snippet is followed by a compiled version that works as-is: ```js function MyFirstApp() { @@ -129,3 +131,4 @@ function MyFirstApp() { } ``` +You can safely ignore the JSX snippets and rely on their compiled versions – they will just work even when pasted to your browser's developer tools. From 2c7bcd024d6498f9ef327c5912442fb306b1d51c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Zieli=C5=84ski?= Date: Mon, 31 Jan 2022 15:57:17 +0100 Subject: [PATCH 09/51] Explain all the dependencies of our app.js --- docs/how-to-guides/data-basics/1-setup.md | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/docs/how-to-guides/data-basics/1-setup.md b/docs/how-to-guides/data-basics/1-setup.md index e556e06f3e9347..0e09e21fb7bb15 100644 --- a/docs/how-to-guides/data-basics/1-setup.md +++ b/docs/how-to-guides/data-basics/1-setup.md @@ -81,23 +81,34 @@ function load_custom_wp_admin_scripts( $hook ) { return; } - // Load the required WordPress packages + // Load the required WordPress packages: + + // wp-components is a library of generic WordPress components + // used for building consistent user interfaces across the board. wp_enqueue_style( 'wp-components' ); wp_enqueue_script( 'wp-components' ); + + // wp-data provides data management backbone such as the Redux + // implementation or data resolution mechanisms. wp_enqueue_script( 'wp-data' ); - wp_enqueue_script( 'wp-core-data' ); - // Load the style.css - wp_register_style( 'my-first-gutenberg-app', plugins_url( 'my-first-gutenberg-app/style.css' ) ); - wp_enqueue_style( 'my-first-gutenberg-app' ); + // wp-core-data is a glue between WordPress Core and wp-data. + // It provides a Redux store with a number of selectors and actions to + // power common tasks such as loading the data from the WordPress REST API, + // editing it in the browser, and persisting the changes back to the REST API. + wp_enqueue_script( 'wp-core-data' ); - // Load the app.js + // Load our app.js wp_register_script( 'my-first-gutenberg-app', plugins_url( 'my-first-gutenberg-app/app.js' ), array( 'wp-components', 'wp-data', 'wp-core-data' ), ); wp_enqueue_script( 'my-first-gutenberg-app' ); + + // Load our style.css + wp_register_style( 'my-first-gutenberg-app', plugins_url( 'my-first-gutenberg-app/style.css' ) ); + wp_enqueue_style( 'my-first-gutenberg-app' ); } add_action( 'admin_enqueue_scripts', 'load_custom_wp_admin_scripts' ); From a45dbd4c931d98fadadddaefba224ddc30591848 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Zieli=C5=84ski?= Date: Mon, 31 Jan 2022 16:13:59 +0100 Subject: [PATCH 10/51] Grammar improvements --- docs/how-to-guides/data-basics/1-setup.md | 8 +++---- .../data-basics/2-building-a-list-of-pages.md | 22 +++++++++---------- docs/how-to-guides/data-basics/README.md | 2 +- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/docs/how-to-guides/data-basics/1-setup.md b/docs/how-to-guides/data-basics/1-setup.md index 0e09e21fb7bb15..5bc87c91979d3e 100644 --- a/docs/how-to-guides/data-basics/1-setup.md +++ b/docs/how-to-guides/data-basics/1-setup.md @@ -4,7 +4,7 @@ We will build the application as a WordPress plugin, which means you need to hav ## Creating a plugin -To create a new plugin, create a `wp-content/plugins/first-gutenberg-app` directory in your local WordPress environment. We will need to create three files inside that directory: +We'll do all the development inside of a WordPress plugin. Let's start by creating a `wp-content/plugins/first-gutenberg-app` directory in your local WordPress environment. We will need to create three files inside that directory: * first-gutenberg-app.php – to create a new admin page * script.js – for our JavaScript application @@ -114,7 +114,7 @@ function load_custom_wp_admin_scripts( $hook ) { add_action( 'admin_enqueue_scripts', 'load_custom_wp_admin_scripts' ); ``` -If you now go to the Plugins page, you should see a plugin called **My first Gutenberg App**. Go ahead and activate it. A new menu position labeled _My first Gutenberg app_ should show up. Once you click it, you will see a page that says _Hello from JavaScript!_: +If you now go to the Plugins page, you should see a plugin called **My first Gutenberg App**. Go ahead and activate it. A new menu item labeled _My first Gutenberg app_ should show up. Once you click it, you will see a page that says _Hello from JavaScript!_: ![](./media/setup/hello-from-js.jpg) @@ -132,9 +132,9 @@ function MyFirstApp() { } ``` -It is succinct and readable, but the payoff is you need a build tool like webpack to use it. If that's what you prefer, the [Getting Started with JavaScript](/how-to-guides/javascript/) tutorial will guide you through setting up the build tool. +It is concise and readable, but the payoff is you need a build tool like webpack to use it. If that's what you prefer, the [Getting Started with JavaScript](/how-to-guides/javascript/) tutorial will guide you through setting up the build tool. -There's also an another way. If you'd like to start building your app right away, every JSX snippet is followed by a compiled version that works as-is: +There's also another way. If you'd like to start building your app right away, every JSX snippet is followed by a compiled version that works as-is: ```js function MyFirstApp() { diff --git a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md index 6e07cff2d46987..e3c9307bda1d51 100644 --- a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md +++ b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md @@ -53,18 +53,18 @@ function PagesList( { pages } ) { -Note this component does not fetch any data yet, only presents the hardcoded list of pages. When you refresh the page, +Note that this component does not fetch any data yet, only presents the hardcoded list of pages. When you refresh the page, you should see the following: ![](./media/list-of-pages/simple-list.jpg) ## Step 2: Fetch the data -The hardcoded sample page isn’t very useful. We want to display your actual WordPress pages so let’s fetch the actual +The hard-coded sample page isn’t very useful. We want to display your actual WordPress pages so let’s fetch the actual list of pages from the WordPress API. -Before we start, let’s confirm there are some pages for us to fetch. Navigate to Pages using the sidebar menu and -confirm it shows at least four or five positions: +Before we start, let’s confirm we actually have some pages to fetch. Navigate to Pages using the sidebar menu and +ensure it shows at least four or five positions: ![](./media/list-of-pages/pages-list.jpg) @@ -84,7 +84,7 @@ wp.data.select( 'core' ).getEntityRecords( 'postType', 'page' ) ``` If you run that following snippet in your browser’s dev tools, you will see it returns `null`. Why? The pages are only -requested by `getEntityRecords` resolver after you first run the selector. If you wait a moment and run it again, it +requested by `getEntityRecords` resolver after first running the selector. If you wait a moment and re-run it, it will return the list of all pages. Similarly, the `MyFirstApp` component needs to re-run the selector once the data is available. That’s exactly what @@ -213,7 +213,7 @@ function PagesList( { pages } ) { ## Step 4: Add a search Box -The list of pages is short for now, however the longer it grows the harder it is to work with. WordPress admins +The list of pages is short for now; however, the longer it grows, the harder it is to work with. WordPress admins typically solves this problem with a search box – let’s implement one, too! Let’s start by adding a search field: @@ -257,11 +257,11 @@ function MyFirstApp() { Note that instead of using an `input` tag, we took advantage of the [SearchControl](https://developer.wordpress.org/block-editor/reference-guides/components/search-control/) component. -This is how it looks like: +This is what it looks like: ![](./media/list-of-pages/filter-field.jpg) -The field starts empty and the contents are stored in the `searchTerm` state value. If you aren’t familiar with +The field starts empty, and the contents are stored in the `searchTerm` state value. If you aren’t familiar with the [useState](https://reactjs.org/docs/hooks-state.html) hook, you can learn more in [React’s documentation](https://reactjs.org/docs/hooks-state.html). @@ -385,11 +385,11 @@ search=About_ and we’d display the wrong data. Gutenberg data helps by handling the asynchronous part behind the scenes. `useSelect` remembers the most recent call and returns only the data we expect. -Second, every key stroke would trigger an API request. If you typed About, deleted it, and typed it again, it would +Second, every keystroke would trigger an API request. If you typed About, deleted it, and retyped it, it would issue 10 requests in total even though we could reuse the data. Gutenberg data helps by caching the responses to API requests triggered by `getEntityRecords()` and reuses them on -subsequent calls. This is especially important when there’s more other components relying on `getEntityRecords()`. +subsequent calls. This is especially important when other components rely on the same entity records. All in all, the built-in utilities are designed to solve the typical problems so that you can focus on your application instead. @@ -462,7 +462,7 @@ the `hasFinishedResolution` selector: `wp.data.select('core').hasFinishedResolution( 'getEntityRecords', [ 'postType', 'page', { search: 'home' } ] )` -It takes the name of the selector and the arguments, and returns either `true` if the data was already loaded or `false` +It takes the name of the selector and the arguments and returns either `true` if the data was already loaded or `false` it we’re still waiting. Let’s add it to `wp.data.useSelect`: ```js diff --git a/docs/how-to-guides/data-basics/README.md b/docs/how-to-guides/data-basics/README.md index 17400ea07b98fb..23714ed841184a 100644 --- a/docs/how-to-guides/data-basics/README.md +++ b/docs/how-to-guides/data-basics/README.md @@ -1,6 +1,6 @@ # Create your First App with Gutenberg Data -The goal of this tutorial is to get you comfortable on how to use the Gutenberg data layer. It guides you through the process of building a React application that enables the user to manage their WordPress pages. The finished app will look like this: +This tutorial aims to get you comfortable with the Gutenberg data layer. It guides you through building a React application that enables the user to manage their WordPress pages. The finished app will look like this: ![](./media/finished-app.jpg) From ba2b0fa95c9cab483b6cb62891e400c0d7c251b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Zieli=C5=84ski?= Date: Mon, 31 Jan 2022 16:16:29 +0100 Subject: [PATCH 11/51] Link to last part and next part --- docs/how-to-guides/data-basics/1-setup.md | 3 +++ docs/how-to-guides/data-basics/2-building-a-list-of-pages.md | 3 +++ docs/how-to-guides/data-basics/README.md | 1 + 3 files changed, 7 insertions(+) diff --git a/docs/how-to-guides/data-basics/1-setup.md b/docs/how-to-guides/data-basics/1-setup.md index 5bc87c91979d3e..2416dd7a438ef2 100644 --- a/docs/how-to-guides/data-basics/1-setup.md +++ b/docs/how-to-guides/data-basics/1-setup.md @@ -143,3 +143,6 @@ function MyFirstApp() { ``` You can safely ignore the JSX snippets and rely on their compiled versions – they will just work even when pasted to your browser's developer tools. + +Previous part: [Introduction](./README.md) +Next part: [Building a basic list of pages](./2-building-a-list-of-pages.md) diff --git a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md index e3c9307bda1d51..dce504b82b82a7 100644 --- a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md +++ b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md @@ -600,3 +600,6 @@ All that’s left is to refresh the page and enjoy the brand new status indicato ![](./media/list-of-pages/indicator.jpg) ![](./media/list-of-pages/no-results.jpg) + +Previous part: [Setup](./1-setup.md) +Next part: Adding an „Edit page” feature (coming soon) diff --git a/docs/how-to-guides/data-basics/README.md b/docs/how-to-guides/data-basics/README.md index 23714ed841184a..d9a6fe792aa4a3 100644 --- a/docs/how-to-guides/data-basics/README.md +++ b/docs/how-to-guides/data-basics/README.md @@ -10,6 +10,7 @@ This tutorial aims to get you comfortable with the Gutenberg data layer. It guid 2. [Building a basic list of pages](./2-building-a-list-of-pages.md) Coming soon: + 3. Adding an „Edit page” feature 4. Adding a „Create a new page” feature 5. Adding a „Delete” feature From c36f2b39fbb01f14e87839ea3daf394e2e4e3f83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Zieli=C5=84ski?= Date: Mon, 31 Jan 2022 16:19:28 +0100 Subject: [PATCH 12/51] Improve cropping of the screenshots --- .../data-basics/media/finished-app.jpg | Bin 33691 -> 35901 bytes .../media/list-of-pages/fetch-the-data.jpg | Bin 6027 -> 6686 bytes .../media/list-of-pages/filter-field.jpg | Bin 13639 -> 18332 bytes .../media/list-of-pages/make-a-table.jpg | Bin 12740 -> 15840 bytes .../data-basics/media/setup/hello-from-js.jpg | Bin 4052 -> 3698 bytes 5 files changed, 0 insertions(+), 0 deletions(-) diff --git a/docs/how-to-guides/data-basics/media/finished-app.jpg b/docs/how-to-guides/data-basics/media/finished-app.jpg index 8a69a282feab08af7c12a01ec588cc3492a79217..533b37144de405e8444ce6ca9922830f6bfaf637 100644 GIT binary patch literal 35901 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�^v=L`U1 z^l(8&LZXI_5eSUL_L+@fH;VD&%;mgL9<_eWuL*cP^coWJhl+FSs(p7IJnlwj`Nz*0 z^|FweTok=*e0i#@h&%&m1uZ+=bVyvkL`H6_FiT86aRz(UVfrT z6ATE^cJkhiZN1m#)SI6spxR{D^2MBiS?}NvH?>cuYZ*5pgRt2$2OPmP-7`c{JbYH8 zIu|n=&%Rx#s z9cwkq(d+eaei@9;-APPWUb@y#zYFvVa4c##bornh8w`PBp3n*;(56Dy5AH0PQdF@? z(@A1~6W#ZnXueA?U=B{Tn%^l%-Z>DtvcJ91H)+@38^ggEk&~cANTw;v-Ejf%+bW9; zVS1ZGA(7SEBgY>m>^HtuibeR_QoGg^Oxc#*@kscuw^04|7eTM4~A_0TG)s`nEq=A1$HW=^5SNy0) zyNdHiIjnvRtFzNNsSR#(75(glMTH5ZW7$ynGEGv;S69fz$bG>2Sl}ib&@;r%<;_c- z%UhA9?t#!1b^6w)M@>?ut5>pDG?A?Xp|LqlWLnf#DdEYRXsO^K_{EC(3t{?+nhB?m zmA z#SG>OBPpP~4smWVWIxl-oJkC=Y7*`clMb{#QeCK{8>q>lxL*SVoC$$f&3i%xv<5l| z!RUhVVlD-OYPfs54RfOJTXTI0|F#TV}j=+YJ?!?fAn{r-MaX+e5M?2&-UUC3t7*70AxbpP7LvbJhH`mA-nRn#hJTeb#R&@^k$E#ZIuxN6h%_)LV(^!qUQ z{j6y%+!MNCG9p2huf812HpVh$T`o-Fw5>e#yc-Q|MCa$1UPgefuJ@;6_P7UYUb*!O zcAE`%Y`2(0B6P+uolp-P)J{E^kZPAp^~z=!geEg_X<9ou@XaS+5beOu_ z)QKaFu_@SNxnw?dA}}*kD8$WvxuJL8q9XkJAd_(thK{0NPsFY6hBf=|`>b+yI13ww z%Vh*x2BS!QOMW z5dX&-x7;yXr^Cte-UwXrK^2}Qs0Ss!9crImup9I;aU@O&14(Kw|ny3 zAm4P{C3U|`6WM#?!9ePP5`w&mStf8Pw70OQZ8!(3-@b!rvee5{SW-LOesIz>^(l9k zk#9_DL6t*xDt zWE3WfbEmxTT%?P)N z&n~)1SB%T??&8e$;vL^ddRHPa^1M7%yBxhOYO~Rt$fM_VHAhOH9`CF(VW;X2aD8O9 zY6Y}*LuYn_+NIdi+vzc2(oqiH6e}&H@JYn>!r|$Bqp+tfYXeus0+&UMWWOU|L;-xI zGCvX_ozboC^x?I;5*TTeD+C+rG!ANoO8g*id8Yz~$C!L?lc=#J#45tc^z z68Sb=ii48F)z3PsphO|AE&dFIRSoHcbCB1qD-rY;7Yme)z4kA~qQBi|=93GsVEnxN zM!iYkda1VlZ3>89xO|H5q{+NX=OQZTu`1)ptKoMk{WI>U7oO)H_Sa{%YA3j}Wb2;N z{wSvm{6K%Q(Uc+Zq=~3=L$QABiZySC8gsrTHOmm@FEB{novfob|5Xu9n?mFjXqu#S zTDbK9!y6T7*Qr?S=7zl%P{HCnboz# zy)I_v(vv;})~!ZSgP=&)8R0!C!=JHJ5o*Ytc|6uQd`?pQY`APt03;fc1W2N_0#ng3 z6K~vnKF8UL%<#XpbMr9?sdjVss=Jm3QS)XSZQWmRQfesGNeI(t2c#$7yPNr%&VQ5&+Ie_dp!Ox+ z)Z$BacGkgtq3hFR)zX@Y-4lgA6&zuCwRm=Fsrgz83O(wvi3743{5OG>ZaD8T5SjliKX!N^a)-u&o_$CooSl zePlAU;GyIqy$kE~gQ!o1s`+)kp6ni@w&VFa%!CIzZV=~74S~z^ z?lp2taK3*18nR59cCzcn_weeY?dg#diMNsNZsLwwKrBdhm5nDIg0CZv+x1v$!gFMqfLxlnS z`M?wc)L!=rWjBz%F&+HbBCY}00G$9M<(>>4YH!4_^1Dm5&4Ffv_7LIp+b@5uFBqsO zg339pMrp+@f%Q$h7imS%qjnFEM80)ZiHjE`O3bSXR$K{E>kXiFy_ttEP;LX`Sdg!E zsxC+Wj_P>9V?yNE*5hO0Yk93xT83K^T!hfFLv$ z5fT(2{g+{BUYC7>4532ZmejA>FYluAA~XKJY7`;_@_W_ih{*xzjjP|zsd$AVL2P*o z_1GO$+K%+H>J@7jcH03iWGQVC2?S?d8a`0lZv4xU7S|yO28%j3)1q({nXWkMI#1Zf z!=*50U(8*SXd!eu!mTOa^rkQa;8(x(&GtpAe%-iz?Zozwd_1QsW5KBMLt_#pzHfCJ zHh*2te+($g8zwM0{yoeDWh{DSqkEs0!uEUm@nvcH$wWTcAYV=A_2g9m+MCPQrt^+H z8WcqT^TYrD=EFteSq1#dq75^(_dH}L+x6m>hY;w-{&{n3+n+s(d|JdBXj3^Tf#Z%{ zzV-Kd_us;(QFrN&0aVaZ>s3B*5V`)FZSxPE^f&XVnGEJFqMJjJ7!ZXh@wM$FgZ=vN zLnG;Krnq%AdQA;_H&#G?*)Rv4KN6UFJoU1YFlor43Nv+=6sN&~6l?kS zkzl_CN>EshS%TqYnGX>jnf^GsNzqJ(;a|E(MIaH)d=uVedEnY^!*o{><$1o^4?>7cR2!BsbdtYii&)yKrWh0Cku3hz&~W+M zsmq+ijs1=4^!MH^RXIIg8?gUsVwePlS()srdQiewyBU)dyP_Eby={ay#Ya{5gn=}d zr@5jeN?7uvgtFKeOKa*c>#z!7{oOP82<9k#xOpCnFJbb)jw4pR={5BZD59kG0~MX@ ztG-$6{&w0>S}nZtj zz?TmiKYv-5tb!`CST{@B;^AWa<9lE9&=*XqzIc1MaS=E7F}z3RG&lH-Vx zo$}uNtO2a)nF->(Fi*U|k5YuY<|T*5IF;yH@bcC4yYp}g{n0BCfplCu-$(DeCJ{X9 zZk>bmR3Af@aBnH_C3IlAZwjM**2oBOK23p5bzgMUQ*SNe9UpLYQU_+{fKdKzvg_+C zrDmn>74jQfs9IUJH&#Qrjl z;j-_c!j`zJH4zwjDY`S&r1`rk|dcIHa^jN2}9Z zeO*>sA|ZPHTn6k6?(cF>qk<9C1~l3g*&5L2p#ss`(`aFYUzpRD2|9|%cB7kzStA(U zM9O1OU{m1|fGnNZeq<@sz&0nZ?4c>o;9=hDD3P!Eb@GHPa^-Y#^4GU-!Og=|-`}hA zeDZGSawgAHVZ+mEd5<08ZI}rz>~BveaeK7fG07Mt599qpV%WaC_2p@g_?40E~=ZVV?qQ)Q#6Fe#2YNQxkJ8j0!j`U0Nyr_ zIx6EQAbOeLxnVO@Dqy9E947E^h}uAjHk>Jm^ziCsz6c9?5AE9*9Putgja#U#?hSWf2mp zFcsaDj+weB)yYOl#}bgio%<1DvC^=dRkkpF3?iN;iEwfD%PF z>J#wx<=LLxt|SpX{N3dfeK?9YOGD_B%-kH8k8ACp4~=(FXi>coHPjOl{@fQ%`Mx*i z4UUBF@JnZ$S5R2~ud&o~*ZQ&Z)QQqDU8QucBqxCflm){eX=?|2d!E;Ox2KN`guIFt z3!bdxbxKnXEk{urfgi~p9;agM)A1Tx3i5GoIS98|*nIivLUNv|#7o1nMEk0`|FBWQ zZuDaO`aF-<#F)q0V*bp%sl;-;U3d`Y(yj~U^j#Cm8XC0r;YBG1O?LBAy^)jNKC6ZV zp06e7>`B{9gZVOzOA87rx$=G{Xhfsoc|QCc8_=tjMYS-itnW)*!Y-kpY}6lbe<0{_ zz|~ZiTjUd3lC-il`2uRE?$~pleY&<@app4tFLJBf^p$`mWG=tU+NvjyATKHbzdzd* z5;`(ECw^ZpP@%-#p!eZLME!l1y<3gpgd}O~X*v4NUATKW9!>G_6SMYiwR2ucfkJxH z*2>|cg)b60Ri|Ii+Rv(R9XE_Axb*Kf3-0(*_?tSC>d(p*o4|kgF!c>-Ot|ao75}gH z&N?WLbzS!)Bxr!(F2UWMAz1JLfdqF6VQ`1w3GNOHCqV}H!QI_0gAeWuI>FYRtiATB zZRgajy7$z%b!-1K-97YF&-66Y-}}7J^ZVT24ZRW~M?aSz?Llvf3NXQQI#FXRh;U6t zS=JOD0#oX{BWaftT0#0Z<@p|7a>w9mubEBJ!}Qo- zz=v}cQ;@zMJnG=O{)WnxS3F6b5>|yg_V#0ZRTIvnGaKnPRX<@7hs6q~)?60ISG4Y~ zVsBOCpi)#g&AUpeK~ybG=vnhaL5rHotR&H{Ma$R$qEu z7fh$##Od!AlqORe^dvcqt zGAk?|cB-qiu`f8;r_VYr@hZL2L*yn0%C);wAg_~)fui__GgiRzwetQtyWI1|WQ7eE zT;8{Ly7kGLMj6$C2A8~|o*>br<+dCl);jys`N!)Ko0SIFBUh+rL?Jf+-dvEOJoaZJ zcf$m=R9!JUi{x@&`v>zLuVYa7y?CK#Oc%YfoyIiVV1j1P_rY%grrCMI0vl$`%9wht zpIQw&Dme$HH=MZpCqo#?RhVuL9a49!<{AHT^YzHZm|r{R>p}>n2sYg>rIdwyHUtp_ z{a0;N7SEh+y-$(ka&}7kL65z2x$_+NDVWVxGQnDdBJUB3993q7lRIIBB|L8%tTmymAOvND=A#C=$1{znbV(CL4HI_uuo6>>8s?)8HFUqw zY5>>z$~_(kHGQ35H3c{h)C)+qn|jE$=hkq*xq+~Lr}DP zwTEQNS$_+%gy!m`KvHLP^<+*-`r`q;iccn0BgO$nWOZ|wE$~)Fs5)rRt82k^jQltZ zfilu*;g zefRYww;YP%F6(A>B2%XtiV8@r5PV%m+cX1?<`_&9LIbnKJBg60k_bOhu0fp~Dbq8VDLKd;;A_qEf_@i%SO zEAu!pw5k=>J>yri+mil5s`HBUnNNUug?{p)zBEfa>b?--mdhDj3-UuKVqWr`4F%(Spsgn63Ugq!& z*M9`}QO%#wMsF68@o~eq_ZuUNLW92S zBP-dYaP}lQRUE3Smg!%^vb{GgUOb#%rJMJWC<9(!EDjU_HTo0U$`&tPInj#7DHUs= ze2Drg@=dAR$^{WIYq+O1qCV3sG1Le8k+oL0)hKNL9DxkdM~QKZHE@qmftcb{h$&+V zPf(icvsXAj)_>l#!0(n!;O!xwjgvINmZCXFk=nzos@}~;hf{usb9Sp>KH_z}wDF?s zbtxZDEG5@1w|_C<5g&|D5UYAQsuSQO+$M{ zYkpSRh469%wKk#XC0RsrrFB9qufFk(25?D!cer-)u#m0YlE;{%!9FnZAt;*Ptf2K{`s2<_YQT(;O9 zBPkjKF_%;(59u2Mg{Hi&xeju$+G!8eS4rx`v4?kdd+Bo2cx#R{ZVK^RRx6!lL{FV%MLU28QipdHg3Cs)vuLsCH+8P{ORB zILP8Y?0`wv*NejhUgO>t0^88Ba2!yB48y)+@Fw@XL?S_+O|c2g{F%QL%f-c2YtY)T zV|;$$db_#@OOcNWqA*G2%Mr~1r}8E$aT$NK(Yw{H?3{_*xaqYdGq=7)2`^Iw$rMSR zTT`(&C!c6tX@0_sH$&mhWi6b0=Sdhju)ZL~zD<5E;hwIw1zBtLb@2T$MNv!flTty> zr}c2Pm}wLQGrsXn0GBlrUgm`45b!_n-pI_-RL{FEl?$p+u_3~E#LK^xms7eYNv2?? zECplVEk5ZwOfUXz9i$;Zvusf?3IUPV=NPZrZIwmsZR;kpYUF9nL`DW@>FUZ4v09%% z7*7`b&PL8Upw*!&He!)B95QM%;|aG}9T67#87<;{DIzW)0x|TTx|#+q7Z&M7J37x< zMDC^>GLmOhSnS;HMh@p}D8sYW(;$FoIj2~*gp!lZX0;o=r97i^Up2F{mG*C+au*@i zRkB!ft!xD0gj=bSb|lp8@tRx0{kkEF6Got2n?|LwEU_OgN2%)>%9FQcyv1bP!G_cI zC;I-Me{|%$SE>>G<9Gi*cj^8z?)*_xBX6(z|0VJR7F6^`i9^9cBH>3enS2r``Ty){ zcG45QrAIkWiNkK=2U5z{fpS-`g8$6cBTb@chsxgytRX*2oOE2;yhEu(u3$#mgalxV z7a>9ac>J}&jMSNnj6l$1AaVcm>R)#K*MIw)XMgQRLPtk{cOwazic>) zLIZG8A^&`YKi+Wr@@TO1f; z3&_)0a@I$=bZlE^U#n)-KqB9%*m9s9m4Ly+#D4H%@ihR*ch55Y$UO92?Gx5co=u^V zu90f>5NLz}vZTOZ-g&;5^127C&6$6}W^h<{ieQ-HTp6O=^ocq|yDDdqt6D0Lz)v^1 z^^>img-LiJw33yU0|LXIgJnz~*q#eGi1P+e_A zjbQKI>xZTG=Y$%eUlYtXQk`S=)Xx$UwMdzi-5)oaWenvCxFkov61V9W6;Cbz zFX<@r--Jb^vhq%5=Cq?SczqcY<1wUjP@QFW(`Odo;5{dAQBKk|X$+Bs4F_59R;>pf zu)L`LtA6vV77L|B05)?Hp*Ua6VA60_HR8R)O2Mc5A?G~Ksw<1<7cF9bw&o!IqwZaC zs6=!&`qaHl0sQ^j`O7hVo!0r|OPdUG8~Et8<-4EplX!lHjdaw#Ea%lO#QE@%vlLQ$ zlT@f$NQyE&kn`n%;|_z?q9W;Fj|sIj(7CS~*)frJ zb)5$8%cwjBX4L)F*6~->U%D$x(Djs1ka2vuk4IUPiJWVydjwgw8^{JK|xn&mJfE)X<+ZS7yQqC(mk>}%rw!X_;Ow2A= zVEB})>w`0;%*IJAarh_Nq>W9?(8nrKN1pry5slMC^DGw|3HE8{7OF+;{T^ z_HDjyMY-ojlnT6Y*jF=a%a|?_WD6^+u2H5QJ{Y3SJd>yS5}~34TrS?M4A)*IT{r?T zZRDUB!E+4T>M}HJ#Js~09p!jJt@y3DO@WlFufSyIM$6jqA8VQf9gqnzcjS zmf!$m@hE9c@DHNw2ENaj*P-Th!imm5t(ASEoTBi4+H;!EI8@Tk990OQ&y8wL0mkX1 zk2K{JFhrP;b4iPt*L_G~&Nsb&3^iv9VSwi)aBI6yDv8?DWan1-LV{B@sCcxLlY@Z8 zAvsF&3MqnR*GU7&fy(+?lowa@BaO}Dvnkh+4le0n3q$q#hxD^>Jr<&u*b0iclMT|t zi{s4JgZM4t&ooHt{?b`Rn06*nh^jYZQTE9CQbVsg2==u^QwqM=0G-_9#{~7Qk2Rc~ zm$5|v82bf*z1o4LN?3jN({{kpyOgrc%HK@6=jf!t3jG>C1QUG)JG8%FAksx)Ya{^5 zv&ZQxPH?p7u5N9JNUHpuEzpIv-&ok7AkbehLq_c4JGLSri||lN1_@Yr@^BZ|?~uKFM)v_!70-UOADJ2#fm7x6Ycc zv~c+R7~PW~0g#sfvuR+@SF1rfR?VD6{ByJU?NLk1J0upmgm8+VU6Mm0ddHQ?W>&)l zKgl!m#%#n2+!6X~tQc07DVuaTP(|)#Dwn`q)-(`Q-%!KZ(Q8O+=id#{ikUoc_hV^j zYpU<4Z`2OsXwGwr3R&r>-n9F8MHXM6RiNfJ0~D~cKfTfGUxT<77zML(r3-vW2bSsy z-rcZSOOQMwLRQ|!Fn%ho>B?h(0H#V2rdZ>)XLCR!)=gT-)C9+XUh`);Ud`gEWWmhq zW-r8)7NnXJ+%J3PDlw`P3M-BlMozuBcqi^T974IRytKnA?}2$gbZnF}SSlRMqg17O zo{Lo}B?f+VwDzy%i7DHc%W#g_XFRfbs7@_;SIJuaF6(GHp~Kr|D$CZsLZ}qw*;6!; z!3s(>McvYGvwykX2%aP}-A5CxU2O>c61pV?yr+>6IiP>tQ>2LPKSe_@OHf0~0Jyn> z^Yvc!#r6Uj+g3Mvi@k5l!PH_Stxf|C&rHWX$37Tl_0D`s^{ia)=v`8w>suwA$x|cw zVWT%64YgvJrLPC;R^&Cu9#<)a5lYuN%Kb!>T3+UJ1S*OTIsvV8=G)2cWnfwbm7X_` zFUfsbwPyhmE~p{)T;+=gHXud%1k(JdI;Dx7l0u!>Wk%?ePJ`ijncB9+yNS>a+)6Nl zb{DSoh@#Av3Ug1aklm>EN6o&zuCH`p50QN>nRdUjYLPR@;WE|EZso_=?vDmf z?a{-X=k(#LV9av@<->Z|&jjiwB~qrjRStJidbr1@`7$kOr`rY?7SFHYPB1*f*A6d@ z;rLqM`FvPNak<{>@Cx06>nyBZbTZMOOXa&So+#oD4yea#kJi6wT)xf;PX83{>JSQ{ zO5G&46J6770AqR(<>1NM$2MlN=AvPvjZYH0JN2_tZI{QC{4H}uZh|BiCj*gp*@a$% zVR&q5bu2L%z)f#)YnF0*S2#k2ID)T8cuob~y-k&pL1ka0F~Jioo)WNA0M^SE-1ER= z5e{KAuE1@$i~wCm-^4g<)LA~u={oj* zYaF8DyOF`4*waq4Ai$y0Al=WlCE_z@G&n|Cn#&xTJja^r)T>0(D@g*Bfe?Tu-=rV+Ud9_PYa9E4*1SoS4wp83(tm%Ba)Nl#V^ zV7j@*EGwp+(9840W^XK+HHn!c(=?!D5U#|*?Ps8%z;<#QP>=Bo0n%1GZ^u;Ll|!&HEpp!U|(IB{24ybE2WKJr`C&@e@VT zseQdrD@Gtab5wq+_MRlGq^()x3d(2!PIoL3qW6q;kGg*Kb#+&B>R!3vP&7B<9c?V} z??}KVW}WCRp?0LLbrbi(oK`j~kMQ-<6}DcXcJ2n4aRiv@W4g|zV&&!?J|9arYZCeA z4Mp1*7aCcYEES+MxLA)dQLC&QR9w5iopAPE06KxYKl4MX67x{3)DG{(;|^q=d55dt zqb}&_39rHv$-)I`4F~6&9xgI(4ZchiNSXcF5**^|q}&$|@+p9s-#u@C1s_mrgM9?|RfhK^ zw^m6(#V`qLt;}&-wP`(9H8p7l%U?3FFQfEOH;rg&2j&UCpQnH{Dqa|_t<vwy99A z`~gaey!IKOZ9xYN-lw2{sSBY9%sdSIrpNcq$lB@J$;oLu<@O+5tG2mAzf$H!525r2 zn6R}oNWz9e;I(IAJ0(>^tL^dh{Dq*K8WG%VdgoNH3Z@;xwcP-Z0w`jAw@E3wAz~ad zVK18i>wh*6q1o_D+XaPG(iac&M!0?^-%3v0ah_xN;jrVT)xVJ^q(x}TSWPv>=~+4u zFR$GGKy@unzM0aH4^&z2AQkigf5%H5^wm{wf*^pi;%{$;w|@&kX7VGkz`s;45QfCk=eMQD z@&%QaQW56a9Q>PnpZ9a}UaVxm_8LkFjY*B-!hJ>P+^Th-I$ zrm)BGf`{*Gy$BPDcL%QC@)%GsH;mTI6t_?r#ku+`K>{)rI9WE_B@?8iQCnamrzn6m z-(WxTX7$#}^?f#e0&cWt{{i?^xJ9JE@~16$rD!k5IW(l=p3UX^ffgAkivNxr?nCOa zk)d1Jst!`LomPq{i5sy0(i-=U8%V;t`$Uo58uqfBwBNB1;zlQ!#N^F!vgEa-%uu;( z9#R~dOgdAn$-=5pm{}rKt}(@28SHA6c*F*)vv)_x`SVfA3RaW>rQj;&_PkcxEHks!$c{sl} z)NVOxvJ|E}c(C>LE1rN2TYUM>ruYYap6BZAEx?R^=mRJ9W%#wt_I2dGa5G|je@jT` zK9%W8$+qc&Dq?n^^t~=K!%N@87u>Mw`>0Lk)TI&4E|1eBVs54z)d%_r>4;q-tu#8dv5x<@VA~E zFAto!*6BtxDdAJa{2L_6&x3`?MSo%#VO@Sc;N@2oh0ec6U{+1HcPb#$!zA^Ko}zai%a%QnUU)-f8s`!? zQwgTzXKj^yksN;3-`?UN@~hlJ{CwbH%eQje&R`%|xrqrqI)$t3sA zww-d)J~pTvpj`C2*oLFmWyJBEwueOfJ%wcVc0NPcavoJ)gnmd_Q-zN{tRlA9+URA% zlH6;$*&Nx|Loehids>*wz5socpwgdg8y0!x5;6{Y4* z(4x(zsu|4ilhmWsXRJYPOmQGmN*t)%31U*gY>L^(S8yc-1jQM_*X)@$;)OB&XcfST zpgjFJT?Vb;UFL}z);UcOI)?&LmJ>Wl3a=&w-spu!fseg=sVHk<04+XiBhvX+#k^HT z%b1jgcCCbSwjhq=X9^`ljd5K~ltDp1Ji7b@;L%V@vK~3O&nm%W`Mt;nCACIlsCs?6 zg8j$l;4Cv~dK5H5bGp%2<7#*O&IOHz8G0Rk{>1x_uVw)#DYrT>texuozTB*6dJd3b zzY#D8D-95jwWDK)ism%Nso6{>9(1)S5iQyMhx=<>^zu}40&BsK4-R?@kH!kgaWgO4 z!-DGjV=c=#d^fZU&u5KodB>CNmxR=#8S2dnsf9PqL5ii0x;;^ZrdiN%> z2eKCXDrVyC*Hwj+V-2Q8g_}_eS~*j4VwDJjs@*_oMU3qSe5hLgn4dAm5K8%mn5WOj zl7nWIM$r%B*H5Pk*+d?0PIVKAG;(O3f0HkEp~0%j4{dh;{vH(!rm4h zo2GusG4&-tqD_UeV4Qpu5f5Z0pl8dDU-u{Uy!Sl5C*O=LC%QC*dr^8#+lfvq``7ZR zYy)0U$zLEbINsxrOF|QsdgSwG5kDS(=X^s(9qhsbJi(G;^cD(O^^7=11b>e%&eNUbA}}jBO)|im7ALhtkw0@8E*u^oM_K?^n6z z;E(Pc1kU+r`dFRu_3L1@Hv@C=aItPtyPGeqy2WeOUIRg|DXjIP+Y1VpR6f&daArK^ z$~>CJr+>Lz^J!$zE)+oAC%Do@W{g>B--@##{;7A$Q>~AwM{mB0>1-#|?pbPTik2Lq zF@OJYGkyHr7Mj{1JteQChPFx2LfK_Uq(4C&7Z$u`LA!P`G?-H$%(XO)zBXwEJlt&& zul{8P&p9`-VQesOLl1kGD6d!ariVJ%NNCRIWBC|ELpXnys4&r?g;4lI;p9V!StBqF zs!8IkUEIYapvPp&w=A*2Ejr%fyT0fng5X^_*S=|P+4r`c`?{`3ksr5qwB;;onVb^X zb_oD=<9d2`wlgdMoHq2w%#2as@={G;7d;n8>Ori0Xc4(9XW zY;v8k`7thImfU|{1Fu6nsDIgnuOf|Q8&A!9?_FRvP^{3Xs|Tj8<`=2;k3{-X93@r@ z#41HY>}J}=b#%|_ySXtGe5&ZzwWro=S}ETOi2fF?JKNI1YfucVHM(x&Eb|F5&)h7A z9%yt+4QXu8#E+yuUKk8Pi1Y=s3nlt;h&>N`SFvDMk6EAd7vcWWv+Gk9wJGSYmw52> zYsYpSp7J$oLNc%=hX4`#!&QxX!s#!8&55dt<#bqk1=Z++K~4xo&;4 z%;9U`SQ9vEn9|prP1KpY*X0T)TI)_Pj|uF6dha*LiHXn?r_D@D(f5qMTj^2{a14zG zITy&|U|?%Px9=j$wX*MwPFwPh9+Y~udPi_=`97S6Ik~H?-r%d;L9T6-_rc)HiLh0A z7*V`XC_rRG*VYcqg>P+VmfBFwKMA3gp`R8?DQj6SlhyQil9-^1<=IFf&RSA#EBg~z z`a@s8E~R(&{8Cwkes1zf9~Fz zUZ1+U;4VL^F$(jPuv6qe_)y8bBB!Az%>gDqIR+nrTPCLxp{U{5r5lJszeBpQzHN%# zN8_SvOWEeSw?2eXQHzNo4;#fjt4|S-X<4m9#skvF3QcfI%uj4~Z}HGRm~Rs}a8>55 zIGF5(vVfUcZ|%m06PwjG+SA3rH7o``D)5GKPwHL`!_I5k!)_1Jv5KN}tg!^(#do&f zaJLd~mhxO`Og@w{DgZF1MJ%7ju%?H$0gD=&`kFW@zfVuN-jXT{jUKKa3Y{P-D2=V8 z&wAS1+J09vHx@ZrW!8trctCn{GFa2?aT3oAN@<9XBZ}I+%a6~o{<$nGJXJ2Lp2`~u z6j%aXRbS~S)l^Cof>2TEv$78kKkYZjsMZMm?>1ZihAc>0=IJlD@Yo6Ii&)O$ycSoQ zVec7kisDv$t-%*PP$4glV=9JbXe>D`uv2AcG{mWz=1r9cY+C%R&2xfI1CetiZ4{w+ zl-!P=CmUmQKPsE+ zblDitMk9n0Wf=m5lI{fb*h`0my4qv*cM%Yn$(YltyA$nc&ibL=v(LF6b1Af*Wg>=c zb)vorGHw7_4#gc5&t?92s=e(mBK$5qI`nY!=L@}U!~;SJiyW!Jbw6zR*)Y8&ILaZK zn(?bDz1$cX>e2y16uW@ecI;x-ZhD1Z@@=%q?B+q1wIg{e56wf7H9z@|U9q{HvMPEq zV>1erCP}sXjBw7@qA&ZV0cwRD+jTAsqdM`>1k%)#A&Rg!@l`|Q$zQs}qxr8;i*rDT z>?2XKdEq|9KV%~Wi>1P7PD@vaZdq{E0;`lN z$dQdjQgQNDqSLCM#>?mLN=C)feIU=9v#JM7AAMPs{xa&$^cd&>wIMlaBeE!DhMr;Y z3V+OgH#)!cA}2S|{)S;G;-@r^I*Hq)CQY_3*-0neJ+I(QXU#ac1JFhv1`KOQL^{J- z`gbI&-{c)!RrPeBYukA|^wpZ=HHs)PmTcsLub-ZU{MIb`!>YO$p=UdJ7e2xU8`2%2 z+N9=Lt2S5rjqBKbi#p%e&>yMA%j(rOilTTS2Sl9NK8;omA1~|^#hMjqUU&!2Ak)TJ zijg~cy2u9VtKs&ThmePl&p1!hQ<(uVX7PCU;J6<|6JBIfMVx zy@&~KC;Eki!j)+Dqet`jYRM6EBQu4Gf=^cA{EI&{@n@BG~< zIwN0G!7>ul_c&}6moI@C`Y|h5i22>9d;HKspi4a|3-9Ee59z;q-$jjgvaE87wMGMJhLpIgGVRcSRZ7nDPMH<{Mi)g4-rM_>NYn{wv9_k)d1o8{<)M*6t zIhS!SSD*=>pz&9Ja>|SiY{$MAJA2+MWQ03;!v5kVxD|op02(S|$gOCaCA=rO8ecP@ z0yY_FRZq!p91~Ic8578wM3#(Mrr;So?F2Uuj^mT|3-M9E&vXTiUYpvG3DEqhhmdyN zi=6f`CTe-(_;##QX>Uq=U0CIVvA5Hp^(~lbwn3>0HeuOY|B06v1D9%u9 zR=aj_yWd^&L^U6drrbf!?1j#)ewO*kvimU|@+Ns%tzT(3Yk=Pr*zCK0vROlNqb9Ik zAe(Q3;$RyZ8hy5NiN#T)a1k{(Z?*Bl&5}eCc^--k(5iD;oGdJs#;a*-yDGR*JU3+e z9qEOsaR?})mF9X)gkDog)*k{jQYE_B zE`TKuP~iSn2YvxOa-C9spjkFM&dpa8?Kta`N8?O>+Wl4kkg4Zx_`2zZNeI(UzgJ*i z>gGI3Y03Ai8AXP?)tkr;6*A>FUb@+a?|DFE2K#zrs~iXQPIccGN<0=$Hxt*fLD<1U zA;&911C%l?mS3E^w!AW-uemi zt3!E%u~@Uw#G#t6M*JK$+Ncm=3NCM;>&We=t~I^~NcCFMta<=DDHIc{W}0I9{{Q z$eQx1zR+EpamJj_Xw|*QdyE1yw^u+WVlTV9%A?Y`8}n^)TDG+xHyX42D`E;wu-75; zw{P+E^a!Uo=ifBAqy!9e^|Z?0MfG{^YreQ9I2f*^ujDXpqr6-CQJ0gh%~*-0S}y!P zSpkBn=B)1){ZPK_lhIIo@JKaN;TnxMq1=)^59FZL@qj=c(kV;3gCbpQpGa2-QRM`j zmCkBfi}c?fmbP?M8aGiZhve_6M+?~z)@d0tcsR69m8pFFqu~3`kV?NOF$nw9EAuj- zpo+JHN0HQvueaOvVkYZ@3KG$Rik}|w#E~DrUU%HA&>$%0mpHeW5X8(#t_Z-ie6Ihb z(Zb{1FVgZ~_xZ&x-=n@HMg$n!_mB{LzF0{_Os}o-;pP{&+za*L`LX|LGlE%8Hz~2l zW%E0d@2}~d(5b%sjwI!6e0TDTl>YBy{QF$}4_;R!b%@!+l8}IU!7<;UI;;H$BJ*OT zG6c54j0$HsTmG!RC^6}OC~&`kBS@3TK6Ug7f$2zq#@~?|5sJ{=exwOgfiNs4_qKC1?HVu=q!V|34@_f3N%eU)lPT7ymzS;9p75Um=G7{?GXL JNBI56{{pP?lrsPT literal 33691 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 diff --git a/docs/how-to-guides/data-basics/media/list-of-pages/fetch-the-data.jpg b/docs/how-to-guides/data-basics/media/list-of-pages/fetch-the-data.jpg index 58595b9d21219ee645441a17aeae72014d2dd77a..c87c994479acbb5b86f71f4a515667589d524874 100644 GIT binary patch literal 6686 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 V=TwRN|KUpL-*1Y3;}c{2zW@*DPe=d& literal 6027 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
6t`5 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 literal 4052 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 From 2cfc6560242b974d34159562631aa177650216ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Zieli=C5=84ski?= Date: Mon, 31 Jan 2022 16:27:24 +0100 Subject: [PATCH 13/51] Add the full example to the repository --- docs/how-to-guides/data-basics/1-setup.md | 7 +- .../data-basics/2-building-a-list-of-pages.md | 7 +- .../list-of-pages/first-gutenberg-app/app.js | 72 +++++++++++++++++++ .../first-gutenberg-app.php | 63 ++++++++++++++++ .../first-gutenberg-app/style.css | 17 +++++ .../media/setup/first-gutenberg-app/app.js | 18 +++++ .../first-gutenberg-app.php | 63 ++++++++++++++++ .../media/setup/first-gutenberg-app/style.css | 17 +++++ 8 files changed, 260 insertions(+), 4 deletions(-) create mode 100644 docs/how-to-guides/data-basics/media/list-of-pages/first-gutenberg-app/app.js create mode 100644 docs/how-to-guides/data-basics/media/list-of-pages/first-gutenberg-app/first-gutenberg-app.php create mode 100644 docs/how-to-guides/data-basics/media/list-of-pages/first-gutenberg-app/style.css create mode 100644 docs/how-to-guides/data-basics/media/setup/first-gutenberg-app/app.js create mode 100644 docs/how-to-guides/data-basics/media/setup/first-gutenberg-app/first-gutenberg-app.php create mode 100644 docs/how-to-guides/data-basics/media/setup/first-gutenberg-app/style.css diff --git a/docs/how-to-guides/data-basics/1-setup.md b/docs/how-to-guides/data-basics/1-setup.md index 2416dd7a438ef2..5c98736e4c6b6c 100644 --- a/docs/how-to-guides/data-basics/1-setup.md +++ b/docs/how-to-guides/data-basics/1-setup.md @@ -144,5 +144,8 @@ function MyFirstApp() { You can safely ignore the JSX snippets and rely on their compiled versions – they will just work even when pasted to your browser's developer tools. -Previous part: [Introduction](./README.md) -Next part: [Building a basic list of pages](./2-building-a-list-of-pages.md) +## What's next? + +* Review the [full example](./media/setup/first-gutenberg-app). +* Previous part: [Introduction](./README.md) +* Next part: [Building a basic list of pages](./2-building-a-list-of-pages.md) diff --git a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md index dce504b82b82a7..d1d2fe28fb1f45 100644 --- a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md +++ b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md @@ -601,5 +601,8 @@ All that’s left is to refresh the page and enjoy the brand new status indicato ![](./media/list-of-pages/indicator.jpg) ![](./media/list-of-pages/no-results.jpg) -Previous part: [Setup](./1-setup.md) -Next part: Adding an „Edit page” feature (coming soon) +## What's next? + +* Review the [full example](./media/list-of-pages/first-gutenberg-app) +* **Previous part:** [Setup](./1-setup.md) +* **Next part:** Adding an „Edit page” feature (coming soon) diff --git a/docs/how-to-guides/data-basics/media/list-of-pages/first-gutenberg-app/app.js b/docs/how-to-guides/data-basics/media/list-of-pages/first-gutenberg-app/app.js new file mode 100644 index 00000000000000..0011d937434e73 --- /dev/null +++ b/docs/how-to-guides/data-basics/media/list-of-pages/first-gutenberg-app/app.js @@ -0,0 +1,72 @@ +const { SearchControl, Spinner } = window.wp.components; + +function MyFirstApp() { + const [ searchTerm, setSearchTerm ] = window.wp.element.useState( '' ); + const { pages, hasResolved } = window.wp.data.useSelect( + ( select ) => { + const query = {}; + if ( searchTerm ) { + query.search = searchTerm; + } + return { + pages: select( window.wp.coreData.store ).getEntityRecords( + 'postType', + 'page', + query + ), + hasResolved: select( + window.wp.coreData.store + ).hasFinishedResolution( 'getEntityRecords', [ + 'postType', + 'page', + query, + ] ), + }; + }, + [ searchTerm ] + ); + + return ( +
+ + +
+ ); +} + +function PagesList( { hasResolved, pages } ) { + if ( ! hasResolved ) { + return ; + } + if ( ! pages?.length ) { + return
No results
; + } + + return ( + + + + + + + + { pages?.map( ( page ) => ( + + + + ) ) } + +
Title
{ page.title.rendered }
+ ); +} + +window.addEventListener( + 'load', + function () { + window.wp.element.render( + window.wp.element.createElement( MyFirstApp ), + document.querySelector( '#my-first-gutenberg-app' ) + ); + }, + false +); diff --git a/docs/how-to-guides/data-basics/media/list-of-pages/first-gutenberg-app/first-gutenberg-app.php b/docs/how-to-guides/data-basics/media/list-of-pages/first-gutenberg-app/first-gutenberg-app.php new file mode 100644 index 00000000000000..1c46bf9c8cd619 --- /dev/null +++ b/docs/how-to-guides/data-basics/media/list-of-pages/first-gutenberg-app/first-gutenberg-app.php @@ -0,0 +1,63 @@ +Pages +
+ '; + }, + 'dashicons-schedule', + 3 + ); +} + +add_action( 'admin_menu', 'my_admin_menu' ); + +function load_custom_wp_admin_scripts( $hook ) { + // Load only on ?page=my-first-gutenberg-app + if ( $hook !== 'toplevel_page_my-first-gutenberg-app' ) { + return; + } + + // Load the required WordPress packages: + + // wp-components is a library of generic WordPress components + // used for building consistent user interfaces across the board. + wp_enqueue_style( 'wp-components' ); + wp_enqueue_script( 'wp-components' ); + + // wp-data provides data management backbone such as the Redux + // implementation or data resolution mechanisms. + wp_enqueue_script( 'wp-data' ); + + // wp-core-data is a glue between WordPress Core and wp-data. + // It provides a Redux store with a number of selectors and actions to + // power common tasks such as loading the data from the WordPress REST API, + // editing it in the browser, and persisting the changes back to the REST API. + wp_enqueue_script( 'wp-core-data' ); + + // Load our app.js + wp_register_script( + 'my-first-gutenberg-app', + plugins_url( 'my-first-gutenberg-app/app.js' ), + array( 'wp-components', 'wp-data', 'wp-core-data' ), + ); + wp_enqueue_script( 'my-first-gutenberg-app' ); + + // Load our style.css + wp_register_style( 'my-first-gutenberg-app', plugins_url( 'my-first-gutenberg-app/style.css' ) ); + wp_enqueue_style( 'my-first-gutenberg-app' ); +} + +add_action( 'admin_enqueue_scripts', 'load_custom_wp_admin_scripts' ); diff --git a/docs/how-to-guides/data-basics/media/list-of-pages/first-gutenberg-app/style.css b/docs/how-to-guides/data-basics/media/list-of-pages/first-gutenberg-app/style.css new file mode 100644 index 00000000000000..25e32e0fa121dc --- /dev/null +++ b/docs/how-to-guides/data-basics/media/list-of-pages/first-gutenberg-app/style.css @@ -0,0 +1,17 @@ +.toplevel_page_my-first-gutenberg-app #wpcontent { + background: #FFF; +} +#my-first-gutenberg-app { + max-width: 500px; +} +#my-first-gutenberg-app ul, +#my-first-gutenberg-app ul li { + list-style-type: disc; +} +#my-first-gutenberg-app ul { + padding-left: 20px; +} +#my-first-gutenberg-app .components-search-control__input { + height: 36px; + margin-left: 0; +} diff --git a/docs/how-to-guides/data-basics/media/setup/first-gutenberg-app/app.js b/docs/how-to-guides/data-basics/media/setup/first-gutenberg-app/app.js new file mode 100644 index 00000000000000..2e4ad4c1fde8e5 --- /dev/null +++ b/docs/how-to-guides/data-basics/media/setup/first-gutenberg-app/app.js @@ -0,0 +1,18 @@ +function MyFirstApp() { + return window.wp.element.createElement( + 'span', + {}, + 'Hello from JavaScript!' + ); +} + +window.addEventListener( + 'load', + function () { + window.wp.element.render( + window.wp.element.createElement( MyFirstApp ), + document.querySelector( '#my-first-gutenberg-app' ) + ); + }, + false +); diff --git a/docs/how-to-guides/data-basics/media/setup/first-gutenberg-app/first-gutenberg-app.php b/docs/how-to-guides/data-basics/media/setup/first-gutenberg-app/first-gutenberg-app.php new file mode 100644 index 00000000000000..1c46bf9c8cd619 --- /dev/null +++ b/docs/how-to-guides/data-basics/media/setup/first-gutenberg-app/first-gutenberg-app.php @@ -0,0 +1,63 @@ +Pages +
+ '; + }, + 'dashicons-schedule', + 3 + ); +} + +add_action( 'admin_menu', 'my_admin_menu' ); + +function load_custom_wp_admin_scripts( $hook ) { + // Load only on ?page=my-first-gutenberg-app + if ( $hook !== 'toplevel_page_my-first-gutenberg-app' ) { + return; + } + + // Load the required WordPress packages: + + // wp-components is a library of generic WordPress components + // used for building consistent user interfaces across the board. + wp_enqueue_style( 'wp-components' ); + wp_enqueue_script( 'wp-components' ); + + // wp-data provides data management backbone such as the Redux + // implementation or data resolution mechanisms. + wp_enqueue_script( 'wp-data' ); + + // wp-core-data is a glue between WordPress Core and wp-data. + // It provides a Redux store with a number of selectors and actions to + // power common tasks such as loading the data from the WordPress REST API, + // editing it in the browser, and persisting the changes back to the REST API. + wp_enqueue_script( 'wp-core-data' ); + + // Load our app.js + wp_register_script( + 'my-first-gutenberg-app', + plugins_url( 'my-first-gutenberg-app/app.js' ), + array( 'wp-components', 'wp-data', 'wp-core-data' ), + ); + wp_enqueue_script( 'my-first-gutenberg-app' ); + + // Load our style.css + wp_register_style( 'my-first-gutenberg-app', plugins_url( 'my-first-gutenberg-app/style.css' ) ); + wp_enqueue_style( 'my-first-gutenberg-app' ); +} + +add_action( 'admin_enqueue_scripts', 'load_custom_wp_admin_scripts' ); diff --git a/docs/how-to-guides/data-basics/media/setup/first-gutenberg-app/style.css b/docs/how-to-guides/data-basics/media/setup/first-gutenberg-app/style.css new file mode 100644 index 00000000000000..25e32e0fa121dc --- /dev/null +++ b/docs/how-to-guides/data-basics/media/setup/first-gutenberg-app/style.css @@ -0,0 +1,17 @@ +.toplevel_page_my-first-gutenberg-app #wpcontent { + background: #FFF; +} +#my-first-gutenberg-app { + max-width: 500px; +} +#my-first-gutenberg-app ul, +#my-first-gutenberg-app ul li { + list-style-type: disc; +} +#my-first-gutenberg-app ul { + padding-left: 20px; +} +#my-first-gutenberg-app .components-search-control__input { + height: 36px; + margin-left: 0; +} From 9856c496ec38f1f5dc7718b270ea004427071e38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Zieli=C5=84ski?= Date: Mon, 31 Jan 2022 16:29:00 +0100 Subject: [PATCH 14/51] Rename full to finished --- docs/how-to-guides/data-basics/1-setup.md | 2 +- docs/how-to-guides/data-basics/2-building-a-list-of-pages.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/how-to-guides/data-basics/1-setup.md b/docs/how-to-guides/data-basics/1-setup.md index 5c98736e4c6b6c..8715da4875423a 100644 --- a/docs/how-to-guides/data-basics/1-setup.md +++ b/docs/how-to-guides/data-basics/1-setup.md @@ -146,6 +146,6 @@ You can safely ignore the JSX snippets and rely on their compiled versions – t ## What's next? -* Review the [full example](./media/setup/first-gutenberg-app). +* Review the [finished example](./media/setup/first-gutenberg-app). * Previous part: [Introduction](./README.md) * Next part: [Building a basic list of pages](./2-building-a-list-of-pages.md) diff --git a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md index d1d2fe28fb1f45..84d42945aae4c4 100644 --- a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md +++ b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md @@ -603,6 +603,6 @@ All that’s left is to refresh the page and enjoy the brand new status indicato ## What's next? -* Review the [full example](./media/list-of-pages/first-gutenberg-app) +* Review the [finished example](./media/list-of-pages/first-gutenberg-app) * **Previous part:** [Setup](./1-setup.md) * **Next part:** Adding an „Edit page” feature (coming soon) From 811252694bf3eab31a7ed2b2c69218993719ea66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Zieli=C5=84ski?= Date: Mon, 31 Jan 2022 17:24:12 +0100 Subject: [PATCH 15/51] Rename first-gutenberg-app to my-first-gutenberg-app --- docs/how-to-guides/data-basics/1-setup.md | 6 +- .../app.js | 0 .../my-first-gutenberg-app.php} | 0 .../style.css | 0 .../media/setup/first-gutenberg-app/app.js | 18 ---- .../media/setup/my-first-gutenberg-app/app.js | 88 +++++++++++++++++++ .../my-first-gutenberg-app.php} | 0 .../style.css | 0 8 files changed, 91 insertions(+), 21 deletions(-) rename docs/how-to-guides/data-basics/media/list-of-pages/{first-gutenberg-app => my-first-gutenberg-app}/app.js (100%) rename docs/how-to-guides/data-basics/media/list-of-pages/{first-gutenberg-app/first-gutenberg-app.php => my-first-gutenberg-app/my-first-gutenberg-app.php} (100%) rename docs/how-to-guides/data-basics/media/list-of-pages/{first-gutenberg-app => my-first-gutenberg-app}/style.css (100%) delete mode 100644 docs/how-to-guides/data-basics/media/setup/first-gutenberg-app/app.js create mode 100644 docs/how-to-guides/data-basics/media/setup/my-first-gutenberg-app/app.js rename docs/how-to-guides/data-basics/media/setup/{first-gutenberg-app/first-gutenberg-app.php => my-first-gutenberg-app/my-first-gutenberg-app.php} (100%) rename docs/how-to-guides/data-basics/media/setup/{first-gutenberg-app => my-first-gutenberg-app}/style.css (100%) diff --git a/docs/how-to-guides/data-basics/1-setup.md b/docs/how-to-guides/data-basics/1-setup.md index 8715da4875423a..44ef7051a6cd68 100644 --- a/docs/how-to-guides/data-basics/1-setup.md +++ b/docs/how-to-guides/data-basics/1-setup.md @@ -4,9 +4,9 @@ We will build the application as a WordPress plugin, which means you need to hav ## Creating a plugin -We'll do all the development inside of a WordPress plugin. Let's start by creating a `wp-content/plugins/first-gutenberg-app` directory in your local WordPress environment. We will need to create three files inside that directory: +We'll do all the development inside of a WordPress plugin. Let's start by creating a `wp-content/plugins/my-first-gutenberg-app` directory in your local WordPress environment. We will need to create three files inside that directory: -* first-gutenberg-app.php – to create a new admin page +* my-first-gutenberg-app.php – to create a new admin page * script.js – for our JavaScript application * style.css – for the minimal stylesheet @@ -47,7 +47,7 @@ window.addEventListener( 'load', function() { } ``` -**first-gutenberg-app.php:** +**my-first-gutenberg-app.php:** ```php { + const query = {}; + if ( searchTerm ) { + query.search = searchTerm; + } + return { + pages: select( window.wp.coreData.store ).getEntityRecords( + 'postType', + 'page', + query + ), + hasResolved: select( + window.wp.coreData.store + ).hasFinishedResolution( 'getEntityRecords', [ + 'postType', + 'page', + query, + ] ), + }; + }, + [ searchTerm ] + ); + + return window.wp.element.createElement( + 'div', + {}, + window.wp.element.createElement( window.wp.components.SearchControl, { + onChange: setSearchTerm, + value: searchTerm, + } ), + window.wp.element.createElement( PagesList, { hasResolved, pages } ) + ); +} + +function PagesList( { hasResolved, pages } ) { + if ( ! hasResolved ) { + return window.wp.element.createElement( window.wp.components.Spinner ); + } + if ( ! pages?.length ) { + return window.wp.element.createElement( 'div', {}, 'No results' ); + } + + return window.wp.element.createElement( + 'table', + { + className: + 'wp-list-table widefat fixed striped table-view-list posts', + }, + window.wp.element.createElement( + 'thead', + {}, + window.wp.element.createElement( + 'tr', + {}, + window.wp.element.createElement( 'td', {}, 'Title' ) + ) + ), + window.wp.element.createElement( + 'tbody', + {}, + pages?.map( ( page ) => + window.wp.element.createElement( + 'tr', + { key: page.id }, + window.wp.element.createElement( + 'td', + {}, + page.title.rendered + ) + ) + ) + ) + ); +} + +window.addEventListener( + 'load', + function () { + window.wp.element.render( + window.wp.element.createElement( MyFirstApp ), + document.querySelector( '#my-first-gutenberg-app' ) + ); + }, + false +); diff --git a/docs/how-to-guides/data-basics/media/setup/first-gutenberg-app/first-gutenberg-app.php b/docs/how-to-guides/data-basics/media/setup/my-first-gutenberg-app/my-first-gutenberg-app.php similarity index 100% rename from docs/how-to-guides/data-basics/media/setup/first-gutenberg-app/first-gutenberg-app.php rename to docs/how-to-guides/data-basics/media/setup/my-first-gutenberg-app/my-first-gutenberg-app.php diff --git a/docs/how-to-guides/data-basics/media/setup/first-gutenberg-app/style.css b/docs/how-to-guides/data-basics/media/setup/my-first-gutenberg-app/style.css similarity index 100% rename from docs/how-to-guides/data-basics/media/setup/first-gutenberg-app/style.css rename to docs/how-to-guides/data-basics/media/setup/my-first-gutenberg-app/style.css From 2942090ab5862acbc3eda2d89127747951d40d8d Mon Sep 17 00:00:00 2001 From: Adam Zielinski Date: Tue, 1 Feb 2022 15:57:17 +0100 Subject: [PATCH 16/51] Update docs/how-to-guides/data-basics/1-setup.md Co-authored-by: George Mamadashvili --- docs/how-to-guides/data-basics/1-setup.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/how-to-guides/data-basics/1-setup.md b/docs/how-to-guides/data-basics/1-setup.md index 44ef7051a6cd68..a6a8293f581923 100644 --- a/docs/how-to-guides/data-basics/1-setup.md +++ b/docs/how-to-guides/data-basics/1-setup.md @@ -122,7 +122,7 @@ Congratulations! You are now ready to start building the app! ## Readability vs Convenience -You don’t need a build tool to complete this tutorial, but using one will make your core look nicer. +You don’t need a build tool to complete this tutorial, but using one will make your code look nicer. The examples in this tutorial use the JSX syntax: From 96d4f417e30b145f1b910647345bc20b65294ba6 Mon Sep 17 00:00:00 2001 From: Adam Zielinski Date: Tue, 1 Feb 2022 15:57:28 +0100 Subject: [PATCH 17/51] Update docs/how-to-guides/data-basics/1-setup.md Co-authored-by: George Mamadashvili --- docs/how-to-guides/data-basics/1-setup.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/how-to-guides/data-basics/1-setup.md b/docs/how-to-guides/data-basics/1-setup.md index a6a8293f581923..79cfb539739e56 100644 --- a/docs/how-to-guides/data-basics/1-setup.md +++ b/docs/how-to-guides/data-basics/1-setup.md @@ -7,7 +7,7 @@ We will build the application as a WordPress plugin, which means you need to hav We'll do all the development inside of a WordPress plugin. Let's start by creating a `wp-content/plugins/my-first-gutenberg-app` directory in your local WordPress environment. We will need to create three files inside that directory: * my-first-gutenberg-app.php – to create a new admin page -* script.js – for our JavaScript application +* app.js – for our JavaScript application * style.css – for the minimal stylesheet Go ahead and create these files using the following snippets: From f7c4ecb0ebf6f80c458688e32b443d230e171c96 Mon Sep 17 00:00:00 2001 From: Adam Zielinski Date: Thu, 3 Feb 2022 14:04:53 +0100 Subject: [PATCH 18/51] Update docs/how-to-guides/data-basics/README.md Co-authored-by: Dave Smith --- docs/how-to-guides/data-basics/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/how-to-guides/data-basics/README.md b/docs/how-to-guides/data-basics/README.md index d9a6fe792aa4a3..b90527d8e8e68b 100644 --- a/docs/how-to-guides/data-basics/README.md +++ b/docs/how-to-guides/data-basics/README.md @@ -1,6 +1,6 @@ # Create your First App with Gutenberg Data -This tutorial aims to get you comfortable with the Gutenberg data layer. It guides you through building a React application that enables the user to manage their WordPress pages. The finished app will look like this: +This tutorial aims to get you comfortable with the Gutenberg data layer. It guides you through building a simple React application that enables the user to manage their WordPress pages. The finished app will look like this: ![](./media/finished-app.jpg) From 9c3569ad1b6a18fc3e4f8b745e45c4fe4c92d041 Mon Sep 17 00:00:00 2001 From: Adam Zielinski Date: Thu, 3 Feb 2022 14:05:07 +0100 Subject: [PATCH 19/51] Update docs/how-to-guides/data-basics/2-building-a-list-of-pages.md Co-authored-by: Dave Smith --- docs/how-to-guides/data-basics/2-building-a-list-of-pages.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md index 84d42945aae4c4..482dd43464626f 100644 --- a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md +++ b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md @@ -462,7 +462,7 @@ the `hasFinishedResolution` selector: `wp.data.select('core').hasFinishedResolution( 'getEntityRecords', [ 'postType', 'page', { search: 'home' } ] )` -It takes the name of the selector and the arguments and returns either `true` if the data was already loaded or `false` +It takes the name of the selector and the _exact same arguments you passed to that selector_ and returns either `true` if the data was already loaded or `false` it we’re still waiting. Let’s add it to `wp.data.useSelect`: ```js From 2b79ae2c8840b71a042e78930dee4ab59ce4086d Mon Sep 17 00:00:00 2001 From: Adam Zielinski Date: Thu, 3 Feb 2022 14:05:15 +0100 Subject: [PATCH 20/51] Update docs/how-to-guides/data-basics/2-building-a-list-of-pages.md Co-authored-by: Dave Smith --- docs/how-to-guides/data-basics/2-building-a-list-of-pages.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md index 482dd43464626f..3f633c78d2de77 100644 --- a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md +++ b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md @@ -391,7 +391,7 @@ issue 10 requests in total even though we could reuse the data. Gutenberg data helps by caching the responses to API requests triggered by `getEntityRecords()` and reuses them on subsequent calls. This is especially important when other components rely on the same entity records. -All in all, the built-in utilities are designed to solve the typical problems so that you can focus on your application +All in all, the utilities built into core-data are designed to solve the typical problems so that you can focus on your application instead. ## Step 5: Loading Indicator From 6655e97f37f43ba81f8e9bde5a0a7d0baabf8542 Mon Sep 17 00:00:00 2001 From: Adam Zielinski Date: Thu, 3 Feb 2022 14:05:21 +0100 Subject: [PATCH 21/51] Update docs/how-to-guides/data-basics/2-building-a-list-of-pages.md Co-authored-by: Dave Smith --- docs/how-to-guides/data-basics/2-building-a-list-of-pages.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md index 3f633c78d2de77..9c58348cb8439c 100644 --- a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md +++ b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md @@ -84,7 +84,7 @@ wp.data.select( 'core' ).getEntityRecords( 'postType', 'page' ) ``` If you run that following snippet in your browser’s dev tools, you will see it returns `null`. Why? The pages are only -requested by `getEntityRecords` resolver after first running the selector. If you wait a moment and re-run it, it +requested by the `getEntityRecords` resolver after first running the _selector_. If you wait a moment and re-run it, it will return the list of all pages. Similarly, the `MyFirstApp` component needs to re-run the selector once the data is available. That’s exactly what From 335d4ea6fc77e12a14ef186541db8513fdae754f Mon Sep 17 00:00:00 2001 From: Adam Zielinski Date: Thu, 3 Feb 2022 14:05:28 +0100 Subject: [PATCH 22/51] Update docs/how-to-guides/data-basics/2-building-a-list-of-pages.md Co-authored-by: Dave Smith --- docs/how-to-guides/data-basics/2-building-a-list-of-pages.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md index 9c58348cb8439c..16f2a84780166d 100644 --- a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md +++ b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md @@ -385,7 +385,7 @@ search=About_ and we’d display the wrong data. Gutenberg data helps by handling the asynchronous part behind the scenes. `useSelect` remembers the most recent call and returns only the data we expect. -Second, every keystroke would trigger an API request. If you typed About, deleted it, and retyped it, it would +Secondly, every keystroke would trigger an API request. If you typed `About`, deleted it, and retyped it, it would issue 10 requests in total even though we could reuse the data. Gutenberg data helps by caching the responses to API requests triggered by `getEntityRecords()` and reuses them on From 9da2b5d2f04b2b73a2069543876e0116a5e517c7 Mon Sep 17 00:00:00 2001 From: Adam Zielinski Date: Thu, 3 Feb 2022 14:05:35 +0100 Subject: [PATCH 23/51] Update docs/how-to-guides/data-basics/2-building-a-list-of-pages.md Co-authored-by: Dave Smith --- docs/how-to-guides/data-basics/2-building-a-list-of-pages.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md index 16f2a84780166d..fb4403ae9bd02a 100644 --- a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md +++ b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md @@ -64,7 +64,7 @@ The hard-coded sample page isn’t very useful. We want to display your actual W list of pages from the WordPress API. Before we start, let’s confirm we actually have some pages to fetch. Navigate to Pages using the sidebar menu and -ensure it shows at least four or five positions: +ensure it shows at least four or five Pages: ![](./media/list-of-pages/pages-list.jpg) From 15d0ae2c43f656a167b4db8f4bb1d48b2999898a Mon Sep 17 00:00:00 2001 From: Adam Zielinski Date: Thu, 3 Feb 2022 14:05:42 +0100 Subject: [PATCH 24/51] Update docs/how-to-guides/data-basics/2-building-a-list-of-pages.md Co-authored-by: Dave Smith --- docs/how-to-guides/data-basics/2-building-a-list-of-pages.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md index fb4403ae9bd02a..1d84cc6bab48da 100644 --- a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md +++ b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md @@ -63,7 +63,7 @@ you should see the following: The hard-coded sample page isn’t very useful. We want to display your actual WordPress pages so let’s fetch the actual list of pages from the WordPress API. -Before we start, let’s confirm we actually have some pages to fetch. Navigate to Pages using the sidebar menu and +Before we start, let’s confirm we actually have some pages to fetch. Within WPAdmin, Navigate to Pages using the sidebar menu and ensure it shows at least four or five Pages: ![](./media/list-of-pages/pages-list.jpg) From 2d615a5203b8e94f8aacc632c1dea0de92590302 Mon Sep 17 00:00:00 2001 From: Adam Zielinski Date: Thu, 3 Feb 2022 14:05:50 +0100 Subject: [PATCH 25/51] Update docs/how-to-guides/data-basics/2-building-a-list-of-pages.md Co-authored-by: Dave Smith --- docs/how-to-guides/data-basics/2-building-a-list-of-pages.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md index 1d84cc6bab48da..cf8c573c04911d 100644 --- a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md +++ b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md @@ -61,7 +61,7 @@ you should see the following: ## Step 2: Fetch the data The hard-coded sample page isn’t very useful. We want to display your actual WordPress pages so let’s fetch the actual -list of pages from the WordPress API. +list of pages from the [WordPress REST API](https://developer.wordpress.org/rest-api/). Before we start, let’s confirm we actually have some pages to fetch. Within WPAdmin, Navigate to Pages using the sidebar menu and ensure it shows at least four or five Pages: From 2df6ec3b06971b8af511e0349c2a6ab0874cfb68 Mon Sep 17 00:00:00 2001 From: Adam Zielinski Date: Thu, 3 Feb 2022 14:05:57 +0100 Subject: [PATCH 26/51] Update docs/how-to-guides/data-basics/1-setup.md Co-authored-by: Dave Smith --- docs/how-to-guides/data-basics/1-setup.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/how-to-guides/data-basics/1-setup.md b/docs/how-to-guides/data-basics/1-setup.md index 79cfb539739e56..bc32c13638fb3c 100644 --- a/docs/how-to-guides/data-basics/1-setup.md +++ b/docs/how-to-guides/data-basics/1-setup.md @@ -1,6 +1,6 @@ ## Setup -We will build the application as a WordPress plugin, which means you need to have the WordPress itself installed. One way to do it is by following the instructions on [Getting Started](/docs/contributors/code/getting-started-with-code-contribution.md) page. Once your setup is finished, you can follow along with the rest of this tutorial. +We will build the application as a WordPress plugin, which means you need to have WordPress itself installed. One way to do this is by following the instructions on the [Getting Started](/docs/contributors/code/getting-started-with-code-contribution.md) page. Once your setup is complete, you can follow along with the rest of this tutorial. ## Creating a plugin From 7388b7c71b036ca7e26bd40d3c0ac45cd6b5be00 Mon Sep 17 00:00:00 2001 From: Adam Zielinski Date: Thu, 3 Feb 2022 14:06:10 +0100 Subject: [PATCH 27/51] Update docs/how-to-guides/data-basics/2-building-a-list-of-pages.md Co-authored-by: Dave Smith --- docs/how-to-guides/data-basics/2-building-a-list-of-pages.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md index cf8c573c04911d..d5e89fe25c7571 100644 --- a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md +++ b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md @@ -169,7 +169,7 @@ function PagesList( { pages } ) { - + From 0662b193aaffb8e1b8d623926b0a2d9b01ad073c Mon Sep 17 00:00:00 2001 From: Adam Zielinski Date: Thu, 3 Feb 2022 14:06:21 +0100 Subject: [PATCH 28/51] Update docs/how-to-guides/data-basics/2-building-a-list-of-pages.md Co-authored-by: Dave Smith --- docs/how-to-guides/data-basics/2-building-a-list-of-pages.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md index d5e89fe25c7571..8e9ec6d230a192 100644 --- a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md +++ b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md @@ -211,7 +211,7 @@ function PagesList( { pages } ) { ![](./media/list-of-pages/make-a-table.jpg) -## Step 4: Add a search Box +## Step 4: Add a search box The list of pages is short for now; however, the longer it grows, the harder it is to work with. WordPress admins typically solves this problem with a search box – let’s implement one, too! From 6f0f9ad42936525e20a5cb08301c93bcc2f831c0 Mon Sep 17 00:00:00 2001 From: Adam Zielinski Date: Thu, 3 Feb 2022 14:08:44 +0100 Subject: [PATCH 29/51] Update docs/how-to-guides/data-basics/2-building-a-list-of-pages.md Co-authored-by: Dave Smith --- docs/how-to-guides/data-basics/2-building-a-list-of-pages.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md index 8e9ec6d230a192..d1b0fda85f4ec0 100644 --- a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md +++ b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md @@ -214,7 +214,7 @@ function PagesList( { pages } ) { ## Step 4: Add a search box The list of pages is short for now; however, the longer it grows, the harder it is to work with. WordPress admins -typically solves this problem with a search box – let’s implement one, too! +typically solves this problem with a search box – let’s implement one too! Let’s start by adding a search field: From a45fc7ac5bcd2398533b6eeaf747131cb0b58b5e Mon Sep 17 00:00:00 2001 From: Adam Zielinski Date: Thu, 3 Feb 2022 14:08:54 +0100 Subject: [PATCH 30/51] Update docs/how-to-guides/data-basics/2-building-a-list-of-pages.md Co-authored-by: Dave Smith --- docs/how-to-guides/data-basics/2-building-a-list-of-pages.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md index d1b0fda85f4ec0..59504f2c2d948b 100644 --- a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md +++ b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md @@ -269,7 +269,7 @@ We can now request only the pages matching the `searchTerm`. After checking with the [WordPress API documentation]([https://developer.wordpress.org/rest-api/reference/pages/]), we see that the [/wp/v2/pages]([https://developer.wordpress.org/rest-api/reference/pages/]) endpoint accepts a `search` -query parameter and uses it to _Limit results to those matching a string_. But how to use it? We can pass custom query +query parameter and uses it to _limit results to those matching a string_. But how to use it? We can pass custom query parameters as the third argument to `getEntityRecords` as below: ```js From c67f5f1a79c2799ac9d69f9ba182ac8e24712cd2 Mon Sep 17 00:00:00 2001 From: Adam Zielinski Date: Thu, 3 Feb 2022 14:09:11 +0100 Subject: [PATCH 31/51] Update docs/how-to-guides/data-basics/2-building-a-list-of-pages.md Co-authored-by: Dave Smith --- docs/how-to-guides/data-basics/2-building-a-list-of-pages.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md index 59504f2c2d948b..156b3f654e2241 100644 --- a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md +++ b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md @@ -279,7 +279,7 @@ wp.data.select( 'core' ).getEntityRecords( 'postType', 'page', { search: 'home' Running that snippet in your browser’s dev tools will trigger a request to `/wp/v2/pages?search=home` instead of just `/wp/v2/pages`. -Let’s update our `useSelect` call as follows: +Let’s mirror this in our `useSelect` call as follows: ```js function MyFirstApp() { From 4f8cb3fc2c8c34efad30d3c26e043630d8da8367 Mon Sep 17 00:00:00 2001 From: Adam Zielinski Date: Thu, 3 Feb 2022 14:09:22 +0100 Subject: [PATCH 32/51] Update docs/how-to-guides/data-basics/2-building-a-list-of-pages.md Co-authored-by: Dave Smith --- docs/how-to-guides/data-basics/2-building-a-list-of-pages.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md index 156b3f654e2241..2eb1b820977fbe 100644 --- a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md +++ b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md @@ -298,7 +298,7 @@ function MyFirstApp() { } ``` -The `searchTerm` is now used as a `search` query parameter when specified. Note that `searchTerm` is also specified +The `searchTerm` is now used as a `search` query parameter when provided. Note that `searchTerm` is also specified inside the list of `useSelect` dependencies to make sure `getEntityRecords` is re-run when the `searchTerm` changes. Finally, here’s how `MyFirstApp` looks like once we wire it all together: From aaaf632f4c702c66be03530f54cc0da947c3cc2f Mon Sep 17 00:00:00 2001 From: Adam Zielinski Date: Thu, 3 Feb 2022 14:09:33 +0100 Subject: [PATCH 33/51] Update docs/how-to-guides/data-basics/2-building-a-list-of-pages.md Co-authored-by: Dave Smith --- docs/how-to-guides/data-basics/2-building-a-list-of-pages.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md index 2eb1b820977fbe..f91342cc69a84b 100644 --- a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md +++ b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md @@ -358,7 +358,7 @@ Voila! We can now filter the results: ![](./media/list-of-pages/filter.jpg) -### Gutenberg data vs working directly with the API +### Using core-data instead vs calling the API directly Let’s take a pause for a moment to consider an alternative approach. Imagine we sent the API requests directly: From 53225b70d9c2f8b537ddc26eee3972b1eb6f05e8 Mon Sep 17 00:00:00 2001 From: Adam Zielinski Date: Thu, 3 Feb 2022 14:09:46 +0100 Subject: [PATCH 34/51] Update docs/how-to-guides/data-basics/2-building-a-list-of-pages.md Co-authored-by: Dave Smith --- docs/how-to-guides/data-basics/2-building-a-list-of-pages.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md index f91342cc69a84b..6784438829e1e4 100644 --- a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md +++ b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md @@ -301,7 +301,7 @@ function MyFirstApp() { The `searchTerm` is now used as a `search` query parameter when provided. Note that `searchTerm` is also specified inside the list of `useSelect` dependencies to make sure `getEntityRecords` is re-run when the `searchTerm` changes. -Finally, here’s how `MyFirstApp` looks like once we wire it all together: +Finally, here’s how `MyFirstApp` looks once we wire it all together: ```js const { SearchControl } = wp.components; From 6f73b43ba5e9ee5168866aea6845c12af53dfdd4 Mon Sep 17 00:00:00 2001 From: Adam Zielinski Date: Thu, 3 Feb 2022 14:10:08 +0100 Subject: [PATCH 35/51] Update docs/how-to-guides/data-basics/2-building-a-list-of-pages.md Co-authored-by: Dave Smith --- docs/how-to-guides/data-basics/2-building-a-list-of-pages.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md index 6784438829e1e4..dc5eaea9b16965 100644 --- a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md +++ b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md @@ -360,7 +360,7 @@ Voila! We can now filter the results: ### Using core-data instead vs calling the API directly -Let’s take a pause for a moment to consider an alternative approach. Imagine we sent the API requests directly: +Let’s take a pause for a moment to consider the downsides of an alternative approach we could have taken - working with the API directly. Imagine we sent the API requests directly: ```js function MyFirstApp() { From 3c5166f3381d06a12f90e70d27d91160d4ebb163 Mon Sep 17 00:00:00 2001 From: Adam Zielinski Date: Thu, 3 Feb 2022 14:10:21 +0100 Subject: [PATCH 36/51] Update docs/how-to-guides/data-basics/2-building-a-list-of-pages.md Co-authored-by: Dave Smith --- docs/how-to-guides/data-basics/2-building-a-list-of-pages.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md index dc5eaea9b16965..12364c5a36fabc 100644 --- a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md +++ b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md @@ -376,7 +376,7 @@ function MyFirstApp() { } ``` -We would need to solve two problems here. +Working outside of core-data, we would need to solve two problems here. First, out-of-order updates. Searching for „About” would trigger five API requests filtering for A, Ab, Abo, Abou, and About. They could finish in a different order than they started. It is possible that _search=A_ would resolve after _ From fb28f442495be9b5e168314c1adfb625d781cdd2 Mon Sep 17 00:00:00 2001 From: Adam Zielinski Date: Thu, 3 Feb 2022 14:10:31 +0100 Subject: [PATCH 37/51] Update docs/how-to-guides/data-basics/2-building-a-list-of-pages.md Co-authored-by: Dave Smith --- docs/how-to-guides/data-basics/2-building-a-list-of-pages.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md index 12364c5a36fabc..9564aa95cc87d7 100644 --- a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md +++ b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md @@ -378,7 +378,7 @@ function MyFirstApp() { Working outside of core-data, we would need to solve two problems here. -First, out-of-order updates. Searching for „About” would trigger five API requests filtering for A, Ab, Abo, Abou, and +Firstly, out-of-order updates. Searching for „About” would trigger five API requests filtering for `A`, `Ab`, `Abo`, `Abou`, and About. They could finish in a different order than they started. It is possible that _search=A_ would resolve after _ search=About_ and we’d display the wrong data. From e51a9ac28c4484a548fb5adc9ee7c5b79cb475fe Mon Sep 17 00:00:00 2001 From: Adam Zielinski Date: Thu, 3 Feb 2022 14:10:45 +0100 Subject: [PATCH 38/51] Update docs/how-to-guides/data-basics/2-building-a-list-of-pages.md Co-authored-by: Dave Smith --- docs/how-to-guides/data-basics/2-building-a-list-of-pages.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md index 9564aa95cc87d7..2ced7b1139e139 100644 --- a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md +++ b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md @@ -379,7 +379,7 @@ function MyFirstApp() { Working outside of core-data, we would need to solve two problems here. Firstly, out-of-order updates. Searching for „About” would trigger five API requests filtering for `A`, `Ab`, `Abo`, `Abou`, and -About. They could finish in a different order than they started. It is possible that _search=A_ would resolve after _ +`About`. Theese requests could finish in a different order than they started. It is possible that _search=A_ would resolve after _ search=About_ and we’d display the wrong data. Gutenberg data helps by handling the asynchronous part behind the scenes. `useSelect` remembers the most recent call and From 2ecc2ae51cc224797464c3ea31f996aac23958ee Mon Sep 17 00:00:00 2001 From: Adam Zielinski Date: Thu, 3 Feb 2022 14:10:58 +0100 Subject: [PATCH 39/51] Update docs/how-to-guides/data-basics/2-building-a-list-of-pages.md Co-authored-by: Dave Smith --- docs/how-to-guides/data-basics/2-building-a-list-of-pages.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md index 2ced7b1139e139..2b8df11ff8ba86 100644 --- a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md +++ b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md @@ -380,7 +380,7 @@ Working outside of core-data, we would need to solve two problems here. Firstly, out-of-order updates. Searching for „About” would trigger five API requests filtering for `A`, `Ab`, `Abo`, `Abou`, and `About`. Theese requests could finish in a different order than they started. It is possible that _search=A_ would resolve after _ -search=About_ and we’d display the wrong data. +search=About_ and thus we’d display the wrong data. Gutenberg data helps by handling the asynchronous part behind the scenes. `useSelect` remembers the most recent call and returns only the data we expect. From ae22627d0e462bf314fa1a3ddb14d0e9878b1539 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Zieli=C5=84ski?= Date: Thu, 3 Feb 2022 14:12:23 +0100 Subject: [PATCH 40/51] "how to use it" -> "how can we use it" --- docs/how-to-guides/data-basics/2-building-a-list-of-pages.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md index 2b8df11ff8ba86..3b942cc1bd15a0 100644 --- a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md +++ b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md @@ -269,7 +269,7 @@ We can now request only the pages matching the `searchTerm`. After checking with the [WordPress API documentation]([https://developer.wordpress.org/rest-api/reference/pages/]), we see that the [/wp/v2/pages]([https://developer.wordpress.org/rest-api/reference/pages/]) endpoint accepts a `search` -query parameter and uses it to _limit results to those matching a string_. But how to use it? We can pass custom query +query parameter and uses it to _limit results to those matching a string_. But how can we use it? We can pass custom query parameters as the third argument to `getEntityRecords` as below: ```js From ca728b522dd75ceec9c8226c2f04d9e2efa6f959 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Zieli=C5=84ski?= Date: Thu, 3 Feb 2022 15:01:03 +0100 Subject: [PATCH 41/51] Migrate the tutorial to the ESNext syntax --- docs/how-to-guides/data-basics/1-setup.md | 74 ++++--- .../data-basics/2-building-a-list-of-pages.md | 207 ------------------ .../my-first-gutenberg-app/package.json | 28 +++ .../{app.js => src/index.js} | 11 +- .../media/setup/my-first-gutenberg-app/app.js | 88 -------- .../setup/my-first-gutenberg-app/package.json | 28 +++ .../setup/my-first-gutenberg-app/src/index.js | 14 ++ 7 files changed, 123 insertions(+), 327 deletions(-) create mode 100644 docs/how-to-guides/data-basics/media/list-of-pages/my-first-gutenberg-app/package.json rename docs/how-to-guides/data-basics/media/list-of-pages/my-first-gutenberg-app/{app.js => src/index.js} (80%) delete mode 100644 docs/how-to-guides/data-basics/media/setup/my-first-gutenberg-app/app.js create mode 100644 docs/how-to-guides/data-basics/media/setup/my-first-gutenberg-app/package.json create mode 100644 docs/how-to-guides/data-basics/media/setup/my-first-gutenberg-app/src/index.js diff --git a/docs/how-to-guides/data-basics/1-setup.md b/docs/how-to-guides/data-basics/1-setup.md index bc32c13638fb3c..7f75f1131f6621 100644 --- a/docs/how-to-guides/data-basics/1-setup.md +++ b/docs/how-to-guides/data-basics/1-setup.md @@ -7,20 +7,21 @@ We will build the application as a WordPress plugin, which means you need to hav We'll do all the development inside of a WordPress plugin. Let's start by creating a `wp-content/plugins/my-first-gutenberg-app` directory in your local WordPress environment. We will need to create three files inside that directory: * my-first-gutenberg-app.php – to create a new admin page -* app.js – for our JavaScript application +* src/index.js – for our JavaScript application * style.css – for the minimal stylesheet +* package.json – for the build process Go ahead and create these files using the following snippets: -**app.js:** +**src/index.js:** ```js function MyFirstApp() { - return wp.element.createElement('span', {}, 'Hello from JavaScript!'); + return Hello from JavaScript!; } window.addEventListener( 'load', function() { wp.element.render( - wp.element.createElement( MyFirstApp ), + , document.querySelector( '#my-first-gutenberg-app' ) ); }, false ); @@ -98,10 +99,10 @@ function load_custom_wp_admin_scripts( $hook ) { // editing it in the browser, and persisting the changes back to the REST API. wp_enqueue_script( 'wp-core-data' ); - // Load our app.js + // Load the built version of index.js wp_register_script( 'my-first-gutenberg-app', - plugins_url( 'my-first-gutenberg-app/app.js' ), + plugins_url( 'my-first-gutenberg-app/build/index.js' ), array( 'wp-components', 'wp-data', 'wp-core-data' ), ); wp_enqueue_script( 'my-first-gutenberg-app' ); @@ -114,35 +115,54 @@ function load_custom_wp_admin_scripts( $hook ) { add_action( 'admin_enqueue_scripts', 'load_custom_wp_admin_scripts' ); ``` -If you now go to the Plugins page, you should see a plugin called **My first Gutenberg App**. Go ahead and activate it. A new menu item labeled _My first Gutenberg app_ should show up. Once you click it, you will see a page that says _Hello from JavaScript!_: +**package.json:** + +```json +{ + "name": "05-recipe-card-esnext", + "version": "1.1.0", + "private": true, + "description": "Example: Recipe Card (ESNext).", + "author": "The WordPress Contributors", + "license": "GPL-2.0-or-later", + "keywords": [ + "WordPress", + "block" + ], + "homepage": "https://github.com/WordPress/gutenberg-examples/", + "repository": "git+https://github.com/WordPress/gutenberg-examples.git", + "bugs": { + "url": "https://github.com/WordPress/gutenberg-examples/issues" + }, + "main": "build/index.js", + "devDependencies": { + "@wordpress/scripts": "^18.0.1" + }, + "scripts": { + "build": "wp-scripts build", + "format:js": "wp-scripts format-js", + "lint:js": "wp-scripts lint-js", + "packages-update": "wp-scripts packages-update", + "start": "wp-scripts start" + } +} +``` -![](./media/setup/hello-from-js.jpg) +## Setting up the build pipeline -Congratulations! You are now ready to start building the app! +This tutorial will proceed assuming the reader is familiar with ESNext syntax and the concept of build tools (like webpack). If that sounds confusing, you may want to review the [Getting started with JavaScript Build Setup](/how-to-guides/javascript/js-build-setup.md) first. -## Readability vs Convenience +To install the build tool, navigate to the plugin directory using your terminal and run `npm install`. -You don’t need a build tool to complete this tutorial, but using one will make your code look nicer. +Once all the dependencies are in place, all that's left is to run `npm start` and voila! A watcher will run in the terminal. You can then edit away in your text editor; after each save, it will automatically build. -The examples in this tutorial use the JSX syntax: +## Testing if it worked -```js -function MyFirstApp() { - return Hello from JavaScript! ; -} -``` - -It is concise and readable, but the payoff is you need a build tool like webpack to use it. If that's what you prefer, the [Getting Started with JavaScript](/how-to-guides/javascript/) tutorial will guide you through setting up the build tool. - -There's also another way. If you'd like to start building your app right away, every JSX snippet is followed by a compiled version that works as-is: +If you now go to the Plugins page, you should see a plugin called **My first Gutenberg App**. Go ahead and activate it. A new menu item labeled _My first Gutenberg app_ should show up. Once you click it, you will see a page that says _Hello from JavaScript!_: -```js -function MyFirstApp() { - return wp.element.createElement('span', {}, 'Hello from JavaScript!'); -} -``` +![](./media/setup/hello-from-js.jpg) -You can safely ignore the JSX snippets and rely on their compiled versions – they will just work even when pasted to your browser's developer tools. +Congratulations! You are now ready to start building the app! ## What's next? diff --git a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md index 3b942cc1bd15a0..f1e5b68475f447 100644 --- a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md +++ b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md @@ -30,29 +30,6 @@ function PagesList( { pages } ) { } ``` -
Compiled snippet - -```js -function MyFirstApp() { - const pages = [{ id: 'mock', title: 'Sample page' }] - return ( - wp.element.createElement( PagesList, { pages } ) - ) -} - -function PagesList( { pages } ) { - return ( - wp.element.createElement( 'ul', {}, - pages?.map( page => ( - wp.element.createElement( 'li', { key: page.id }, page.title ) - ) ) - ) - ) -} -``` - -
- Note that this component does not fetch any data yet, only presents the hardcoded list of pages. When you refresh the page, you should see the following: @@ -130,33 +107,6 @@ function PagesList( { pages } ) { } ``` -
Compiled snippet - -```js -function MyFirstApp() { - const pages = wp.data.useSelect( - select => - select( wp.coreData.store ).getEntityRecords( 'postType', 'page' ), - [] - ); - return ( - wp.element.createElement( PagesList, { pages } ) - ) -} - -function PagesList( { pages } ) { - return ( - wp.element.createElement( 'ul', {}, - pages?.map( page => ( - wp.element.createElement( 'li', { key: page.id }, page.title ) - ) ) - ) - ) -} -``` - -
- Refreshing the page should display a list similar to this one: ![](./media/list-of-pages/fetch-the-data.jpg) @@ -184,31 +134,6 @@ function PagesList( { pages } ) { } ``` -
Compiled snippet - -```js -function PagesList( { pages } ) { - return wp.element.createElement( - 'table', - { className: 'wp-list-table widefat fixed striped table-view-list' }, - wp.element.createElement( 'thead', {}, - wp.element.createElement( 'tr', {}, - wp.element.createElement( 'td', {}, 'Title' ), - ), - ), - wp.element.createElement( 'tbody', {}, - pages?.map( page => ( - wp.element.createElement( 'tr', { key: page.id }, - wp.element.createElement( 'td', {}, page.title.rendered ), - ) - ) ), - ), - ); -} -``` - -
- ![](./media/list-of-pages/make-a-table.jpg) ## Step 4: Add a search box @@ -235,26 +160,6 @@ function MyFirstApp() { } ``` -
Compiled snippet - -```js -function MyFirstApp() { - const [searchTerm, setSearchTerm] = wp.element.useState( '' ); - // ... - return ( - wp.element.createElement( 'div', {}, - wp.element.createElement( wp.components.SearchControl, { - onChange: setSearchTerm, - value: searchTerm, - } ), - // ... - ) - ) -} -``` - -
- Note that instead of using an `input` tag, we took advantage of the [SearchControl](https://developer.wordpress.org/block-editor/reference-guides/components/search-control/) component. This is what it looks like: @@ -327,33 +232,6 @@ function MyFirstApp() { } ``` -
Compiled snippet - -```js -function MyFirstApp() { - const [searchTerm, setSearchTerm] = wp.element.useState( '' ); - const pages = wp.data.useSelect( select => { - const query = {}; - if ( searchTerm ) { - query.search = searchTerm; - } - return select( wp.coreData.store ).getEntityRecords( 'postType', 'page', query ); - }, [searchTerm] ); - - return ( - wp.element.createElement( 'div', {}, - wp.element.createElement( wp.components.SearchControl, { - onChange: setSearchTerm, - value: searchTerm, - } ), - wp.element.createElement( PagesList, { pages } ), - ) - ) -} -``` - -
- Voila! We can now filter the results: ![](./media/list-of-pages/filter.jpg) @@ -427,33 +305,6 @@ function MyFirstApp() { } ``` -
Compiled snippet - -```js -function PagesList( { hasResolved, pages } ) { - if ( !hasResolved ) { - return wp.element.createElement( wp.components.Spinner ); - } - if ( !pages?.length ) { - return wp.element.createElement( 'div', {}, 'No results' ); - } - // ... -} - -function MyFirstApp() { - // ... - - return ( - wp.element.createElement( 'div', {}, - // ... - wp.element.createElement( PagesList, { hasResolved, pages } ), - ) - ) -} -``` - -
- Note that instead of building a custom loading indicator, we took advantage of the [Spinner](https://developer.wordpress.org/block-editor/reference-guides/components/spinner/) component. @@ -538,64 +389,6 @@ function PagesList( { hasResolved, pages } ) { } ``` -
Compiled snippet - -```js - -function MyFirstApp() { - const [searchTerm, setSearchTerm] = wp.element.useState( '' ); - const { pages, hasResolved } = wp.data.useSelect( select => { - const query = {}; - if ( searchTerm ) { - query.search = searchTerm; - } - return { - pages: select( wp.coreData.store ).getEntityRecords( 'postType', 'page', query ), - hasResolved: select( wp.coreData.store ) - .hasFinishedResolution( 'getEntityRecords', ['postType', 'page', query] ), - }; - }, [searchTerm] ); - - return ( - wp.element.createElement( 'div', {}, - wp.element.createElement( wp.components.SearchControl, { - onChange: setSearchTerm, - value: searchTerm, - } ), - wp.element.createElement( PagesList, { hasResolved, pages } ), - ) - ); -} - -function PagesList( { hasResolved, pages } ) { - if ( !hasResolved ) { - return wp.element.createElement( wp.components.Spinner ); - } - if ( !pages?.length ) { - return wp.element.createElement( 'div', {}, 'No results' ); - } - - return wp.element.createElement( - 'table', - { className: 'wp-list-table widefat fixed striped table-view-list posts' }, - wp.element.createElement( 'thead', {}, - wp.element.createElement( 'tr', {}, - wp.element.createElement( 'td', {}, 'Title' ), - ), - ), - wp.element.createElement( 'tbody', {}, - pages?.map( page => ( - wp.element.createElement( 'tr', { key: page.id }, - wp.element.createElement( 'td', {}, page.title.rendered ), - ) - ) ), - ), - ); -} -``` - -
- All that’s left is to refresh the page and enjoy the brand new status indicator: ![](./media/list-of-pages/indicator.jpg) diff --git a/docs/how-to-guides/data-basics/media/list-of-pages/my-first-gutenberg-app/package.json b/docs/how-to-guides/data-basics/media/list-of-pages/my-first-gutenberg-app/package.json new file mode 100644 index 00000000000000..bdba08890bc8e9 --- /dev/null +++ b/docs/how-to-guides/data-basics/media/list-of-pages/my-first-gutenberg-app/package.json @@ -0,0 +1,28 @@ +{ + "name": "05-recipe-card-esnext", + "version": "1.1.0", + "private": true, + "description": "Example: Recipe Card (ESNext).", + "author": "The WordPress Contributors", + "license": "GPL-2.0-or-later", + "keywords": [ + "WordPress", + "block" + ], + "homepage": "https://github.com/WordPress/gutenberg-examples/", + "repository": "git+https://github.com/WordPress/gutenberg-examples.git", + "bugs": { + "url": "https://github.com/WordPress/gutenberg-examples/issues" + }, + "main": "build/index.js", + "devDependencies": { + "@wordpress/scripts": "^18.0.1" + }, + "scripts": { + "build": "wp-scripts build", + "format:js": "wp-scripts format-js", + "lint:js": "wp-scripts lint-js", + "packages-update": "wp-scripts packages-update", + "start": "wp-scripts start" + } +} diff --git a/docs/how-to-guides/data-basics/media/list-of-pages/my-first-gutenberg-app/app.js b/docs/how-to-guides/data-basics/media/list-of-pages/my-first-gutenberg-app/src/index.js similarity index 80% rename from docs/how-to-guides/data-basics/media/list-of-pages/my-first-gutenberg-app/app.js rename to docs/how-to-guides/data-basics/media/list-of-pages/my-first-gutenberg-app/src/index.js index 0011d937434e73..5e60b7529e8e98 100644 --- a/docs/how-to-guides/data-basics/media/list-of-pages/my-first-gutenberg-app/app.js +++ b/docs/how-to-guides/data-basics/media/list-of-pages/my-first-gutenberg-app/src/index.js @@ -1,21 +1,22 @@ -const { SearchControl, Spinner } = window.wp.components; +const wp = window.wp; +const { SearchControl, Spinner } = wp.components; function MyFirstApp() { - const [ searchTerm, setSearchTerm ] = window.wp.element.useState( '' ); - const { pages, hasResolved } = window.wp.data.useSelect( + const [ searchTerm, setSearchTerm ] = wp.element.useState( '' ); + const { pages, hasResolved } = wp.data.useSelect( ( select ) => { const query = {}; if ( searchTerm ) { query.search = searchTerm; } return { - pages: select( window.wp.coreData.store ).getEntityRecords( + pages: select( wp.coreData.store ).getEntityRecords( 'postType', 'page', query ), hasResolved: select( - window.wp.coreData.store + wp.coreData.store ).hasFinishedResolution( 'getEntityRecords', [ 'postType', 'page', diff --git a/docs/how-to-guides/data-basics/media/setup/my-first-gutenberg-app/app.js b/docs/how-to-guides/data-basics/media/setup/my-first-gutenberg-app/app.js deleted file mode 100644 index 38fb0206202969..00000000000000 --- a/docs/how-to-guides/data-basics/media/setup/my-first-gutenberg-app/app.js +++ /dev/null @@ -1,88 +0,0 @@ -function MyFirstApp() { - const [ searchTerm, setSearchTerm ] = window.wp.element.useState( '' ); - const { pages, hasResolved } = window.wp.data.useSelect( - ( select ) => { - const query = {}; - if ( searchTerm ) { - query.search = searchTerm; - } - return { - pages: select( window.wp.coreData.store ).getEntityRecords( - 'postType', - 'page', - query - ), - hasResolved: select( - window.wp.coreData.store - ).hasFinishedResolution( 'getEntityRecords', [ - 'postType', - 'page', - query, - ] ), - }; - }, - [ searchTerm ] - ); - - return window.wp.element.createElement( - 'div', - {}, - window.wp.element.createElement( window.wp.components.SearchControl, { - onChange: setSearchTerm, - value: searchTerm, - } ), - window.wp.element.createElement( PagesList, { hasResolved, pages } ) - ); -} - -function PagesList( { hasResolved, pages } ) { - if ( ! hasResolved ) { - return window.wp.element.createElement( window.wp.components.Spinner ); - } - if ( ! pages?.length ) { - return window.wp.element.createElement( 'div', {}, 'No results' ); - } - - return window.wp.element.createElement( - 'table', - { - className: - 'wp-list-table widefat fixed striped table-view-list posts', - }, - window.wp.element.createElement( - 'thead', - {}, - window.wp.element.createElement( - 'tr', - {}, - window.wp.element.createElement( 'td', {}, 'Title' ) - ) - ), - window.wp.element.createElement( - 'tbody', - {}, - pages?.map( ( page ) => - window.wp.element.createElement( - 'tr', - { key: page.id }, - window.wp.element.createElement( - 'td', - {}, - page.title.rendered - ) - ) - ) - ) - ); -} - -window.addEventListener( - 'load', - function () { - window.wp.element.render( - window.wp.element.createElement( MyFirstApp ), - document.querySelector( '#my-first-gutenberg-app' ) - ); - }, - false -); diff --git a/docs/how-to-guides/data-basics/media/setup/my-first-gutenberg-app/package.json b/docs/how-to-guides/data-basics/media/setup/my-first-gutenberg-app/package.json new file mode 100644 index 00000000000000..87bfbc1abfe7d6 --- /dev/null +++ b/docs/how-to-guides/data-basics/media/setup/my-first-gutenberg-app/package.json @@ -0,0 +1,28 @@ +{ + "name": "05-recipe-card-esnext", + "version": "1.1.0", + "private": true, + "description": "Example: Recipe Card (ESNext).", + "author": "The WordPress Contributors", + "license": "GPL-2.0-or-later", + "keywords": [ + "WordPress", + "block" + ], + "homepage": "https://github.com/WordPress/gutenberg-examples/", + "repository": "git+https://github.com/WordPress/gutenberg-examples.git", + "bugs": { + "url": "https://github.com/WordPress/gutenberg-examples/issues" + }, + "main": "build/index.js", + "devDependencies": { + "@wordpress/scripts": "^18.0.1" + }, + "scripts": { + "build": "wp-scripts build", + "format:js": "wp-scripts format-js", + "lint:js": "wp-scripts lint-js", + "packages-update": "wp-scripts packages-update", + "start": "wp-scripts start" + } +} diff --git a/docs/how-to-guides/data-basics/media/setup/my-first-gutenberg-app/src/index.js b/docs/how-to-guides/data-basics/media/setup/my-first-gutenberg-app/src/index.js new file mode 100644 index 00000000000000..05ec9554d2664b --- /dev/null +++ b/docs/how-to-guides/data-basics/media/setup/my-first-gutenberg-app/src/index.js @@ -0,0 +1,14 @@ +function MyFirstApp() { + return Hello from Javascript!; +} + +window.addEventListener( + 'load', + function () { + window.wp.element.render( + , + document.querySelector( '#my-first-gutenberg-app' ) + ); + }, + false +); From 6fbea81b5d2d34686cdf05832d0d96853387ecf1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Zieli=C5=84ski?= Date: Thu, 3 Feb 2022 15:05:04 +0100 Subject: [PATCH 42/51] Refactor selector arguments into a separate variable --- .../data-basics/2-building-a-list-of-pages.md | 30 +++++++++++++++---- .../my-first-gutenberg-app/src/index.js | 16 ++++------ 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md index f1e5b68475f447..a9498695684b3e 100644 --- a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md +++ b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md @@ -322,7 +322,7 @@ function MyFirstApp() { const { pages, hasResolved } = wp.data.useSelect( select => { // ... return { - pages: {/* ... */ }, + pages: select( wp.coreData.store ).getEntityRecords( 'postType', 'page', query ), hasResolved: select( wp.coreData.store ).hasFinishedResolution( 'getEntityRecords', ['postType', 'page', query] ), } @@ -332,6 +332,25 @@ function MyFirstApp() { } ``` +There is just one last problem. It is easy too make a typo and pass different arguments to `getEntityRecords` and `hasFinishedResolution`. We can remove this risk by storing the arguments in a variable: + +```js +function MyFirstApp() { + // ... + const { pages, hasResolved } = wp.data.useSelect( select => { + // ... + const selectorArgs = [ 'postType', 'page', query ]; + return { + pages: select( wp.coreData.store ).getEntityRecords( ...selectorArgs ), + hasResolved: + select( wp.coreData.store ).hasFinishedResolution( 'getEntityRecords', selectorArgs ), + } + }, [searchTerm] ); + + // ... +} +``` + All the pieces are in place, great! Here’s the complete JavaScript code of our app: ```js @@ -344,11 +363,12 @@ function MyFirstApp() { if ( searchTerm ) { query.search = searchTerm; } + const selectorArgs = [ 'postType', 'page', query ]; return { - pages: select( wp.coreData.store ).getEntityRecords( 'postType', 'page', query ), - hasResolved: select( wp.coreData.store ) - .hasFinishedResolution( 'getEntityRecords', ['postType', 'page', query] ), - }; + pages: select( wp.coreData.store ).getEntityRecords( ...selectorArgs ), + hasResolved: + select( wp.coreData.store ).hasFinishedResolution( 'getEntityRecords', selectorArgs ), + } }, [searchTerm] ); return ( diff --git a/docs/how-to-guides/data-basics/media/list-of-pages/my-first-gutenberg-app/src/index.js b/docs/how-to-guides/data-basics/media/list-of-pages/my-first-gutenberg-app/src/index.js index 5e60b7529e8e98..0f2c3cae920467 100644 --- a/docs/how-to-guides/data-basics/media/list-of-pages/my-first-gutenberg-app/src/index.js +++ b/docs/how-to-guides/data-basics/media/list-of-pages/my-first-gutenberg-app/src/index.js @@ -9,19 +9,15 @@ function MyFirstApp() { if ( searchTerm ) { query.search = searchTerm; } + const selectorArgs = [ 'postType', 'page', query ]; return { pages: select( wp.coreData.store ).getEntityRecords( - 'postType', - 'page', - query + ...selectorArgs + ), + hasResolved: select( wp.coreData.store ).hasFinishedResolution( + 'getEntityRecords', + selectorArgs ), - hasResolved: select( - wp.coreData.store - ).hasFinishedResolution( 'getEntityRecords', [ - 'postType', - 'page', - query, - ] ), }; }, [ searchTerm ] From e2b1ca12e8e8c1c74b0c73329ec3659f9ca344db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Zieli=C5=84ski?= Date: Fri, 4 Feb 2022 11:32:50 +0100 Subject: [PATCH 43/51] Fix 404 link --- docs/how-to-guides/data-basics/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/how-to-guides/data-basics/README.md b/docs/how-to-guides/data-basics/README.md index b90527d8e8e68b..3246cc32f4a2c6 100644 --- a/docs/how-to-guides/data-basics/README.md +++ b/docs/how-to-guides/data-basics/README.md @@ -6,7 +6,7 @@ This tutorial aims to get you comfortable with the Gutenberg data layer. It guid ### Table of Contents -1. [Setup](./1-setup) +1. [Setup](./1-setup.md) 2. [Building a basic list of pages](./2-building-a-list-of-pages.md) Coming soon: From a17461ee13c27a7d1cbe71ceb58d8bb8d12f3cd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Zieli=C5=84ski?= Date: Fri, 4 Feb 2022 12:19:39 +0100 Subject: [PATCH 44/51] Migrate from wp.data to module imports --- docs/how-to-guides/data-basics/1-setup.md | 57 ++++---- .../data-basics/2-building-a-list-of-pages.md | 130 ++++++++++++------ .../my-first-gutenberg-app.php | 61 ++++---- .../my-first-gutenberg-app/src/index.js | 23 ++-- .../my-first-gutenberg-app.php | 61 ++++---- 5 files changed, 186 insertions(+), 146 deletions(-) diff --git a/docs/how-to-guides/data-basics/1-setup.md b/docs/how-to-guides/data-basics/1-setup.md index 7f75f1131f6621..9c583c0c6ea1ca 100644 --- a/docs/how-to-guides/data-basics/1-setup.md +++ b/docs/how-to-guides/data-basics/1-setup.md @@ -15,12 +15,14 @@ Go ahead and create these files using the following snippets: **src/index.js:** ```js +import { render } from '@wordpress/element'; + function MyFirstApp() { return Hello from JavaScript!; } window.addEventListener( 'load', function() { - wp.element.render( + render( , document.querySelector( '#my-first-gutenberg-app' ) ); @@ -57,17 +59,17 @@ window.addEventListener( 'load', function() { */ function my_admin_menu() { - // Create a new admin page for our app + // Create a new admin page for our app. add_menu_page( - __( 'My first Gutenberg app', 'my-textdomain' ), - __( 'My first Gutenberg app', 'my-textdomain' ), + __( 'My first Gutenberg app', 'gutenberg' ), + __( 'My first Gutenberg app', 'gutenberg' ), 'manage_options', 'my-first-gutenberg-app', - function() { + function () { echo ' -

Pages

-
- '; +

Pages

+
+ '; }, 'dashicons-schedule', 3 @@ -77,38 +79,35 @@ function my_admin_menu() { add_action( 'admin_menu', 'my_admin_menu' ); function load_custom_wp_admin_scripts( $hook ) { - // Load only on ?page=my-first-gutenberg-app - if ( $hook !== 'toplevel_page_my-first-gutenberg-app' ) { + // Load only on ?page=my-first-gutenberg-app. + if ( 'toplevel_page_my-first-gutenberg-app' !== $hook ) { return; } - // Load the required WordPress packages: - - // wp-components is a library of generic WordPress components - // used for building consistent user interfaces across the board. - wp_enqueue_style( 'wp-components' ); - wp_enqueue_script( 'wp-components' ); + // Load the required WordPress packages. - // wp-data provides data management backbone such as the Redux - // implementation or data resolution mechanisms. - wp_enqueue_script( 'wp-data' ); + // Automatically load imported dependencies and assets version. + $asset_file = include plugin_dir_path( __FILE__ ) . 'build/index.asset.php'; - // wp-core-data is a glue between WordPress Core and wp-data. - // It provides a Redux store with a number of selectors and actions to - // power common tasks such as loading the data from the WordPress REST API, - // editing it in the browser, and persisting the changes back to the REST API. - wp_enqueue_script( 'wp-core-data' ); + // Enqueue CSS dependencies. + foreach ( $asset_file['dependencies'] as $style ) { + wp_enqueue_style( $style ); + } - // Load the built version of index.js + // Load our app.js. wp_register_script( 'my-first-gutenberg-app', - plugins_url( 'my-first-gutenberg-app/build/index.js' ), - array( 'wp-components', 'wp-data', 'wp-core-data' ), + plugins_url( 'build/index.js', __FILE__ ), + $asset_file['dependencies'], + $asset_file['version'] ); wp_enqueue_script( 'my-first-gutenberg-app' ); - // Load our style.css - wp_register_style( 'my-first-gutenberg-app', plugins_url( 'my-first-gutenberg-app/style.css' ) ); + // Load our style.css. + wp_register_style( + 'my-first-gutenberg-app', + plugins_url( 'style.css', __FILE__ ) + ); wp_enqueue_style( 'my-first-gutenberg-app' ); } diff --git a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md index a9498695684b3e..eaead4d9ab63f2 100644 --- a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md +++ b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md @@ -68,16 +68,21 @@ Similarly, the `MyFirstApp` component needs to re-run the selector once the data the `useSelect` hook does: ```js +import { useSelect } from '@wordpress/data'; +import { store as coreDataStore } from '@wordpress/core-data'; + function MyFirstApp() { - const pages = wp.data.useSelect( + const pages = useSelect( select => - select( wp.coreData.store ).getEntityRecords( 'postType', 'page' ), + select( coreDataStore ).getEntityRecords( 'postType', 'page' ), [] ); // ... } ``` +Note that we use an `import` statement inside index.js. This enables the plugin to automatically load the dependencies using `wp_enqueue_script`. Any references to `coreDataStore` are compiled to the same `wp.data` reference we use in browser's devtools. + `useSelect` takes two arguments: a callback and dependencies. In broad strokes, it re-runs the callback whenever either the dependencies or the underlying data store changes. You can learn more about [useSelect](#) in the [data module documentation](/packages/data/README.md#useselect). @@ -85,10 +90,13 @@ the [data module documentation](/packages/data/README.md#useselect). Putting it together, we get the following code: ```js +import { useSelect } from '@wordpress/data'; +import { store as coreDataStore } from '@wordpress/core-data'; + function MyFirstApp() { - const pages = wp.data.useSelect( + const pages = useSelect( select => - select( wp.coreData.store ).getEntityRecords( 'postType', 'page' ), + select( coreDataStore ).getEntityRecords( 'postType', 'page' ), [] ); return ; @@ -144,9 +152,11 @@ typically solves this problem with a search box – let’s implement one too! Let’s start by adding a search field: ```js -const { SearchControl } = wp.components; +import { SearchControl } from '@wordpress/components'; +import { useState, render } from '@wordpress/element'; + function MyFirstApp() { - const [searchTerm, setSearchTerm] = wp.element.useState( '' ); + const [searchTerm, setSearchTerm] = useState( '' ); // ... return (
@@ -187,15 +197,18 @@ just `/wp/v2/pages`. Let’s mirror this in our `useSelect` call as follows: ```js +import { useSelect } from '@wordpress/data'; +import { store as coreDataStore } from '@wordpress/core-data'; + function MyFirstApp() { // ... - const { pages } = wp.data.useSelect( select => { + const { pages } = useSelect( select => { const query = {}; if ( searchTerm ) { query.search = searchTerm; } return { - pages: select( wp.coreData.store ).getEntityRecords( 'postType', 'page', query ) + pages: select( coreDataStore ).getEntityRecords( 'postType', 'page', query ) } }, [searchTerm] ); @@ -209,15 +222,19 @@ inside the list of `useSelect` dependencies to make sure `getEntityRecords` is r Finally, here’s how `MyFirstApp` looks once we wire it all together: ```js -const { SearchControl } = wp.components; +import { SearchControl } from '@wordpress/components'; +import { useState, render } from '@wordpress/element'; +import { useSelect } from '@wordpress/data'; +import { store as coreDataStore } from '@wordpress/core-data'; + function MyFirstApp() { - const [searchTerm, setSearchTerm] = wp.element.useState( '' ); - const pages = wp.data.useSelect( select => { + const [searchTerm, setSearchTerm] = useState( '' ); + const pages = useSelect( select => { const query = {}; if ( searchTerm ) { query.search = searchTerm; } - return select( wp.coreData.store ).getEntityRecords( 'postType', 'page', query ); + return select( coreDataStore ).getEntityRecords( 'postType', 'page', query ); }, [searchTerm] ); return ( @@ -241,13 +258,13 @@ Voila! We can now filter the results: Let’s take a pause for a moment to consider the downsides of an alternative approach we could have taken - working with the API directly. Imagine we sent the API requests directly: ```js +import { apiFetch } from '@wordpress/api-fetch'; function MyFirstApp() { // ... const [pages, setPages] = useState( [] ); useEffect( () => { const url = '/wp-json/wp/v2/pages?search=' + searchTerm; - wp - .apiFetch( { url } ) + apiFetch( { url } ) .then( setPages ) }, [searchTerm] ); // ... @@ -282,7 +299,7 @@ A few messages like _Loading…_ or _No results_ would clear it up. Let’s imp aware of the current status: ```js -const { Spinner } = wp.components; +import { SearchControl, Spinner } from '@wordpress/components'; function PagesList( { hasResolved, pages } ) { if ( !hasResolved ) { return @@ -314,17 +331,20 @@ the `hasFinishedResolution` selector: `wp.data.select('core').hasFinishedResolution( 'getEntityRecords', [ 'postType', 'page', { search: 'home' } ] )` It takes the name of the selector and the _exact same arguments you passed to that selector_ and returns either `true` if the data was already loaded or `false` -it we’re still waiting. Let’s add it to `wp.data.useSelect`: +it we’re still waiting. Let’s add it to `useSelect`: ```js +import { useSelect } from '@wordpress/data'; +import { store as coreDataStore } from '@wordpress/core-data'; + function MyFirstApp() { // ... - const { pages, hasResolved } = wp.data.useSelect( select => { + const { pages, hasResolved } = useSelect( select => { // ... return { - pages: select( wp.coreData.store ).getEntityRecords( 'postType', 'page', query ), + pages: select( coreDataStore ).getEntityRecords( 'postType', 'page', query ), hasResolved: - select( wp.coreData.store ).hasFinishedResolution( 'getEntityRecords', ['postType', 'page', query] ), + select( coreDataStore ).hasFinishedResolution( 'getEntityRecords', ['postType', 'page', query] ), } }, [searchTerm] ); @@ -335,15 +355,17 @@ function MyFirstApp() { There is just one last problem. It is easy too make a typo and pass different arguments to `getEntityRecords` and `hasFinishedResolution`. We can remove this risk by storing the arguments in a variable: ```js +import { useSelect } from '@wordpress/data'; +import { store as coreDataStore } from '@wordpress/core-data'; function MyFirstApp() { // ... - const { pages, hasResolved } = wp.data.useSelect( select => { + const { pages, hasResolved } = useSelect( select => { // ... const selectorArgs = [ 'postType', 'page', query ]; return { - pages: select( wp.coreData.store ).getEntityRecords( ...selectorArgs ), + pages: select( coreDataStore ).getEntityRecords( ...selectorArgs ), hasResolved: - select( wp.coreData.store ).hasFinishedResolution( 'getEntityRecords', selectorArgs ), + select( coreDataStore ).hasFinishedResolution( 'getEntityRecords', selectorArgs ), } }, [searchTerm] ); @@ -354,39 +376,46 @@ function MyFirstApp() { All the pieces are in place, great! Here’s the complete JavaScript code of our app: ```js -const { SearchControl, Spinner } = wp.components; +import { SearchControl, Spinner } from '@wordpress/components'; +import { useState, render } from '@wordpress/element'; +import { useSelect } from '@wordpress/data'; +import { store as coreDataStore } from '@wordpress/core-data'; function MyFirstApp() { - const [searchTerm, setSearchTerm] = wp.element.useState( '' ); - const { pages, hasResolved } = wp.data.useSelect( select => { - const query = {}; - if ( searchTerm ) { - query.search = searchTerm; - } - const selectorArgs = [ 'postType', 'page', query ]; - return { - pages: select( wp.coreData.store ).getEntityRecords( ...selectorArgs ), - hasResolved: - select( wp.coreData.store ).hasFinishedResolution( 'getEntityRecords', selectorArgs ), - } - }, [searchTerm] ); + const [ searchTerm, setSearchTerm ] = useState( '' ); + const { pages, hasResolved } = useSelect( + ( select ) => { + const query = {}; + if ( searchTerm ) { + query.search = searchTerm; + } + const selectorArgs = [ 'postType', 'page', query ]; + return { + pages: select( coreDataStore ).getEntityRecords( + ...selectorArgs + ), + hasResolved: select( coreDataStore ).hasFinishedResolution( + 'getEntityRecords', + selectorArgs + ), + }; + }, + [ searchTerm ] + ); return (
- - + +
); } function PagesList( { hasResolved, pages } ) { - if ( !hasResolved ) { - return + if ( ! hasResolved ) { + return ; } - if ( !pages?.length ) { + if ( ! pages?.length ) { return
No results
; } @@ -398,7 +427,7 @@ function PagesList( { hasResolved, pages } ) {
- { pages?.map( page => ( + { pages?.map( ( page ) => ( @@ -407,6 +436,17 @@ function PagesList( { hasResolved, pages } ) {
TitleTitle
{ page.title.rendered }
); } + +window.addEventListener( + 'load', + function () { + render( + , + document.querySelector( '#my-first-gutenberg-app' ) + ); + }, + false +); ``` All that’s left is to refresh the page and enjoy the brand new status indicator: diff --git a/docs/how-to-guides/data-basics/media/list-of-pages/my-first-gutenberg-app/my-first-gutenberg-app.php b/docs/how-to-guides/data-basics/media/list-of-pages/my-first-gutenberg-app/my-first-gutenberg-app.php index 1c46bf9c8cd619..0f286f12ce2dfa 100644 --- a/docs/how-to-guides/data-basics/media/list-of-pages/my-first-gutenberg-app/my-first-gutenberg-app.php +++ b/docs/how-to-guides/data-basics/media/list-of-pages/my-first-gutenberg-app/my-first-gutenberg-app.php @@ -5,58 +5,55 @@ */ function my_admin_menu() { - // Create a new admin page for our app + // Create a new admin page for our app. add_menu_page( - __( 'My first Gutenberg app', 'my-textdomain' ), - __( 'My first Gutenberg app', 'my-textdomain' ), - 'manage_options', - 'my-first-gutenberg-app', - function () { - echo ' + __( 'My first Gutenberg app', 'gutenberg' ), + __( 'My first Gutenberg app', 'gutenberg' ), + 'manage_options', + 'my-first-gutenberg-app', + function () { + echo '

Pages

'; - }, - 'dashicons-schedule', - 3 + }, + 'dashicons-schedule', + 3 ); } add_action( 'admin_menu', 'my_admin_menu' ); function load_custom_wp_admin_scripts( $hook ) { - // Load only on ?page=my-first-gutenberg-app - if ( $hook !== 'toplevel_page_my-first-gutenberg-app' ) { + // Load only on ?page=my-first-gutenberg-app. + if ( 'toplevel_page_my-first-gutenberg-app' !== $hook ) { return; } - // Load the required WordPress packages: + // Load the required WordPress packages. - // wp-components is a library of generic WordPress components - // used for building consistent user interfaces across the board. - wp_enqueue_style( 'wp-components' ); - wp_enqueue_script( 'wp-components' ); + // Automatically load imported dependencies and assets version. + $asset_file = include plugin_dir_path( __FILE__ ) . 'build/index.asset.php'; - // wp-data provides data management backbone such as the Redux - // implementation or data resolution mechanisms. - wp_enqueue_script( 'wp-data' ); - - // wp-core-data is a glue between WordPress Core and wp-data. - // It provides a Redux store with a number of selectors and actions to - // power common tasks such as loading the data from the WordPress REST API, - // editing it in the browser, and persisting the changes back to the REST API. - wp_enqueue_script( 'wp-core-data' ); + // Enqueue CSS dependencies. + foreach ( $asset_file['dependencies'] as $style ) { + wp_enqueue_style( $style ); + } - // Load our app.js + // Load our app.js. wp_register_script( - 'my-first-gutenberg-app', - plugins_url( 'my-first-gutenberg-app/app.js' ), - array( 'wp-components', 'wp-data', 'wp-core-data' ), + 'my-first-gutenberg-app', + plugins_url( 'build/index.js', __FILE__ ), + $asset_file['dependencies'], + $asset_file['version'] ); wp_enqueue_script( 'my-first-gutenberg-app' ); - // Load our style.css - wp_register_style( 'my-first-gutenberg-app', plugins_url( 'my-first-gutenberg-app/style.css' ) ); + // Load our style.css. + wp_register_style( + 'my-first-gutenberg-app', + plugins_url( 'style.css', __FILE__ ) + ); wp_enqueue_style( 'my-first-gutenberg-app' ); } diff --git a/docs/how-to-guides/data-basics/media/list-of-pages/my-first-gutenberg-app/src/index.js b/docs/how-to-guides/data-basics/media/list-of-pages/my-first-gutenberg-app/src/index.js index 0f2c3cae920467..d3e665fb01d4b8 100644 --- a/docs/how-to-guides/data-basics/media/list-of-pages/my-first-gutenberg-app/src/index.js +++ b/docs/how-to-guides/data-basics/media/list-of-pages/my-first-gutenberg-app/src/index.js @@ -1,9 +1,16 @@ -const wp = window.wp; -const { SearchControl, Spinner } = wp.components; +/** + * WordPress dependencies + */ +/* eslint-disable import/no-extraneous-dependencies */ +import { SearchControl, Spinner } from '@wordpress/components'; +import { useState, render } from '@wordpress/element'; +import { useSelect } from '@wordpress/data'; +import { store as coreDataStore } from '@wordpress/core-data'; +/* eslint-enable import/no-extraneous-dependencies */ function MyFirstApp() { - const [ searchTerm, setSearchTerm ] = wp.element.useState( '' ); - const { pages, hasResolved } = wp.data.useSelect( + const [ searchTerm, setSearchTerm ] = useState( '' ); + const { pages, hasResolved } = useSelect( ( select ) => { const query = {}; if ( searchTerm ) { @@ -11,10 +18,10 @@ function MyFirstApp() { } const selectorArgs = [ 'postType', 'page', query ]; return { - pages: select( wp.coreData.store ).getEntityRecords( + pages: select( coreDataStore ).getEntityRecords( ...selectorArgs ), - hasResolved: select( wp.coreData.store ).hasFinishedResolution( + hasResolved: select( coreDataStore ).hasFinishedResolution( 'getEntityRecords', selectorArgs ), @@ -60,8 +67,8 @@ function PagesList( { hasResolved, pages } ) { window.addEventListener( 'load', function () { - window.wp.element.render( - window.wp.element.createElement( MyFirstApp ), + render( + , document.querySelector( '#my-first-gutenberg-app' ) ); }, diff --git a/docs/how-to-guides/data-basics/media/setup/my-first-gutenberg-app/my-first-gutenberg-app.php b/docs/how-to-guides/data-basics/media/setup/my-first-gutenberg-app/my-first-gutenberg-app.php index 1c46bf9c8cd619..0f286f12ce2dfa 100644 --- a/docs/how-to-guides/data-basics/media/setup/my-first-gutenberg-app/my-first-gutenberg-app.php +++ b/docs/how-to-guides/data-basics/media/setup/my-first-gutenberg-app/my-first-gutenberg-app.php @@ -5,58 +5,55 @@ */ function my_admin_menu() { - // Create a new admin page for our app + // Create a new admin page for our app. add_menu_page( - __( 'My first Gutenberg app', 'my-textdomain' ), - __( 'My first Gutenberg app', 'my-textdomain' ), - 'manage_options', - 'my-first-gutenberg-app', - function () { - echo ' + __( 'My first Gutenberg app', 'gutenberg' ), + __( 'My first Gutenberg app', 'gutenberg' ), + 'manage_options', + 'my-first-gutenberg-app', + function () { + echo '

Pages

'; - }, - 'dashicons-schedule', - 3 + }, + 'dashicons-schedule', + 3 ); } add_action( 'admin_menu', 'my_admin_menu' ); function load_custom_wp_admin_scripts( $hook ) { - // Load only on ?page=my-first-gutenberg-app - if ( $hook !== 'toplevel_page_my-first-gutenberg-app' ) { + // Load only on ?page=my-first-gutenberg-app. + if ( 'toplevel_page_my-first-gutenberg-app' !== $hook ) { return; } - // Load the required WordPress packages: + // Load the required WordPress packages. - // wp-components is a library of generic WordPress components - // used for building consistent user interfaces across the board. - wp_enqueue_style( 'wp-components' ); - wp_enqueue_script( 'wp-components' ); + // Automatically load imported dependencies and assets version. + $asset_file = include plugin_dir_path( __FILE__ ) . 'build/index.asset.php'; - // wp-data provides data management backbone such as the Redux - // implementation or data resolution mechanisms. - wp_enqueue_script( 'wp-data' ); - - // wp-core-data is a glue between WordPress Core and wp-data. - // It provides a Redux store with a number of selectors and actions to - // power common tasks such as loading the data from the WordPress REST API, - // editing it in the browser, and persisting the changes back to the REST API. - wp_enqueue_script( 'wp-core-data' ); + // Enqueue CSS dependencies. + foreach ( $asset_file['dependencies'] as $style ) { + wp_enqueue_style( $style ); + } - // Load our app.js + // Load our app.js. wp_register_script( - 'my-first-gutenberg-app', - plugins_url( 'my-first-gutenberg-app/app.js' ), - array( 'wp-components', 'wp-data', 'wp-core-data' ), + 'my-first-gutenberg-app', + plugins_url( 'build/index.js', __FILE__ ), + $asset_file['dependencies'], + $asset_file['version'] ); wp_enqueue_script( 'my-first-gutenberg-app' ); - // Load our style.css - wp_register_style( 'my-first-gutenberg-app', plugins_url( 'my-first-gutenberg-app/style.css' ) ); + // Load our style.css. + wp_register_style( + 'my-first-gutenberg-app', + plugins_url( 'style.css', __FILE__ ) + ); wp_enqueue_style( 'my-first-gutenberg-app' ); } From 52b00cd44fcb93c790327bee4091c6175e611d99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Zieli=C5=84ski?= Date: Fri, 4 Feb 2022 12:21:29 +0100 Subject: [PATCH 45/51] Refer to WordPress packages by their name --- .../how-to-guides/data-basics/2-building-a-list-of-pages.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md index eaead4d9ab63f2..543f6d00aa8fd6 100644 --- a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md +++ b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md @@ -48,9 +48,9 @@ ensure it shows at least four or five Pages: If it doesn’t, go ahead and create a few pages – you can use the same titles as on the screenshot above. Be sure to _ publish_ and not just _save_ them. -Now that we have the data to work with, let’s dive into the code. We will take advantage of the Gutenberg’s `coreData` -package which provides resolvers, selectors, and actions to work with the WordPress core API. `coreData` builds on top -of the [Gutenberg’s `data` package](https://github.com/WordPress/gutenberg/tree/trunk/packages/data). +Now that we have the data to work with, let’s dive into the code. We will take advantage of the `@wordpress/core-data` +package which provides resolvers, selectors, and actions to work with the WordPress core API. `@wordpress/core-data` builds on top +of the [`@wordpress/data` package](https://github.com/WordPress/gutenberg/tree/trunk/packages/data). To fetch the list of pages, we will use the [`getEntityRecords`](/docs/reference-guides/data/data-core/#getentityrecords) selector. In broad strokes, it will From 91246daf52873bab99a46c1db10128760ba937e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Zieli=C5=84ski?= Date: Fri, 4 Feb 2022 12:22:09 +0100 Subject: [PATCH 46/51] Link package names to the repository --- docs/how-to-guides/data-basics/2-building-a-list-of-pages.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md index 543f6d00aa8fd6..ca99d1dc13040c 100644 --- a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md +++ b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md @@ -48,7 +48,7 @@ ensure it shows at least four or five Pages: If it doesn’t, go ahead and create a few pages – you can use the same titles as on the screenshot above. Be sure to _ publish_ and not just _save_ them. -Now that we have the data to work with, let’s dive into the code. We will take advantage of the `@wordpress/core-data` +Now that we have the data to work with, let’s dive into the code. We will take advantage of the [`@wordpress/core-data` package](https://github.com/WordPress/gutenberg/tree/trunk/packages/core-data) package which provides resolvers, selectors, and actions to work with the WordPress core API. `@wordpress/core-data` builds on top of the [`@wordpress/data` package](https://github.com/WordPress/gutenberg/tree/trunk/packages/data). From 7948a686d9c921b573eae5c038ec0da172307ffd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Zieli=C5=84ski?= Date: Fri, 4 Feb 2022 13:54:04 +0100 Subject: [PATCH 47/51] Remove "Coming Soon" from README.md --- docs/how-to-guides/data-basics/README.md | 8 -------- 1 file changed, 8 deletions(-) diff --git a/docs/how-to-guides/data-basics/README.md b/docs/how-to-guides/data-basics/README.md index 3246cc32f4a2c6..c2cc98a74cc037 100644 --- a/docs/how-to-guides/data-basics/README.md +++ b/docs/how-to-guides/data-basics/README.md @@ -8,11 +8,3 @@ This tutorial aims to get you comfortable with the Gutenberg data layer. It guid 1. [Setup](./1-setup.md) 2. [Building a basic list of pages](./2-building-a-list-of-pages.md) - -Coming soon: - -3. Adding an „Edit page” feature -4. Adding a „Create a new page” feature -5. Adding a „Delete” feature -6. Advanced pages list (author column, Treegrid) - From f51f853eda977a7cc49c3a73735e278c3e2fb93e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Zieli=C5=84ski?= Date: Fri, 4 Feb 2022 13:57:31 +0100 Subject: [PATCH 48/51] Rely on the code in gutenberg-examples repo instead of including the examples here --- docs/how-to-guides/data-basics/1-setup.md | 2 +- .../data-basics/2-building-a-list-of-pages.md | 2 +- docs/how-to-guides/data-basics/README.md | 4 +- .../my-first-gutenberg-app.php | 60 --------------- .../my-first-gutenberg-app/package.json | 28 ------- .../my-first-gutenberg-app/src/index.js | 76 ------------------- .../my-first-gutenberg-app/style.css | 17 ----- .../my-first-gutenberg-app.php | 60 --------------- .../setup/my-first-gutenberg-app/package.json | 28 ------- .../setup/my-first-gutenberg-app/src/index.js | 14 ---- .../setup/my-first-gutenberg-app/style.css | 17 ----- 11 files changed, 5 insertions(+), 303 deletions(-) delete mode 100644 docs/how-to-guides/data-basics/media/list-of-pages/my-first-gutenberg-app/my-first-gutenberg-app.php delete mode 100644 docs/how-to-guides/data-basics/media/list-of-pages/my-first-gutenberg-app/package.json delete mode 100644 docs/how-to-guides/data-basics/media/list-of-pages/my-first-gutenberg-app/src/index.js delete mode 100644 docs/how-to-guides/data-basics/media/list-of-pages/my-first-gutenberg-app/style.css delete mode 100644 docs/how-to-guides/data-basics/media/setup/my-first-gutenberg-app/my-first-gutenberg-app.php delete mode 100644 docs/how-to-guides/data-basics/media/setup/my-first-gutenberg-app/package.json delete mode 100644 docs/how-to-guides/data-basics/media/setup/my-first-gutenberg-app/src/index.js delete mode 100644 docs/how-to-guides/data-basics/media/setup/my-first-gutenberg-app/style.css diff --git a/docs/how-to-guides/data-basics/1-setup.md b/docs/how-to-guides/data-basics/1-setup.md index 9c583c0c6ea1ca..55803df30cf787 100644 --- a/docs/how-to-guides/data-basics/1-setup.md +++ b/docs/how-to-guides/data-basics/1-setup.md @@ -165,6 +165,6 @@ Congratulations! You are now ready to start building the app! ## What's next? -* Review the [finished example](./media/setup/first-gutenberg-app). * Previous part: [Introduction](./README.md) * Next part: [Building a basic list of pages](./2-building-a-list-of-pages.md) +* (optional) Review the [finished app](https://github.com/WordPress/gutenberg-examples/tree/trunk/09-code-data-basics-esnext) in the gutenberg-examples repository diff --git a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md index ca99d1dc13040c..5509cdd32432ac 100644 --- a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md +++ b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md @@ -456,6 +456,6 @@ All that’s left is to refresh the page and enjoy the brand new status indicato ## What's next? -* Review the [finished example](./media/list-of-pages/first-gutenberg-app) * **Previous part:** [Setup](./1-setup.md) * **Next part:** Adding an „Edit page” feature (coming soon) +* (optional) Review the [finished app](https://github.com/WordPress/gutenberg-examples/tree/trunk/09-code-data-basics-esnext) in the gutenberg-examples repository diff --git a/docs/how-to-guides/data-basics/README.md b/docs/how-to-guides/data-basics/README.md index c2cc98a74cc037..ba1b6e39105039 100644 --- a/docs/how-to-guides/data-basics/README.md +++ b/docs/how-to-guides/data-basics/README.md @@ -2,7 +2,9 @@ This tutorial aims to get you comfortable with the Gutenberg data layer. It guides you through building a simple React application that enables the user to manage their WordPress pages. The finished app will look like this: -![](./media/finished-app.jpg) +![](./media/list-of-pages/part1-finished.jpg) + +You may review the [finished app](https://github.com/WordPress/gutenberg-examples/tree/trunk/09-code-data-basics-esnext) in the gutenberg-examples repository. ### Table of Contents diff --git a/docs/how-to-guides/data-basics/media/list-of-pages/my-first-gutenberg-app/my-first-gutenberg-app.php b/docs/how-to-guides/data-basics/media/list-of-pages/my-first-gutenberg-app/my-first-gutenberg-app.php deleted file mode 100644 index 0f286f12ce2dfa..00000000000000 --- a/docs/how-to-guides/data-basics/media/list-of-pages/my-first-gutenberg-app/my-first-gutenberg-app.php +++ /dev/null @@ -1,60 +0,0 @@ -Pages -
- '; - }, - 'dashicons-schedule', - 3 - ); -} - -add_action( 'admin_menu', 'my_admin_menu' ); - -function load_custom_wp_admin_scripts( $hook ) { - // Load only on ?page=my-first-gutenberg-app. - if ( 'toplevel_page_my-first-gutenberg-app' !== $hook ) { - return; - } - - // Load the required WordPress packages. - - // Automatically load imported dependencies and assets version. - $asset_file = include plugin_dir_path( __FILE__ ) . 'build/index.asset.php'; - - // Enqueue CSS dependencies. - foreach ( $asset_file['dependencies'] as $style ) { - wp_enqueue_style( $style ); - } - - // Load our app.js. - wp_register_script( - 'my-first-gutenberg-app', - plugins_url( 'build/index.js', __FILE__ ), - $asset_file['dependencies'], - $asset_file['version'] - ); - wp_enqueue_script( 'my-first-gutenberg-app' ); - - // Load our style.css. - wp_register_style( - 'my-first-gutenberg-app', - plugins_url( 'style.css', __FILE__ ) - ); - wp_enqueue_style( 'my-first-gutenberg-app' ); -} - -add_action( 'admin_enqueue_scripts', 'load_custom_wp_admin_scripts' ); diff --git a/docs/how-to-guides/data-basics/media/list-of-pages/my-first-gutenberg-app/package.json b/docs/how-to-guides/data-basics/media/list-of-pages/my-first-gutenberg-app/package.json deleted file mode 100644 index bdba08890bc8e9..00000000000000 --- a/docs/how-to-guides/data-basics/media/list-of-pages/my-first-gutenberg-app/package.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "name": "05-recipe-card-esnext", - "version": "1.1.0", - "private": true, - "description": "Example: Recipe Card (ESNext).", - "author": "The WordPress Contributors", - "license": "GPL-2.0-or-later", - "keywords": [ - "WordPress", - "block" - ], - "homepage": "https://github.com/WordPress/gutenberg-examples/", - "repository": "git+https://github.com/WordPress/gutenberg-examples.git", - "bugs": { - "url": "https://github.com/WordPress/gutenberg-examples/issues" - }, - "main": "build/index.js", - "devDependencies": { - "@wordpress/scripts": "^18.0.1" - }, - "scripts": { - "build": "wp-scripts build", - "format:js": "wp-scripts format-js", - "lint:js": "wp-scripts lint-js", - "packages-update": "wp-scripts packages-update", - "start": "wp-scripts start" - } -} diff --git a/docs/how-to-guides/data-basics/media/list-of-pages/my-first-gutenberg-app/src/index.js b/docs/how-to-guides/data-basics/media/list-of-pages/my-first-gutenberg-app/src/index.js deleted file mode 100644 index d3e665fb01d4b8..00000000000000 --- a/docs/how-to-guides/data-basics/media/list-of-pages/my-first-gutenberg-app/src/index.js +++ /dev/null @@ -1,76 +0,0 @@ -/** - * WordPress dependencies - */ -/* eslint-disable import/no-extraneous-dependencies */ -import { SearchControl, Spinner } from '@wordpress/components'; -import { useState, render } from '@wordpress/element'; -import { useSelect } from '@wordpress/data'; -import { store as coreDataStore } from '@wordpress/core-data'; -/* eslint-enable import/no-extraneous-dependencies */ - -function MyFirstApp() { - const [ searchTerm, setSearchTerm ] = useState( '' ); - const { pages, hasResolved } = useSelect( - ( select ) => { - const query = {}; - if ( searchTerm ) { - query.search = searchTerm; - } - const selectorArgs = [ 'postType', 'page', query ]; - return { - pages: select( coreDataStore ).getEntityRecords( - ...selectorArgs - ), - hasResolved: select( coreDataStore ).hasFinishedResolution( - 'getEntityRecords', - selectorArgs - ), - }; - }, - [ searchTerm ] - ); - - return ( -
- - -
- ); -} - -function PagesList( { hasResolved, pages } ) { - if ( ! hasResolved ) { - return ; - } - if ( ! pages?.length ) { - return
No results
; - } - - return ( - - - - - - - - { pages?.map( ( page ) => ( - - - - ) ) } - -
Title
{ page.title.rendered }
- ); -} - -window.addEventListener( - 'load', - function () { - render( - , - document.querySelector( '#my-first-gutenberg-app' ) - ); - }, - false -); diff --git a/docs/how-to-guides/data-basics/media/list-of-pages/my-first-gutenberg-app/style.css b/docs/how-to-guides/data-basics/media/list-of-pages/my-first-gutenberg-app/style.css deleted file mode 100644 index 25e32e0fa121dc..00000000000000 --- a/docs/how-to-guides/data-basics/media/list-of-pages/my-first-gutenberg-app/style.css +++ /dev/null @@ -1,17 +0,0 @@ -.toplevel_page_my-first-gutenberg-app #wpcontent { - background: #FFF; -} -#my-first-gutenberg-app { - max-width: 500px; -} -#my-first-gutenberg-app ul, -#my-first-gutenberg-app ul li { - list-style-type: disc; -} -#my-first-gutenberg-app ul { - padding-left: 20px; -} -#my-first-gutenberg-app .components-search-control__input { - height: 36px; - margin-left: 0; -} diff --git a/docs/how-to-guides/data-basics/media/setup/my-first-gutenberg-app/my-first-gutenberg-app.php b/docs/how-to-guides/data-basics/media/setup/my-first-gutenberg-app/my-first-gutenberg-app.php deleted file mode 100644 index 0f286f12ce2dfa..00000000000000 --- a/docs/how-to-guides/data-basics/media/setup/my-first-gutenberg-app/my-first-gutenberg-app.php +++ /dev/null @@ -1,60 +0,0 @@ -Pages -
- '; - }, - 'dashicons-schedule', - 3 - ); -} - -add_action( 'admin_menu', 'my_admin_menu' ); - -function load_custom_wp_admin_scripts( $hook ) { - // Load only on ?page=my-first-gutenberg-app. - if ( 'toplevel_page_my-first-gutenberg-app' !== $hook ) { - return; - } - - // Load the required WordPress packages. - - // Automatically load imported dependencies and assets version. - $asset_file = include plugin_dir_path( __FILE__ ) . 'build/index.asset.php'; - - // Enqueue CSS dependencies. - foreach ( $asset_file['dependencies'] as $style ) { - wp_enqueue_style( $style ); - } - - // Load our app.js. - wp_register_script( - 'my-first-gutenberg-app', - plugins_url( 'build/index.js', __FILE__ ), - $asset_file['dependencies'], - $asset_file['version'] - ); - wp_enqueue_script( 'my-first-gutenberg-app' ); - - // Load our style.css. - wp_register_style( - 'my-first-gutenberg-app', - plugins_url( 'style.css', __FILE__ ) - ); - wp_enqueue_style( 'my-first-gutenberg-app' ); -} - -add_action( 'admin_enqueue_scripts', 'load_custom_wp_admin_scripts' ); diff --git a/docs/how-to-guides/data-basics/media/setup/my-first-gutenberg-app/package.json b/docs/how-to-guides/data-basics/media/setup/my-first-gutenberg-app/package.json deleted file mode 100644 index 87bfbc1abfe7d6..00000000000000 --- a/docs/how-to-guides/data-basics/media/setup/my-first-gutenberg-app/package.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "name": "05-recipe-card-esnext", - "version": "1.1.0", - "private": true, - "description": "Example: Recipe Card (ESNext).", - "author": "The WordPress Contributors", - "license": "GPL-2.0-or-later", - "keywords": [ - "WordPress", - "block" - ], - "homepage": "https://github.com/WordPress/gutenberg-examples/", - "repository": "git+https://github.com/WordPress/gutenberg-examples.git", - "bugs": { - "url": "https://github.com/WordPress/gutenberg-examples/issues" - }, - "main": "build/index.js", - "devDependencies": { - "@wordpress/scripts": "^18.0.1" - }, - "scripts": { - "build": "wp-scripts build", - "format:js": "wp-scripts format-js", - "lint:js": "wp-scripts lint-js", - "packages-update": "wp-scripts packages-update", - "start": "wp-scripts start" - } -} diff --git a/docs/how-to-guides/data-basics/media/setup/my-first-gutenberg-app/src/index.js b/docs/how-to-guides/data-basics/media/setup/my-first-gutenberg-app/src/index.js deleted file mode 100644 index 05ec9554d2664b..00000000000000 --- a/docs/how-to-guides/data-basics/media/setup/my-first-gutenberg-app/src/index.js +++ /dev/null @@ -1,14 +0,0 @@ -function MyFirstApp() { - return Hello from Javascript!; -} - -window.addEventListener( - 'load', - function () { - window.wp.element.render( - , - document.querySelector( '#my-first-gutenberg-app' ) - ); - }, - false -); diff --git a/docs/how-to-guides/data-basics/media/setup/my-first-gutenberg-app/style.css b/docs/how-to-guides/data-basics/media/setup/my-first-gutenberg-app/style.css deleted file mode 100644 index 25e32e0fa121dc..00000000000000 --- a/docs/how-to-guides/data-basics/media/setup/my-first-gutenberg-app/style.css +++ /dev/null @@ -1,17 +0,0 @@ -.toplevel_page_my-first-gutenberg-app #wpcontent { - background: #FFF; -} -#my-first-gutenberg-app { - max-width: 500px; -} -#my-first-gutenberg-app ul, -#my-first-gutenberg-app ul li { - list-style-type: disc; -} -#my-first-gutenberg-app ul { - padding-left: 20px; -} -#my-first-gutenberg-app .components-search-control__input { - height: 36px; - margin-left: 0; -} From 825cd9bca479671472a040ec939e5485f6ea08fb Mon Sep 17 00:00:00 2001 From: Adam Zielinski Date: Fri, 4 Feb 2022 14:21:02 +0100 Subject: [PATCH 49/51] Update docs/how-to-guides/data-basics/2-building-a-list-of-pages.md Co-authored-by: Dave Smith --- docs/how-to-guides/data-basics/2-building-a-list-of-pages.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md index 5509cdd32432ac..ebde2d9077ceae 100644 --- a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md +++ b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md @@ -352,7 +352,7 @@ function MyFirstApp() { } ``` -There is just one last problem. It is easy too make a typo and pass different arguments to `getEntityRecords` and `hasFinishedResolution`. We can remove this risk by storing the arguments in a variable: +There is just one last problem. It is easy to make a typo and pass different arguments to `getEntityRecords` and `hasFinishedResolution`. We can remove this risk by storing the arguments in a variable: ```js import { useSelect } from '@wordpress/data'; From bb09fe51d1b0c39ec5aa7c7d841c818326b191bf Mon Sep 17 00:00:00 2001 From: Adam Zielinski Date: Fri, 4 Feb 2022 14:21:23 +0100 Subject: [PATCH 50/51] Update docs/how-to-guides/data-basics/2-building-a-list-of-pages.md Co-authored-by: Dave Smith --- docs/how-to-guides/data-basics/2-building-a-list-of-pages.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md index ebde2d9077ceae..8ea830439f3119 100644 --- a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md +++ b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md @@ -331,7 +331,7 @@ the `hasFinishedResolution` selector: `wp.data.select('core').hasFinishedResolution( 'getEntityRecords', [ 'postType', 'page', { search: 'home' } ] )` It takes the name of the selector and the _exact same arguments you passed to that selector_ and returns either `true` if the data was already loaded or `false` -it we’re still waiting. Let’s add it to `useSelect`: +if we’re still waiting. Let’s add it to `useSelect`: ```js import { useSelect } from '@wordpress/data'; From db7214ed08bde49f33631ac353736e8ec55e6ffe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Zieli=C5=84ski?= Date: Fri, 4 Feb 2022 14:22:06 +0100 Subject: [PATCH 51/51] Be more explicit about the consequences of passing different arguments to the selector and hasFinished resolution - thank you @get_dave! --- docs/how-to-guides/data-basics/2-building-a-list-of-pages.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md index 5509cdd32432ac..eb2d716a06c323 100644 --- a/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md +++ b/docs/how-to-guides/data-basics/2-building-a-list-of-pages.md @@ -352,7 +352,7 @@ function MyFirstApp() { } ``` -There is just one last problem. It is easy too make a typo and pass different arguments to `getEntityRecords` and `hasFinishedResolution`. We can remove this risk by storing the arguments in a variable: +There is just one last problem. It is easy to make a typo and end up passing different arguments to `getEntityRecords` and `hasFinishedResolution`. It is critical that they are identical. We can remove this risk by storing the arguments in a variable: ```js import { useSelect } from '@wordpress/data';