0

Changing entity base field settings

I have a custom car entity with 8 base fields like the following:

  $fields['color'] = BaseFieldDefinition::create('list_string')
    ->setLabel(t('Color'))
    ->setRequired(TRUE)
    ->setSettings([
      'allowed_values' => [
        'Blue' => 'Blue',
        'Green' => 'Green',
        'Red' => 'Red',
      ],
    ])
    ->setDisplayOptions('view', [
      'label' => 'inline',
      'type' => 'string',
      'weight' => 1,
    ])
    ->setDisplayOptions('form', [
      'type' => 'options_select',
      'weight' => 1,
    ])
    ->setDisplayConfigurable('form', TRUE)
    ->setDisplayConfigurable('view', TRUE);

I have a requirement to allow the end user to partially change some parts of some of the base fields like order and allowed values using custom simplified forms. I have the following code in the 'submitForm' function of a form.

  $field_definition = $this->entityDefinitionUpdateManager->getFieldStorageDefinition('color', 'car_module');
  $field_definition->setRequired(FALSE);
  $this->entityDefinitionUpdateManager->updateFieldStorageDefinition($field_definition);

When the 'Save' button is hit, the server takes a long time to respond like database changes are being made but the field definition does not get updated.

5
  • 1
    This is for update hooks after the code has changed. For changing entity base field settings depending on user input use BaseFieldOverride. See drupal.stackexchange.com/questions/253257/…
    – 4k4
    Dec 22 '20 at 15:52
  • @4k4 Your answer should allow me to change the 'allowed_values' setting for string lists so thank you for your help. I have also been trying to override the form and view display weight option for the entity but have not found a way to using BaseFieldOverride.
    – user320691
    Dec 23 '20 at 19:27
  • 1
    For form and view display options use EntityFormDisplay and EntityViewDisplay.
    – 4k4
    Dec 23 '20 at 19:40
  • 1
    See drupal.stackexchange.com/questions/212829/…
    – 4k4
    Dec 23 '20 at 19:49
  • @4k4 I've never worked with entities in depth. The entity I am working with is a vehicle content entity that does not support bundles similar in complexity to the one in the 'content_entity_example' sub-module of the 'Examples' module. Neither the entity nor any of its base fields are defined in 'config/install' YAML. Everything is defined in an entity class that extends 'ContentEntityBase'. I've tried the EntityViewDisplay load function as in the link you sent using various combinations of the entity ID and fields but nothing worked.
    – user320691
    Dec 24 '20 at 4:47
1

Base fields are defined in code. When code updates change the database schema you can implement the updates via entityDefinitionUpdateManager in an update hook as shown in the question. This is not possible in a form submit.

If you want to store field settings in a form submit load the field config and save it:

// if the entity type has no bundles use the entity type id:
$entity_type_id = 'vehicle';
$bundle = 'vehicle';

$fields = \Drupal::service('entity_field.manager')->getBaseFieldDefinitions($entity_type_id);
$field_config = $fields['field_example']->getConfig($bundle);
// make changes
$field_config->save();

For form and view display settings you can use EntityDisplayRepositoryInterface::getFormDisplay and EntityDisplayRepositoryInterface::getViewDisplay:

$display_repository = \Drupal::service('entity_display.repository');
$display = $display_repository->getViewDisplay($entity_type_id, $bundle, 'default');
$display->setComponent('field_example', $display_options);
$display->save();

For both code examples if there is no configuration stored yet it will be created.


Your question is about a custom form. Instead you could expose the core field admin UI by adding field_ui_base_route to your entity, even if you don't intend to use bundles or view modes. This works also for base fields marked as configurable. See How do I add a view mode to a simple custom entity?

5
  • I wish I could have used the core field admin UI. Unfortunately, it was deemed too complicated for the end users.
    – user320691
    Dec 26 '20 at 4:07
  • Thank you for your help. Your answer is correct. Saving the form display works but saving the view display throws the following exception: PluginNotFoundException: The "integer" plugin does not exist. Valid plugin IDs for Drupal\Core\Field\FormatterPluginManager are: address_zone_default, address_default...email_mailto, entity_reference_entity_id in Drupal\Core\Plugin\DefaultPluginManager->doGetDefinition() (line 53 of core/lib/Drupal/Component/Plugin/Discovery/DiscoveryTrait.php). I don't even know where to start debugging this one. Thanks again!
    – user320691
    Dec 26 '20 at 4:33
  • 1
    Use 'type' => 'number_integer' in the view display options of an integer field. There is no integer field formatter.
    – 4k4
    Dec 26 '20 at 8:12
  • That helped me over another hurdle. Thanks again. The last hurdle remaining is to allow end users the ability to enable/disable fields. Using the field config's 'disable' method doesn't hide disabled fields in the entity forms and views. Neither does using the EntityDisplayRepositoryInterface's 'setComponent' method to set 'region' => 'hidden'. Is it possible to enable/disable fields using field config and/or EntityDisplayRepositoryInterface so they won't appear in forms/views or will I have to use a form hook to prevent them from being displayed?
    – user320691
    Dec 29 '20 at 22:44
  • 1
    EntityDisplayInterface::removeComponent Sets a component to be hidden.
    – 4k4
    Dec 30 '20 at 0:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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