Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Exercise 2 for the Edit component! #15

Draft
wants to merge 27 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
28aa16e
Add the beginning of exercise 2 for the Edit component
kienstra Jan 28, 2022
b8c4a87
Remove an extra single quote
kienstra Jan 28, 2022
a67efb0
Add 🚧 emoji to show what to work on
kienstra Jan 28, 2022
09afcd9
Merge branch 'main' into exercise/2-edit-component
kienstra Jan 28, 2022
91654a7
Add a link and more text
kienstra Jan 28, 2022
7f8dab1
Merge branch 'main' into exercise/2-edit-component
kienstra Jan 28, 2022
b6473a0
Add a placeholder for Save
kienstra Jan 29, 2022
3f85a15
Remove the full URL
kienstra Jan 29, 2022
7c1a65d
Let the student call useBlockProps
kienstra Jan 29, 2022
0d6cb6d
Add a link to InspectorControls
kienstra Jan 29, 2022
934d036
Remoev 'in WordPress'
kienstra Jan 29, 2022
f812e56
Remove import that a comment references
kienstra Feb 2, 2022
1560313
Merge in main, resolve conflict
kienstra Feb 2, 2022
35c168f
Add more about the onChange handler to INSTRUCTIONS.md
kienstra Feb 2, 2022
55b49bb
Add to the Exercise section
kienstra Feb 2, 2022
83f9cf7
Merge branch 'main' into exercise/2-edit-component
kienstra Feb 4, 2022
d3fad13
Make attributes singular
kienstra Feb 4, 2022
840b967
Merge branch 'main' into exercise/2-edit-component
kienstra Feb 10, 2022
e2741a3
Import the exercise one, not the final one
kienstra Feb 10, 2022
92b9031
Change Color to singular
kienstra Feb 10, 2022
2d6adc6
Make the link text only lower case in the first word
kienstra Feb 10, 2022
2a3bc49
Merege in main, resolve conflicts
kienstra Mar 17, 2022
2842b2f
Make indentation a little easier to read
kienstra Mar 17, 2022
7b1506e
Add a period at the end of a comment
kienstra Mar 17, 2022
e24004d
Fix typos in INSTRUCTIONS.md
kienstra Mar 17, 2022
479a8d4
Remove brackets that hide the link
kienstra Mar 17, 2022
ebfb7bd
Improve the copy in INSTRUCTIONS.md
kienstra Mar 17, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions INSTRUCTIONS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Edit Component

A block's `Edit` component is what renders in the block editor.

It's a React component that's similar to non-WordPress React components.

Though WordPress has custom APIs and hooks.

WordPress also has a big component library in [@wordpress/components](https://github.com/WordPress/gutenberg/tree/trunk/packages/components) that we'll use.

Most of the time, you won't need to write a custom control. That component library will usually have what you need.

We'll render the block controls in [InspectorControls](https://github.com/WordPress/gutenberg/tree/57da3c91a166d917a2a9de98177be9c3dfe07ee5/packages/block-editor/src/components/inspector-controls).

By rendering components inside `<InspectorControls>`, they appear in the Inspector.

## Exercise

You're going to write the `Edit` component.

It's what that the user sees in the block editor.

This component is very interactive.

Its function is to update the block attributes and markup as the user edits the block.

One of its `props` is `setAttributes`:

```jsx
export default function Edit( {
attributes,
setAttributes
} ) {
```

That sets an attribute to a new value.

For example, when the user selects a color, it can set the `color` attribute:

```jsx
onChange={ ( newValue ) =>
setAttributes( { color: newValue } )
}
```

That handler accepts a `newValue` parameter, which is the value that the user just selected.

And `setAttributes` accepts an object.

That object only needs one property, which is the name of the attribute:

```jsx
setAttributes( { color: newValue } )
```

### File
- [js/src/edit.exercise.js](js/src/edit.exercise.js)

[Solution video](https://bit.ly/3HJCDVg)
61 changes: 61 additions & 0 deletions js/src/edit.exercise.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/**
* External dependencies
*/
import * as React from 'react';

/**
* WordPress dependencies
*/
// @ts-ignore The declaration file is outdated.
// 🚧 Also import useBlockProps from '@wordpress/block-editor'
import { InspectorControls } from '@wordpress/block-editor';
// 🚧 Also import a component from '@wordpress/components' to choose a color, and another component to choose a number: https://github.com/WordPress/gutenberg/tree/trunk/packages/components/src
import { PanelBody } from '@wordpress/components';
import { useSelect } from '@wordpress/data';
import { __ } from '@wordpress/i18n';

/**
* The component for the editor.
*
* @param {{
* attributes: import('./').Attributes,
* setAttributes: Function
* }} props
*/
export default function Edit( { attributes, setAttributes } ) {
const blockProps = // 🚧 Call useBlockProps.
const { colors } = useSelect(
// 🚧 Add an anonymous function here as an argument of useSelect().
// The function should accept select as a parameter.
// Then, it should get the data store with:
// select( 'core/block-editor' )
// Call .getSettings() on that data store, and return that.
);

return <div { ...blockProps }>
<p>{ __( 'This is a placeholder for the Progress Indicator block', 'progress-indicator' ) }</p>
<InspectorControls>
{ /*
🚧 Add 2 <PanelBody> components here, and give each of them a title prop that's translated with __().

Inside the 1st <PanelBody>
Add the component to choose colors that you imported above from '@wordpress/components'.
That will be for attributes.color.
Inside the 2nd <PanelBody>
Add 2 components to choose numbers that you imported above from '@wordpress/components'.
Those will be for attribute.currentStep and attributes.numberOfSteps.

The value prop of those components should be the attribute for it.
For example, the value of the color component should be attributes.color.
The onChange prop should be like:

onChange={ ( newValue ) =>
setAttributes( { color: newValue } )
}

The setAttributes() call should have an object with its property being the attribute name.
For example, if the attribute name is color, it would be setAttributes( { color: newValue } )
*/ }
</InspectorControls>
</div>;
}
63 changes: 63 additions & 0 deletions js/src/edit.final.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/**
* External dependencies
*/
import * as React from 'react';

/**
* WordPress dependencies
*/
// @ts-ignore The declaration file is outdated.
import { InspectorControls, useBlockProps } from '@wordpress/block-editor';
import { ColorPalette, PanelBody, RangeControl } from '@wordpress/components';
import { useSelect } from '@wordpress/data';
import { __ } from '@wordpress/i18n';

/**
* The component for the editor.
*
* @param {{
* attributes: import('./index').Attributes,
* setAttributes: Function
* }} props
*/
export default function Edit( { attributes, setAttributes } ) {
const blockProps = useBlockProps();
const { colors } = useSelect(
( select ) => select( 'core/block-editor' ).getSettings()
);

return <div { ...blockProps }>
<p>{ __( 'This is a placeholder for the Progress Indicator block', 'progress-indicator' ) }</p>
<InspectorControls>
<PanelBody title={ __( 'Color', 'progress-indicator' ) }>
<ColorPalette
colors={ colors }
value={ attributes.color }
onChange={ ( newValue ) =>
setAttributes( { color: newValue } )
}
/>
</PanelBody>
<PanelBody title={ __( 'Steps', 'progress-indicator' ) }>
<RangeControl
label={ __( 'Current Step', 'progress-indicator' ) }
value={ attributes.currentStep }
onChange={ ( newValue ) =>
setAttributes( { currentStep: Number( newValue ) } )
}
min={ 1 }
max={ attributes.numberOfSteps }
/>
<RangeControl
label={ __( 'Number of Steps', 'progress-indicator' ) }
value={ attributes.numberOfSteps }
onChange={ ( newValue ) =>
setAttributes( { numberOfSteps: Number( newValue ) } )
}
min={ 1 }
max={ 10 }
/>
</PanelBody>
</InspectorControls>
</div>;
}
67 changes: 3 additions & 64 deletions js/src/edit.js
Original file line number Diff line number Diff line change
@@ -1,68 +1,7 @@
/**
* External dependencies
*/
import * as React from 'react';

/**
* WordPress dependencies
*/
import { InspectorControls, useBlockProps } from '@wordpress/block-editor';
import { ColorPalette, PanelBody, RangeControl } from '@wordpress/components';
import { useSelect } from '@wordpress/data';
import { __ } from '@wordpress/i18n';

/**
* Internal dependencies
*/
import ProgressIndicator from './progress-indicator';

/**
* The component for the editor.
*
* @param {{
* attributes: import('./index').Attributes,
* setAttributes: Function
* }} props
* @return {React.ReactElement} The component.
*/
export default function Edit( { attributes, setAttributes } ) {
const blockProps = useBlockProps();
const { colors } = useSelect(
( select ) => select( 'core/block-editor' ).getSettings()
);
import Edit from './edit.exercise';
// import Edit from './edit.final';

return <div { ...blockProps }>
<ProgressIndicator attributes={ attributes } />
<InspectorControls>
<PanelBody title={ __( 'Color', 'progress-indicator' ) }>
<ColorPalette
colors={ colors }
value={ attributes.color }
onChange={ ( newValue ) =>
setAttributes( { color: newValue } )
}
/>
</PanelBody>
<PanelBody title={ __( 'Steps', 'progress-indicator' ) }>
<RangeControl
label={ __( 'Current Step', 'progress-indicator' ) }
value={ attributes.currentStep }
onChange={ ( newValue ) =>
setAttributes( { currentStep: Number( newValue ) } )
}
min={ 1 }
max={ attributes.numberOfSteps }
/>
<RangeControl
label={ __( 'Number of Steps', 'progress-indicator' ) }
value={ attributes.numberOfSteps }
onChange={ ( newValue ) =>
setAttributes( { numberOfSteps: Number( newValue ) } )
}
min={ 1 }
max={ 10 }
/>
</PanelBody>
</InspectorControls>
</div>;
}
export default Edit;
1 change: 0 additions & 1 deletion js/src/progress-indicator.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import tinycolor2 from 'tinycolor2';
* The progress indicator component.
*
* @param {{attributes: import('./').Attributes}} props
* @return {React.ReactElement} The component.
*/
export default function ProgressIndicator( { attributes } ) {
const color = tinycolor2( attributes.color );
Expand Down
44 changes: 0 additions & 44 deletions js/src/progress-indicator.test.js

This file was deleted.

24 changes: 6 additions & 18 deletions js/src/save.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,11 @@ import * as React from 'react';
/**
* WordPress dependencies
*/
import { useBlockProps } from '@wordpress/block-editor';
import { __ } from '@wordpress/i18n';

/**
* Internal dependencies
*/
import ProgressIndicator from './progress-indicator';

/**
* The component to save the markup.
*
* @param {{attributes: import('./').Attributes}} props
* @return {React.ReactElement} The component.
*/
export default function Save( { attributes } ) {
const blockProps = useBlockProps.save();

return <div { ...blockProps }>
<ProgressIndicator attributes={ attributes } />
</div>;
/** The component to save the markup. */
export default function Save() {
return <span>
{ __( 'This is a placeholder for the Progress Indicator block', 'progress-indicator' ) }
</span>;
}