0

I've created an entity which has fields that users need to fill out. As part of that entity there is a reference field back to a content type 'food'.

The 'food' content type has it's own entity reference called 'sections'.

When a user selects a 'food', i want to dynamically add each 'section' as a title with a textarea box underneath which gets stored against the original entity.

Considered using paragraphs as the 'sections' but they need to be reusable on different 'food' nodes. Also checked the dynamic fields module but this doesn't look like it's well supported.

Fallback approach is going to be to programmatically create a field for each 'section' item as they are added, but with this we could end up with hundreds of fields.

Any ideas on how else this can be done programmatically?

1

Paragraphs is what you want. What you are describing is Paragraphs' exact use case. We use Paragraphs as a staple of our platform because of its re-usability.

Assigning an existing Paragraph to an Entity Reference Revisions field on a node is as simple as:

// Note that the value will be a nested array, even if cardinality is 1.
$node->get('field_food')>setValue([
  [
    'target_id' => $paragraph->id(),
    'target_revision_id' => $paragraph->getRevisionId(),
  ],
]);
$node->save();

// Another example: assigning multiple references to a single field.
$node->get('field_myfield')>setValue([
  [
    'target_id' => $paragraph1->id(),
    'target_revision_id' => $paragraph1->getRevisionId(),
  ],
  [
    'target_id' => $paragraph2->id(),
    'target_revision_id' => $paragraph2->getRevisionId(),
  ],
  [
    'target_id' => $paragraph3->id(),
    'target_revision_id' => $paragraph3->getRevisionId(),
  ],
]);
$node->save();

If you need to generate a paragraph programmatically, that is also easy:

// Note that I'm using the DIC for demonstration's sake.
// Be sure to use dependency injection and other best practices in your project.
$storage = \Drupal::entityTypeManager()->getStorage('paragraph');
$paragraph = $storage->create([
  'type' => 'food',
  'title' => 'A title',
  'field_a' => 'a value',
]);
$paragraph->save();

You can then assign this newly created paragraph to an Entity Reference Revisions field using the method I mentioned above.

5
  • Started going down the paragraphs route for storing each section at the end and was going to generate using a form_alter. Regarding your solution, how would an editor reuse a single paragraph item from 1 node to another, if for example there were multiple paragraph items added.
    – Key
    Dec 7 '20 at 17:01
  • I recommend installing Paragraphs and creating some sort of simple paragraph type, then add an Entity Reference Revisions field to your content type that points to your Paragraph type. I think that seeing it in action will answer most questions for you.
    – Beau
    Dec 7 '20 at 18:09
  • Had already tried adding simple paragraphs but then noticed reusable requires the Paragraphs Library module. Am investigating that to see if it works.
    – Key
    Dec 7 '20 at 18:44
  • To be clear, I think we might be thinking of "reuse" as two different things. In the context of your use case, we would be programmatically generating or retrieving paragraphs and then assigning them to a field. Since a Paragraph instance is a content entity, it is, by default, reusable, in that it can be (un-)(re-)assigned to any Entity Reference Revision field. On our platform, we don't actually use the Paragrahs Library module, but rather have a custom block type per Paragraph type. Each custom block type contains exactly one Entity Reference Revisions field for the target Paragrpah type.
    – Beau
    Dec 7 '20 at 19:01
  • Stuck to the original entity structure but have used paragraphs to create/store the dynamic textareas, your code creating multiple references worked perfectly.
    – Key
    Dec 17 '20 at 14:35

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