Problem/Motivation
Even though it's really quite simple, it took me a while to understand how to setup a loop - I was looking for something more complex. I'm sharing my solution here in case it helps others.
On my site, user profiles have an entity reference field that points to taxonomy terms called "networks". A user can belong to an unlimited number of networks (currently there are about a dozen). When a user profile is updated, I wanted a model to check if there had been any changes to the networks the user had selected. If there have been changes, I wanted to take different actions based on additions and deletions.
For demonstration purposes, the end result displays a message for each addition, deletion or no change. The final product will be somewhat simplified - unnecessary actions will be removed as I don't care about no-changes, just additions and deletions. However, I included them as I was building my model to ensure I understood and checked each step.
Commentary
Sorry there are so many steps in my example. I wanted to provide an opportunity to review each event, condition and action so that details weren't missed. Module maintainers - you have a mind for elegant/simple solutions, feedback is welcome!
Example with Explanation
1. Starting event: Update Content Entity
- Type (and bundle) = user:user
2. Action: Entity Load
- Name of token » unchanged-user
- Load entity from » current scope (default value)
- Entity type » user
- Load unchanged values » yes
3. Condition: Compare two scalar values
- First value » [unchanged-user:field_user_networks]
- Comparison operator » equals
- Second value » [user:field_user_networks]
4. Action: Display a message to the user
- Message » No changes to networks
5. Condition: Compare two scalar values (same as step 3 but negated)
- First value » [unchanged-user:field_user_networks]
- Comparison operator » equals
- Second value » [user:field_user_networks]
- Negate the condition » Yes
6. Action: Entity - get field value "new"
- Field name » field_user_networks
- Name of token » new-networks
- Entity » User
7. Action: Entity - get field value "original"
- Field name » field_user_networks
- Name of token » orig-networks
- Entity » unchanged-user
8. Action: Trigger a custom event (entity aware) "additions"
- Event ID » additions
- Tokens to forward » orig-networks
- Entity » new-networks
9. Action: Trigger a custom event (entity aware) "deletions"
- Event ID » deletions
- Tokens to forward » new-networks *
- Entity » orig-networks *
- * Note reversal from previous step
10. Action: ECA Custom Event (entity-aware) "additions"
- Event ID » additions
11. Action: Entity Load (this is the current item from the list)
- Name of token » loaded-term
- Load entity from » Current scope (default value)
- Entity type » Taxonomy term
12. Condition: Compare two scalar values (does the list of original networks contain the current item?)
- First value » [orig-networks]
- Comparison operator » contains
- Second value » [loaded-term]
- Negate the condition » yes
13. Action: Display a message to the user (show the new item's name)
- Message » new item: [loaded-term:name]
14. Condition: Compare two scalar values (same as step 12 but not negated)
- First value » [orig-networks]
- Comparison operator » contains
- Second value » [loaded-term]
15. Action: Display a message to the user (show the existing item's name)
- Message » item exist already: [loaded-term:name]
16. Action: ECA Custom Event (entity-aware) "deletions"
- Event Id » deletions
17. Action: Entity Load (same as step 11, but in a different pathway)
- Name of token » loaded-term
- Load entity from » Current scope (default value)
- Entity type » Taxonomy term
18. Condition: compare two scalar values (check if the new list of networks contains the current item)
- First value » [new-networks]
- Comparison operator » contains
- Second value » [loaded-term]
- Negate the condition » yes
19. Action: Display a message to the user (show the deleted item's name)
- Message » deleted item: [loaded-term:name]
20. Condition: Compare two scalar values (same as step 18 but not negated)
- First value » [new-networks]
- Comparison operator » contains
- Second value » [loaded-term]
21. Action: Display a message to the user
- Message » item remains: [loaded-term:name]
22. Save and test your model!
- Save the model
- Edit a user
- Remove one item from their list of networks
- Add one item
- Save user
- Check the status message
Comment | File | Size | Author |
---|---|---|---|
eca-loop-22.jpg | 56.33 KB | btown | |
eca-loop-21.jpg | 351.98 KB | btown | |
eca-loop-20.jpg | 290.84 KB | btown | |
eca-loop-19.jpg | 351.88 KB | btown | |
eca-loop-18.jpg | 293.2 KB | btown |
Comments
Comment #2
btown CreditAttribution: btown commentedComment #3
jurgenhaasOh wow!!! @btown you're really mastering ECA and bpmn_io. Like I mentioned in #3317070: Help - comparing changes after updating user, this could be published to the ECA Guide library.
Comment #4
jurgenhaasCan we publish this on the ECA Guide?
Comment #5
rodmarasi CreditAttribution: rodmarasi commented@btown can i get the export file? image file cannot be exported to get better overview
Comment #6
jurgenhaasMoved this to the ECA Guide issue board: https://gitlab.lakedrops.com/drupal/documentation/eca/-/issues/25
Comment #7
jurgenhaasFYI, I have copied this great description over into our ECA Guide as a tutorial under https://ecaguide.org/resources/tutorials/btown-1/
I had to make smaller changes to it and then also built the model following the tutorial. That model is available for download from https://ecaguide.org/library/use%20case/user_network_changes/
Thanks a lot @btown for this amazing contribution!