8

I'm pretty new to Drupal, I come from Wordpress development and I'm trying to "translate" some of my plugins to modules in Drupal 8.

I'm following the documentation trying to add a new field, say "price" to a node. All the documentation I found is related to add a field to a custom node, but in my case I want to add those fields to normal predefined nodes.

First question that comes to my mind is, I can create the custom field with YML configuration files or code right?

I created the field with YML and it is recognised by drupal; the problem is that they don't appear on the nodes (I have to manually activate it).

I created on my module /config/install/:

  • core.entity_form_display.node.article.default
  • core.entity_view_display.node.article.default

I add my field, but of course when I try to activate the module it does not like it since they are already defined by Drupal.

Is there a way to "extend" those core files? is that possible with YML or code?

I followed https://www.drupal.org/docs/8/api/entity-api/programming-custom-fields-into-your-content-type. I created the YML files on /config/install, and indeed the field is created, the problem is I don't know how to "extend" view and form display entities as they are not related to a custom node type, otherwise they should be linked to pre-built node types and I cannot redefine those files (core.entity_form_display.node.article.default core.entity_view_display.node.article.default) since they already exist on the core.

Following this comment I've created the following files:

/config/install/field.field.node.article.field_price.yml

langcode: en
status: true
dependencies:
  config:
    - field.storage.node.field_price
    - node.type.article
id: node.article.field_price
field_name: field_price
entity_type: node
bundle: article
label: Price
description: 'Premium Price'
required: false
translatable: false
default_value: {  }
default_value_callback: ''
settings:
  min: 1
  max: 9999
  prefix: ''
  suffix: ''
field_type: integer

/config/install/field.storage.node.field_price.yml

langcode: en
status: true
dependencies:
  module:
    - node
id: node.field_price
field_name: field_price
entity_type: node
type: integer
settings:
  unsigned: false
  size: normal
module: core
locked: false
cardinality: 1
translatable: true
indexes: {  }
persist_with_no_fields: false
custom_storage: false

Also I created FieldFormatter and FieldWidget. (I am not sure if properly.)

What I found out is the module is creating the field Price. If I go to /admin/structure/types/manage/article/display, I see my price there, but it is under Disabled.

enter image description here

I feel I'm so close, but at the same time so lost.

What am I missing in order to make that field go active?

3
  • Would hook_entity_type_alter do what you need? As it's name implies, this hook allows you to alter the definition of an existing entity type. Commented Dec 20, 2016 at 11:02
  • 1
    If you found a solultion yourself please add it in an answer and mark it accepted. This will help others to find the solution as well and to see that this question got solved sufficiently. Please don't incorporate the answer into the question.
    – leymannx
    Commented Dec 30, 2016 at 6:55
  • Got it working by using a core.entity_form_display.node.<modulename>.default.yml file with following content: Commented Aug 9, 2017 at 6:23

4 Answers 4

7

For a beginner I'ld recommend to use Drupal's convenient user interface in the back-end. Create an admin user, log in, start adding fields, change display, reorder – all done by clicking through the interface.

For example you can add custom fields to the existing Article content type at https://example.com/admin/structure/types/manage/article/fields. There's is a button Add fields. Click it and explore. There is no difference in adding fields to a built-in content type.

As others said before YML are for configuration export and import, when deploying a site. As you would do as an advanced developer: You'ld have that page locally on your computer, add some fields by clicking through the back-end, export their config, push that to a Git repo, and then on your live page, pull from your repository, import the config files and get the same fields there without the need to click anything again.


Adding fields from a custom module can be achieved by providing certain YML in your modules /config/install folder. There as well is no difference between built-in content types or custom content types. It is described pretty good on DO at https://www.drupal.org/docs/8/api/entity-api/programming-custom-fields-into-your-content-type. Except that you would have to change the naming and especially change the value of the bundle: car_brand (content type) you want your fields to get added to.

Apart from that, you may need to install and uninstall this module pretty often during development. Get used to drush commands, for example drush dre module_name to do that in Terminal/Console (you need to have installed the Devel module to use drush dre). For your own good, I hope you already work with a UNIX based OS (Linux or OSX). Maybe you always have a fresh database backup available you can re-import with drush sql-cli < database.sql when you want to start over during development.


Just for reference I paste the deleted answer code here OP originally had put in his question. To finally make the fields available in the content type OP came up with this. I strongly guess he had put this into the module's *.install file calling hook_install() or hook_update_N(). Possibly deprecated functions, but I think you'll get the idea.

$entity_type         = 'node';
$bundle              = 'article';
$field['field_name'] = 'field_price'; // your field id

entity_get_form_display($entity_type, $bundle, 'default')
  ->setComponent($field['field_name'], array())
  ->save();

entity_get_display($entity_type, $bundle, 'default')
  ->setComponent($field['field_name'], array())
  ->save();
6
  • 1
    thank you leymannx, but what i'm looking is to perform that without interaction, just installing my module, so indeed im looking a programmatically way to do that on my module. Is there a way? Commented Dec 20, 2016 at 12:06
  • @ManuelRodriguez Of course there is! I'll extend my answer.
    – leymannx
    Commented Dec 20, 2016 at 12:06
  • thanks a lot @leymannx that's the documentation i was following. I created the YML files on /config/install, and indeed the field is created, the problem is I don't know how to "extend" view and form display entities as they are not related to a custom node type (i can create them) otherwise they should be linked to pre-built node types and I cannot redefine those files (core.entity_form_display.node.article.default core.entity_view_display.node.article.default) since they already exist on the core. BTW, thanks for the drush tip :) Commented Dec 20, 2016 at 15:14
  • @ManuelRodriguez Thanks for your comment. That makes the question a lot clearer. Maybe you can include that last comment into your question.
    – leymannx
    Commented Dec 20, 2016 at 16:01
  • 2
    To use drush dre you need to install the Devel module drupal.org/project/devel Commented Dec 30, 2016 at 4:56
4

Drupal's config YML files are primarily meant for import/export, to make the configuration portable between instances of the same site and to allow version control. They are not really intended as a development tool and I would never recommend writing them by hand, not even when you're an experienced Drupal developer.

Regardless of how a node type was defined, you should be able to add fields to them through the admin UI. I recommend that you do it that way, and use the config export system (either in the admin UI or using Drush on the command line) to generate config YML's that contain all the necessary data.

3
  • 1
    Thanks for the answer, but in this case I want my module when installing to be able to create the fields into the nodes, I don't want the user to create the field, or manage the field himself. Is that possible? Commented Dec 20, 2016 at 10:44
  • Ah, I see. In that case I think YML isn't sufficient, because you need some logic to check that the node type exists, and the field does not. You probably need to implement hook_install in your module and programmatically add the field to the node. Here is a post describing how to do that, but I'm not adding it to my answer because I didn't test if it really works. Commented Dec 20, 2016 at 12:53
  • 3
    Having the fields in exported config is fine, nothing wrong with that IMHO. They have explicit dependencies and won't allow you to install if that node type isn't there. But you also need form/view display information, and those are stored per node type and view/form mode, so you can't just provide it as config, you need to add it as code with hook_install(). See drupal.stackexchange.com/questions/222260/… for example.
    – Berdir
    Commented Dec 20, 2016 at 20:33
3

Got it working by using a core.entity_form_display.node.<modulename>.default.yml file with following content:

langcode: en
status: true
dependencies:
config:
  - field.field.node.modulename.body
  - node.type.modulename
module:
  - link
id: node.modulename.default
targetEntityType: node
bundle: modulename
mode: default
content:
  body:
    label: hidden
    type: string_textarea
    weight: 4
    settings:
      rows: 5
      placeholder: ''
    third_party_settings: {  }
    region: content
hidden:
  created: true
  path: true
  promote: true
  sticky: true
  uid: true
  body: true
2

What @leymannx answer is missing is explanation of what can (and should) be shipped with a custom module and what cannot.

Field storage can and should be shipped with your module.

Field instance may be shipped with your module, but only as optional, as it would depend on other modules providing content types (unless your module provides both content type and fields in which case you may just provide in config/install). Btw, you may store these files either in this or other module - when enabled, Drupal will scan all config/optional dirs for all modules to pickup any relevant configuration. https://www.drupal.org/node/2453919

Entity form display cannot be shipped with your module. Moreover, if your module provides just a field, shipping entity form display for the whole entity would override existing configuration. Instead, your module must include implementation of hook_install() where fields will be altered for form display for all supported content types.

Entity view display should be treated the same way as entity form display.

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.