3

I have these entity types:

  • A node type: nodepage
  • A Paragraph type: pg_a
  • A Paragraph type: pg_b
  • A Paragraph type: pg_child

I have a content model which is:

nodepage
  ->field_a
    Referenced bundles: pg_a
      ->field_child
        Referenced bundles: pg_child
  ->field_b
    Referenced bundles: pg_b
      ->field_child
        Referenced bundles: pg_child

You can see that pg_a and pg_b both have a field called field_child which allows a reference to pg_child. This has great semantic meaning to the site architecture.

Now something I would like to do is form alter pg_child, but only when it is referenced from pg_a and not from pg_b.

In hook_field_widget_form_alter, where I think I should be doing my alters, I can do the following:

$field_definition = $context['items']->getFieldDefinition();

// Get the current field widget being built, eg `field_child_thing`.
$name = $field_definition->getName();

// Get the bundle, ie. `pg_child`
$targetBundle = $field_definition->getTargetBundle();

// Get the bundle that $targetBundle is attached to in this instance...
$instance = ???

I thought I could look further into the $context variable, but so far this has alluded me. The best candidate so far is #parents in the form, but when I only find a reference to field_child which is ambiguous.

I now suspect I can inject more $context from somewhere, maybe in the parent build.

3

In this scenario, we have field_caption being used in various places inside a cta paragraph. The business has asked to limit field_caption to 25 charaters, but only when it is being used in a node on an entity reference field called field_foo_cta.

First we add a #process callback to the widget based on whatever rule, by implementing hook_field_widget_form_alter:

function mymodule_field_widget_form_alter(&$element, FormStateInterface $form_state, &$context) {
  $field_definition = $context['items']->getFieldDefinition();

  if ($field_definition instanceof FieldConfig) {
    $config = $field_definition->id();
    list ($entity_type, $bundle, $field_name) = explode('.', $config);

    if ($entity_type == 'paragraph' && $field_name == 'field_caption') {
      $element['#process'][] = ['\Drupal\mymodule\BusinessRules', 'alterFieldCaption'];
    }

  }
}

Then we create a new class in src directory of the module.

namespace Drupal\mymodule;

class BusinessRules {

  public static function alterFieldCaption(array &$element, FormStateInterface &$form_state, array &$complete_form) {

    // Use whatever logic to target instances of `field_caption`.
    if (reset($element['#parents']) == 'field_foo_cta') {
      $element['value']['#maxlength'] = 25;
    }
    return $element;

  }

}

Thanks @larowlan for help on this.

  • 1
    This pointed me in the right direction, thanks a lot! – plocks Apr 2 at 14:00
0

I thought I could look further into the $context variable, but so far this has alluded me. The best candidate so far is #parents in the form, but when I only find a reference to field_child which is ambiguous.

Is the entity object available in $context? If not it may be inside $form_state somewhere.

Once you got the Paragraph entity you can get its parent using Paragraph::getParentEntity() and from there the type of the parent.

  • When the form is new, there is no existing object. – simesy Oct 3 '18 at 11:23

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.