2

Over the last few days I've been investigating and experimenting on how to use rules to alter fields within a paragraphs bundle on a node. The paragraph field on the node allows for multiple values(to a maximum of 6). In the paragraph bundle there is a radio button field where users select a "type" which then triggers the visibility of a corresponding field. The 'Conditional Fields' module has an option to 'reset to default value' when a dependency is not triggered, but this fails to work for me(needs a patch I believe). In place of that I am using rules to clean the form on submit. This worked perfectly with normal node fields, however it's not so simple when the fields I need to clean are inside a paragraph entity and there are multiple instances of the entity within the field.

In my experimentation I was able to reset the first and only the first paragraph bundle isntance with a data selector that looks like this:

node:field-paragraphs-categories:0:field-select-service

The problem here(I think) is that I'm selecting only the first 'row' in the paragraphs field thanks to the :0: in the data selector? I'm only guessing at the meaning of that number, the labeling of data selectors is cryptic to me.

Without that 0 or any of the other numbers(ex: 1,2,3) shown in the data selector options I can't even access the appropriate field I want to alter.

Screenshot of available data selectors

I figured that the right direction is to loop through the paragraphs field and select each 'row' individually and then, through the current list item of the loop, select the appropriate field to alter it that way but so far have been completely unsuccessful.

I believe I need a component(of type rule) and a standard rule to do this, right?

The rule:

Condition = Entity has field - Parameter: Entity: [node], Field: field_paragraphs_categories

Loop = node:field-paragraphs-categories & add component as an action

Action = Fetch entity by id - current-paragraph:item-id

The component(type rule):

Condition = Data comparison - current-paragraph:item-id(from loop):field-service-type

Action = Set a data value - current-paragraph:item-id(from loop):field-select-service

I can't seem to simply pass the id of the current item of the loop to the data comparison or action in the component so i can drill down to the fields it contains. This is where I'm getting stumped. Perhaps my entire method is wrong though, I don't know.

The closest instruction I've been able to find is in this thread https://www.drupal.org/node/1699712 @ #9 but, while similar, offers no insight into the parts I'm having difficulty with.

The short version of this support request is:

How do I loop through a paragraphs field with multiple values, set a data comparison condition on 'service-type', and then set a data value for 'select-service' if the condition evaluates to true.

CLARIFICATION:

In trying to add any data comparisons or actions such as "set a data value" I am unable to find a way to iterate over each row and then alter a field in that row like so:

First iteration = node:field-paragraphs-categories:0:field-select-service -> set value

Second iteration = node:field-paragraphs-categories:1:field-select-service -> set value

Third iteration = node:field-paragraphs-categories:2:field-select-service -> set value

fourth iteration = node:field-paragraphs-categories:3:field-select-service -> set value

And so on.

As far as I understand right now, without automatically looping through that index number I cannot set data values for fields inside "paragraphs-categories" unless I manually make a rule(or action within a rule) for each possible index number(0,1,2,3,4,5,etc).

Final Findings

After some further testing it appears that the issue is that paragraphs does not make the current list item fields available for manipulation within the loop(you can, however, access them for creating messages and maybe other actions). The field collection module DOES expose field collection fields in a rules loop and the refinements outlined by Pierre.Vriens work perfectly with that module instead.

1 Answer 1

2

Your question requires addressing multiple Rules issues, as further detailed below ...

1. You may not need a Rules Component

It seems you're familiar enough with using "Loops" in Rules, so that part is fine. But what you not seem to be aware of, is that you could use the Conditional Rules module to verify your condition like:

Condition = Data comparison - current-paragraph:item-id(from loop):field-service-type

By using this extra module, you don't need the additional Rules Component, and you have access to everything you need in the (single) rule itself.

2. Passing data to/from your Rules Component

However, using a Rules Component should be a valid alternative also. If that's what you prefer, then I suggest these refinements to your rule (and Rules Component):

  • Make sure to use 2 variables in your Rules Component (using "Parameter", not "Provided"!), defined like so:

    • 1st variable with data type that matches your current-paragraph:item-id(from loop):field-service-type. Say you call the variable V1.
    • 2nd variable with data type that matches your current-paragraph:item-id(from loop):field-select-service. Say you call the variable V2.
  • In your rule, when you invoke the Rules Component:

    • pass a data value for variable V1, which should be your current-paragraph:item-id(from loop):field-service-type.
    • pass a data value for variable V2, which should be your current-paragraph:item-id(from loop):field-select-service.
    • perform the Rules Condition and Rules Action, using the variables V1 and V2. I'm about sure that, after the Rules Component finished executing, the updated value for V2 will also be reflected in its corresponding current-paragraph:item-id(from loop):field-select-service in the Rules where you invoked the Rules Component. If it's not, then try to use "Provided" instead of "Parameter" for V2 (when defining the Rules Component).

3. Don't use 'Set a data value' to manipulate lists

The typical mistake in using Rules is that someone incorrectly uses a Rules Action like "Set a data value" (for a multi value field), which will remove all existing values for that field. The correct way is to use a Rules Action "Add to list" (for the new value to be used). This will preserve existing values. Refer to the List and loops video for more details about this.

However, for your scenario, you probably also need to use "Remove from list" (for the old value to be repaced).

PS: I'm assuming this question is about D7.

4
  • Hi Pierre, thanks for the response! I think the structure of the rule you've outlined is great, however there seems to be a deeper issue of being able to target fields within the paragraph item for setting a data value or reading a data value for a comparison. Sep 23, 2017 at 22:00
  • To further explain, it appears that I need to manually set the index of what row in the paragraph field I want to access(because its a multiple value field) before I can set a data value or compare a data value in my rule. Sep 23, 2017 at 22:12
  • @TheGruntler check my updated answer (item "3." I added). curious to hear if you can get it to work like that ... Sep 24, 2017 at 8:39
  • Hi again! Each paragraph item in list has 4 fields itself and I'm only trying to change 1 of those(field select service). So the issue with paragraphs seems to be that while I can loop through each item in the container field(field_paragraphs_categories) I cannot directly access the fields within each list item to change their values. Deleting the entire current-list-item of the loop(which is the paragraph item) and then recreating it to change 1 field would also mean recreating the values of the 3 other fields within it(which are not accessible to alter in the first place anyway) :( Sep 24, 2017 at 17:03

Your Answer

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

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