Component in a Block
Blocks and components work perfectly together because they are made that way. We simplified this as much as possible but there always a few things you need to do manually.
Try to think of your development process in this way:
- Each component must be standalone and ideally not depend on any other components (sometimes this is not possible but keep this to a minimum).
- Components must not be aware of the layout they are used in.
- No global styles. Instead, all styles should be contained to the block/component. For more details, check this link.
- You should define all heading variations in a
heading
component. You can then use this component everywhere you have a heading instead of writing a new implementation. In practice: don't do<h2>$heading</h2>
but render theheading
component instead using the helpers defined in the helpers section. The heading is just an example, but this applies to every component. - You can have multiple heading components in one block.
I want to use one heading component in my block.
If you have a heading component with these attributes:
src/Blocks/components/heading/manifest.json
"attributes": {
"headingContent": {
"type": "string"
},
"headingLevel": {
"type": "integer",
"default": 2
},
"headingSize": {
"type": "string",
"default": "default"
},
}
and you want to use the heading component in the Jumbotron block, you can use it by adding a component's key in the Jumbotron block manifest like this:
src/Blocks/custom/jumbotron/manifest.json
"attributes": {
"content": {
"type": "string"
"default": "test",
}
},
"components": {
"heading": "heading"
}
In your block attributes object, you will now have these keys:
// Attributes from the component.
"headingContent": "",
"headingLevel": 2,
"headingSize": "default",
// Attributes from the block.
"content": "test",
As you can see in the example, you can merge component attributes in your block attributes. Keep in mind that, in the provided example, the components' attributes will be injected in the block attributes with the same name as defined in the components manifest.
I want to use one heading and paragraph component in my block.
You can do this by following the same principle as before. Here is an example:
src/Blocks/custom/jumbotron/manifest.json
"attributes": {
"content": {
"type": "string"
"default": "test",
}
},
"components": {
"heading": "heading"
"paragraph": "paragraph"
}
I want two heading components in my block.
As you already saw in the previous examples, the heading key and value are the same in the components object. The key represents the components attributes prefix
, and the value represents the actual component name
.
If you want to use the heading component in your block, follow this example:
src/Blocks/custom/jumbotron/manifest.json
"attributes": {
"content": {
"type": "string"
"default": "test",
}
},
"components": {
"heading": "heading"
"intro": "heading"
}
In your block attributes object, you will now have these keys:
// Attributes from the first component.
"headingContent": "",
"headingLevel": 2,
"headingSize": "default",
// Attributes from the second component.
"introContent": "",
"introLevel": 2,
"introSize": "default",
// Attributes from the block.
"content": "test",
I want to override a default attribute of a component in a block.
We build all our attributes by merging attributes objects in this order:
- global attributes (global settings);
- wrapper attributes;
- component attributes; and
- block attributes.
By following the basic principle of merging objects, if you have two keys with the same name, the last one will always override the previous. Now that you know how attributes are built, you can follow this example for your answer.
If you have a heading component with these attributes:
src/Blocks/components/heading/manifest.json
"attributes": {
"headingContent": {
"type": "string"
},
"headingLevel": {
"type": "integer",
"default": 2
},
"headingSize": {
"type": "string",
"default": "default"
},
}
and you want to override one or multiple default attributes from the heading component.
src/Blocks/custom/jumbotron/manifest.json
"attributes": {
"content": {
"type": "string"
"default": "test",
},
"headingSize": {
"type": "string",
"default": "small"
}
},
"components": {
"heading": "heading"
}
In your block attributes object, you will now have these keys:
// Attributes from the component.
"headingContent": "",
"headingLevel": 2,
"headingSize": "small", // changed in the block attributes.
// Attributes from the block.
"content": "test",
Keep in mind that we handle the attributes data necessary to have multiple components in one block but you must provide the correct props inside your files to mock the custom attribute names. The best way to see how this is done is to check the card block.
I want to use a component that uses more components (componentCeption).
For example, if you have a block called cards grid that uses a card component, that card component uses a heading component.
If you have a heading component with these attributes:
src/Blocks/components/heading/manifest.json
"attributes": {
"headingContent": {
"type": "string"
},
"headingLevel": {
"type": "integer",
"default": 2
},
"headingSize": {
"type": "string",
"default": "default"
},
}
and you have a card component:
src/Blocks/components/card/manifest.json
"attributes": {
"superCard": {
"type": "boolean"
"default": true,
},
},
"components": {
"heading": "heading"
}
and you have a cards grid block:
src/Blocks/custom/cards-grid/manifest.json
"attributes": {
"content": {
"type": "string"
"default": "test",
},
},
"components": {
"card": "card"
}
in your block attributes object, you will now have these keys:
// Attributes from the heading component.
"headingContent": "",
"headingLevel": 2,
"headingSize": "default",
// Attributes from the card component.
"superCard": true,
// Attributes from the block.
"content": "test",
As you can see in the example, you have all the attributes from the card and heading component inside your card's grid block.