1

I want to create a block type that has a couple of fields, a template and attached JavaScript.

I want that the user in my site will be able to create blocks of this type just like they create a custom block: through /block/add/myBlockType.

I would like ideally to have it all done programmatically but I dont mind manually creating my block type though "admin/structure/block/block-content/types" or with configuration files.

The thing is I have been scraping google for two days already and I don't manage to figure out how to programmatically create a block type

And this that the information is not easily found on Google makes me think that instead I need to create my type with configuration and then apply my plugin on creation of a new block but im still not sure how to do that and what my plugin needs to extend.

How can I do that?

6
  • When creating custom block types programatically you create a Block plugin. There are a ton of guides how to do that, here's one. valuebound.com/resources/blog/…
    – user72672
    Commented Jan 1, 2020 at 17:00
  • Thank you for the reply. I have already written this block plugin. and I have found tons of guides just like the one you linked here. but they all finish with one single block. I want that my user will be able to create as many blocks as they wish.
    – crab
    Commented Jan 1, 2020 at 17:15
  • Oh, this works in panels, but not in core. You have to add a deriver to the block plugin in order for it to work. Look at this post for help. drupal.stackexchange.com/questions/264177/…
    – user72672
    Commented Jan 1, 2020 at 17:29
  • The discussion is confusing. A custom block type is the bundle of the block content entity (like content type for nodes) and not a block plugin. @crab, please make it more clear what you want to create.
    – 4uk4
    Commented Jan 1, 2020 at 17:43
  • 1
    Perhaps you want to export a block type to a module so that it is created when the module is installed, like this question for paragraph types: drupal.stackexchange.com/questions/283090/…
    – 4uk4
    Commented Jan 1, 2020 at 18:59

3 Answers 3

4

I had the same issue and I hope I have resolved it.

Your algorithm is next:

  1. Create your own module
  2. Create file <your_module>.install
  3. There must be at least one hook hook_install (I have used two: hook_install and hook_uninstall)
  4. Inside install hook:
    • create a new block type
    • create fieldStorageConfig
    • create fieldConfig
    • set component for form and view display

My code:

<?php

use Drupal\block_content\Entity\BlockContentType;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;

function <your_module_name>_install() {
  $newBlockType = BlockContentType::create([
    'id' => <your_id>,
    'label' => 'Custom block type',
    'description' => "A custom block type",
  ]);
  $newBlockType->save();

  $blockId = $newBlockType->id();

  block_content_add_field($blockId, 'Icon', 'custom_block_icon', 'image', 'image', 'image_image');
  block_content_add_field($blockId, 'Count', 'custom_block_count', 'integer', 'number_integer', 'number');
  block_content_add_field($blockId, 'Description', 'custom_block_description', 'text', 'text_default', 'text_textfield');

}
function block_content_add_field(
  $blockTypeId,
  $label,
  $componentName,
  $fieldStorageType,
  $viewDisplayType = 'text_default',
  $formDisplayType = 'text_textarea_with_summary') {
    // Add or remove the body field, as needed.
    $field = FieldConfig::loadByName('block_content', $blockTypeId, $componentName);
    if (empty($field)) {
      $fieldStorage = FieldStorageConfig::loadByName('block_content', $componentName);
      if (empty($fieldStorage)) {
        $fieldStorage = FieldStorageConfig::create([
          'field_name' => $componentName,
          'entity_type' => 'block_content',
          'type' => $fieldStorageType,
        ]);
        $fieldStorage->save();
      }

      $field = FieldConfig::create([
        'field_storage' => $fieldStorage,
        'bundle' => $blockTypeId,
        'label' => $label,
        'settings' => ['display_summary' => FALSE],
      ]);

      $field->save();

      /** @var \Drupal\Core\Entity\EntityDisplayRepositoryInterface $display_repository */
      $display_repository = \Drupal::service('entity_display.repository');

      // Assign widget settings for the default form mode.
      $display_repository->getFormDisplay('block_content', $blockTypeId)
        ->setComponent($componentName, [
          'type' => $formDisplayType,
        ])
        ->save();

      // Assign display settings for default view mode.
      $display_repository->getViewDisplay('block_content', $blockTypeId)
        ->setComponent($componentName, [
          'label' => 'hidden',
          'type' => $viewDisplayType,
        ])
        ->save();
    }

    return $field;
}

Result: the new custom block type with 3 fields.

3
  • Danyil - did you place your code in a your_module.install file? Can you share a little more about the module part. Tryin to learn this and this is the most complete information I can find and still a push. I added this to a module I have for a custom block plugin. But this threw an error... thanks!
    – timwhelan
    Commented Sep 26, 2020 at 21:54
  • So, I wanted to add this to Danyil's answer. I need to get something working. I added connections to classes and was able to get the Block to install in Custom Block Types on my site. use Drupal\block_content\Entity\BlockContentType; use Drupal\Core\Block\Blockbase; use Drupal\field\Entity\FieldConfig; use Drupal\field\Entity\FieldStorageConfig; use Drupal\Core\Entity\EntityStorage; Hope this helps someone!
    – timwhelan
    Commented Sep 27, 2020 at 19:21
  • @timwhelan Yes, I did. Ex: your module name is coolModule so, create a file coolModule.install and inside it write a hook function coolModule_install(){} Commented Sep 28, 2020 at 14:21
1

You can create content block type using configuration files:
In you module should have config/install/block_content.type.YOUR_BLOCK_TYPE_MACHINE_NAME.yml see the following example from core for Basic block core/profiles/standard/config/install/block_content.type.basic.yml .

Here is an example to create new type called My Block Type

  1. Go to admin/structure/block/block-content/types Create by clicking on Add custom block type
  2. Create fields you want by Manage Fields

  3. To export your configuration Go to admin/config/development/configuration/single/export enter image description here And Create a config file in your Module and put in it the result: YOURMODULENAME/config/install/block_content.type.my_block_type.yml

  4. And also you should export fields associated to your block type: the same way you did with block type config: Go to admin/config/development/configuration/single/export choose Field as configuration type and choose all Configuration name with name block_content.my_block_type.FIELD_NAME like the body field below enter image description here and then the Field Storage configuration.

Or you can export configuration using Drupal console like the following:

drupal config:export:entity block_content my_block_type --module="YOURMODULENAME" --optional-config --remove-uuid --remove-config-hash --include-module-dependencies
0

An easier way to do this would be to:

  1. Add block_content module as a dependency to your custom module
  2. Create the configuration you want and export it, pay attention to the config files created for step 3 below.
  3. Add the exported config to your module under your_module/config/install. You can use config_devel for that to make your life easier.
  4. Enable your module.

This goes more towards the Drupal 7 Features, but it is quite easier to handle and to maintain.

The .info.yml file will have these lines in the end if you use config_devel:

dependecies:
  - block_content

config_devel:
  - block_content.type.html_block
  - language.content_settings.block_content.html_block
  - field.field.block_content.html_block.body
  - core.entity_view_display.block_content.html_block.default
  - core.entity_form_display.block_content.html_block.default

I had to add 5 files in my case (one field, with translations enabled).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.