NocoBase has many Add block buttons for adding blocks to the interface. Some are related to data tables and are called data blocks Data Block, while others that are not related to data tables are called simple blocks Simple Block.

However, the existing block types may not meet our requirements, so we need to develop custom blocks according to our needs. This article focuses on explaining simple blocks Simple Block.
This example will create an image block type and add it to the Add block in Page, Table, and mobile.
This example is mainly to demonstrate the use of initializer. For more information about block extension, please refer to the Block Extension documentation.
The complete example code for this document can be found in plugin-samples.
Following the Write Your First Plugin documentation, if you don't have a project yet, you can create one first. If you already have one or have cloned the source code, you can skip this step.
Then initialize a plugin and add it to the system:
Then start the project:
After logging in, visit http://localhost:13000/admin/pm/list/local/ to see that the plugin has been installed and enabled.
Before implementing this example, we need to understand some basic knowledge:
First, we need to define the block name, which will be used in various places.
We create packages/plugins/@nocobase-sample/plugin-initializer-block-simple/src/client/constants.ts:
This example is about an image block component, so we name it Image.
We create packages/plugins/@nocobase-sample/plugin-initializer-block-simple/src/client/component/Image.tsx file with the following content:
The Image component is essentially a functional component wrapped by withDynamicSchemaProps. withDynamicSchemaProps is a higher-order component used to handle dynamic properties in Schema.
If we ignore withDynamicSchemaProps, Image is just a simple functional component.
Then export it in packages/plugins/@nocobase-sample/plugin-initializer-block-simple/src/client/component/index.ts:
We need to register Image to the system through the plugin.
There are 2 ways to verify components:
Image component to check if it meets the requirementsyarn doc plugins/@nocobase-sample/plugin-initializer-block-simple, and verify if it meets the requirements by writing documentation examples (TODO)We use temporary page verification as an example. We create a new page and add one or more Image components according to property parameters to check if they meet the requirements.
Then visit http://localhost:13000/admin/image-component to see the corresponding test page content.

After verification, the test page needs to be deleted.
NocoBase's dynamic pages are all rendered through Schema, so we need to define a Schema, which will be used later to add the Image block to the interface. Before implementing this section, we need to understand some basic knowledge:
We create packages/plugins/@nocobase-sample/plugin-initializer-block-simple/src/client/schema/index.ts file:
Details about imageSchema:
type: Type, here it is void, indicating a pure UI node with no datax-decorator: Decorator, here it is CardItem component, currently all blocks are wrapped in cards, which provide styles, layouts, and drag-and-drop functionalityx-component: Component, here it is Image, which is the component we just definedThe above Schema is equivalent to the following React component:
Same as verifying components, we can verify the Schema by temporary page verification or documentation example verification. Here we use temporary page verification as an example:
For detailed explanation of SchemaComponent, please refer to the SchemaComponent documentation.
We visit http://localhost:13000/admin/image-schema to see the corresponding test page content.

After verification, the test page needs to be deleted.
We create packages/plugins/@nocobase-sample/plugin-initializer-block-simple/src/client/initializer/index.ts file:
type: Type, here it is item, indicating a text with a click event that can insert a new Schema when clickedname: Unique identifier used to distinguish different Schema Items and CRUD operationsicon: Icon, more icons can be found at Ant Design IconsuseComponentProps: Returns an object containing title and onClick properties, title is the displayed text, onClick is the callback function after clickingSchemaInitializerContext context
insert: Insert a new SchemaFor more information about Schema Item definitions, please refer to the Schema Initializer Item documentation.
A complete Block also needs to have Schema Settings, which are used to configure some properties and operations, but Schema Settings is not the focus of this example, so we only have a remove operation here.
We create packages/plugins/@nocobase-sample/plugin-initializer-block-simple/src/client/settings/index.ts file:
removeParentsIfNoChildren: Whether to delete the parent node if there are no child nodesbreakRemoveOn: Break condition when deleting. Because Add Block automatically wraps children in Grid, we set breakRemoveOn: { 'x-component': 'Grid' } here, so when deleting Grid, it doesn't delete upwards anymore.We modify packages/plugins/@nocobase-sample/plugin-initializer-block-simple/src/client/schema/index.ts in the imageSchema:
There are many Add block buttons in the system, but their names are different.

If we need to add it to the page-level Add block, we need to know the corresponding name. We can view the corresponding name through TODO method.
TODO
From the above figure, we can see that the page-level Add block corresponds to the name page:addBlock, and Other Blocks corresponds to the name otherBlocks.
Then we modify packages/plugins/@nocobase-sample/plugin-initializer-block-simple/src/client/index.tsx file:
The above code first registers the Image component to the system, so that the x-component: 'Image' defined in imageSchema can find the corresponding component. For more detailed explanation, please refer to Global Registration of Component and Scope.
Then add imageSettings to the system through app.schemaSettingsManager.add.
Then use app.schemaInitializerManager.addItem to add imageInitializerItem to the corresponding Initializer sub-item, where page:addBlock is the name of Add block on the page, and otherBlocks is the name of its parent.
Then hover over the Add block button, and you can see the new block type Image. Click Image to add a new Image block.
We need to add it not only to the page-level Add block, but also to the Add block in the Table block Add new modal.

According to the method of obtaining the page-level name, we get the Add block name of the Table block as popup:addNew:addBlock, and Other Blocks corresponds to the name otherBlocks.
Then modify packages/plugins/@nocobase-sample/plugin-initializer-block-simple/src/client/index.tsx file:

First, you need to activate the mobile plugin, refer to the Activate Plugin documentation.
We can add it to the mobile Add block. The method of obtaining the name will not be repeated here.
Then modify packages/plugins/@nocobase-sample/plugin-initializer-block-simple/src/client/index.tsx file:

If you need more Add block, you can continue to add them, just need to know the corresponding name.
According to the Build and Package Plugin documentation, we can package the plugin and upload it to the production environment.
If you cloned the source code, you need to execute a full build first to build the plugin's dependencies as well.
If you used create-nocobase-app to create the project, you can directly execute:
This way you can see the storage/tar/@nocobase-sample/plugin-initializer-block-simple.tar.gz file, and then install it by uploading.