Problem/Motivation
Business Rules makes it possible to configure a dependency between two fields in a node, i.e.: when the "triggering" field changes, new options can be selected from the "target" because it is updated in an AJAX call.
As a site builder, I might want to set up a dependent field inside of a paragraph, whose widget is embedded in a node. It is currently possible to configure this; but it does not work. More specifically, no JavaScript is listening for the triggering field to change, which is different when the two fields are in the node itself.
Steps to reproduce
- Clone drupal, branch
8.9.x
- I was at commit485d2a305f
when I tried this. - Install Drupal using the
standard
install profile. - Download
dBug-2.0.0
,entity_reference_revisions-8.x-1.9
, andparagraphs-8.x-1.12
. - Clone business_rules, branch
2.x
- I was at commitbec01f4
when I tried this. - Create a vocabulary named
vocab1
. Add 2 terms, namedvocab1term1
andvocab1term2
. - Add a term reference field named
field_user_term1
to the user entity. Configure it to use theDefault
Reference method, and accept terms fromvocab1
. Configure the form display to show this field as aSelect list
instead of anAutocomplete
. - Add a view named
view1
that showsUsers
sorted byUnsorted
. Add anEntity Reference
display...- Edit Format -> Format -> Entity reference list -> Settings, and check
User: Name
inSearch fields
. - Add a contextual filter on field_user_term1. When the filter value is not available,
Display contents of "No results found"
. When the filter value is available or a default is provided, checkSpecify validation criteria
, set Validator toTaxonomy term ID
, and check Vocabularyvocab1
(leave the remaining fields at their default).
- Edit Format -> Format -> Entity reference list -> Settings, and check
- Create a paragraph type named
paratype1
...- Add a term reference field named
field_paratype1_termfield1
to the paragraph type. Configure it to use theDefault
Reference method, and accept terms fromvocab1
. Configure the form display to show this field as aSelect list
instead of anAutocomplete
. - Add a user reference field named
field_paratype1_user1
to the paragraph type. Configure it to use theBusiness Rules: Make field dependent using views
. Set View used to select the entities toview1 - Entity Reference
and the Parent field toEntity reference: paratype1_termfield1 [field_paratype_termfield1]
(leave the remaining fields at their default). Configure the form display to show this field as aSelect list
instead of anAutocomplete
.
- Add a term reference field named
- Create a content type named
nodetype1
. Add a paragraph reference field namedfield_nodetype1_parafield1
. - Create four users:
user1
anduser3
referencingvocab1term1
; anduser2
anduser4
referencingvocab1term2
. - Go to
/node/add/nodetype1
. You see thenodetype1_parafield1
field, with an emptyparatype1
in it. You see the triggeringparatype1_termfield1
field containingvocab1term1
andvocab1term2
, and the targetparatype1_user1
field, which is empty. - Select
vocab1term1
fromparatype1_termfield1
.- Expected behavior:
paratype1_user1
changes to containuser1
anduser3
- Actual behavior: nothing happens
- Expected behavior:
- Select
vocab1term2
fromparatype1_termfield1
- Expected behavior:
paratype1_user1
changes to containuser2
anduser4
- Actual behavior: nothing happens
- Expected behavior:
... note that after applying the patch in #29, an AJAX spinner appears after changing the value of paratype1_termfield1
, but paratype1_user1
remains empty.
Proposed resolution
Modify src/Plugin/EntityReferenceSelection/BusinessRulesViewsSelection.php
and js/update-options-command.js
to identify and properly handle subforms.
Remaining tasks
Document a test caseFix test failures in the branchWrite a working patch- Review and feedback
- RTBC and feedback
- Commit
- Release
User interface changes
None.
API changes
- A required boolean
$multiple
parameter has been added to the signature of\Drupal\business_rules\Ajax\UpdateOptionsCommand::__construct()
Data model changes
None.
Original report by @lucius_nick
Following the guidelines in https://www.drupal.org/docs/8/modules/business-rules/advanced-usage/depe... I have created a dependent field in a paragraph.
The business rule works if I save the paragraph but changing the parent field does not trigger ajax.
Comment | File | Size | Author |
---|---|---|---|
#42 | 3040253-41.patch | 47.01 KB | mparker17 |
Comments
Comment #2
C.E.A CreditAttribution: C.E.A commentedCan you please elaborate with any logging errors for this issue ?
Copy and paste the error here please
Comment #3
lucius_nick CreditAttribution: lucius_nick commentedHi, we would like to elaborate but we have no errors, I'm sorry. It seems like the the ajax doesn't get attached to the paragraph at all. Maybe the patch supplied in https://www.drupal.org/project/business_rules/issues/2973571 will solve it. I don't have the time to check it right now. I will try to find some time this week so I can try and apply that patch.
Comment #4
C.E.A CreditAttribution: C.E.A commentedSure!
Also please try to download the last dev release for testing because the beta 6 has been known will plenty issues already fixed in the latest dev release.
Comment #5
gun_dose CreditAttribution: gun_dose at WBX Development commentedI encountered the same problem. There are no errors in logs, but module does not works with paragraphs: just nothing happens and fields are independent. I dig into this problem and made some changes:
1. First of all remove usage on 'Entity' class from .module file, because this class is deprecated and condition
will never fires, because this class is not used now. (Proof)
And this was the reason why there are no errors in log.
2. When we deal with inline forms, we should check if field has parents or not. And we should use field definition from entity associated with subform.
3. When update selects, we should remember that ID's could be changed by AJAX, so we should get elements by 'data-drupal-selector' selector attribute instead of 'id'.
4. Also when field is multiple, but select is empty, it will be rendered as single-value select, so we should change this in according to field cardinality settings. This is the reason why I changed 'UpdateOptionsCommand' class.
And here is a patch, that allows to work with paragraphs. May this needs some work to work with another nested entities, but now it works well with Paragraphs.
Comment #6
gargsuchi CreditAttribution: gargsuchi at Salsa Digital for govCMS (Australian Government Department of Finance) commentedThis patch worked perfectly for me! Thanks @gun_dose.
Comment #7
gun_dose CreditAttribution: gun_dose at WBX Development commentedSorry, I found one bug in my patch - it works good for new entities, but when edit existing entity, it causes validation error for dependent field in paragraph. I fixed it and here is new patch.
Comment #8
Kris77 CreditAttribution: Kris77 commentedThe patch in #7 works great!
Thanks @gun_dose.
Comment #9
colanThanks for working on this. Here's a code review:
There's a lot of nesting here. Can we maybe move this code into one or more (protected?) methods with descriptive names? It would help make the code cleaner as it's unreadable currently.
Extra line of whitespace here.
Typo in "miltiple".
I think it would be best to create a new method for this stuff so the current one doesn't get too big. Maybe something like
extractValueFromNestedEntities()
?Comment #10
el1_1el CreditAttribution: el1_1el commentedpatch in 7 did not apply to beta8 or dev. reroll
Comment #11
pieterjandp CreditAttribution: pieterjandp at Ghent University commentedPatch 10 does not work for nested paragraphs. This patch fixes that problem.
Comment #12
pieterjandp CreditAttribution: pieterjandp at Ghent University commentedComment #13
colanPlease include the missing interdiff. Thanks.
Comment #14
pieterjandp CreditAttribution: pieterjandp at Ghent University commentedComment #15
colanComment #16
kevinkonsorr CreditAttribution: kevinkonsorr as a volunteer commentedPatch #11 is only kinda working for me (I am not sure if I am doing anything correctly..)
I am using beta10 of bussiness_rules and applying the patch via composer.json is not working. (Error says 'cannot apply patch [...]')
When I try applying it with phpStorm I notice that it is not able to process line 116 from the patch (
$subform = $form;
).I apply every other block fine and add
$subform = $form;
to the file manually, skip the block and everything works fine.Also I am not sure on how to use the interdiff – Maybe that is what I am doing wrong?
Tried to add the patch to composer.json like so like all my patches that work fine:
Comment #17
kevinkonsorr CreditAttribution: kevinkonsorr as a volunteer commentedComment #18
el1_1el CreditAttribution: el1_1el commentedPatch rerolled for beta10. Also linked to Multi-valued dependent child fields are not saved since that requires this patch.
Comment #19
MurzThanks for the patch, it also fixes problem with not working dependent fields in Inline Entity Form widgets, issue about this is #2992273: Dependent fields not working in Inline Entity Forms?
Comment #20
Megha_kundar CreditAttribution: Megha_kundar at Specbee commentedAs previous applied patch was failed to apply. Applying new updated patch.
Comment #21
Megha_kundar CreditAttribution: Megha_kundar at Specbee commentedComment #22
Marceldeb CreditAttribution: Marceldeb commentedI can confirm #21 solves a lot of 'ajax hassle' with this module. Before the patch i could not open forms in a modal (ajax would not work and javascript would throw an error).
After patch it works.
Thanks a lot!
Comment #23
Megha_kundar CreditAttribution: Megha_kundar at Specbee commentedComment #25
Megha_kundar CreditAttribution: Megha_kundar at Specbee commentedComment #26
Megha_kundar CreditAttribution: Megha_kundar at Specbee commentedComment #28
colanNew features go into HEAD, and can then be backported if there's interest.
And please don't forget about interdiffs.
Comment #29
Megha_kundar CreditAttribution: Megha_kundar at Specbee commentedHi colan,
Attaching interdiff from #23 to #26 and also ported patch #26 to 2.0.
Please review.
Comment #30
Megha_kundar CreditAttribution: Megha_kundar at Specbee commentedComment #31
colanIf folks are interested in fixing tests (see the test results "Waiting for branch to pass" above), which would help with moving this issue along, please help with #3187013: Error: Call to a member function prepare() on null after updating to Drupal 9.1.0 / PHP 7.4.11.
Comment #32
mparker17Updated the issue summary to conform to the issue template; and added steps to reproduce, i.e.: a manual test case.
Note that when I perform the manual test case after applying the patch in #29, an AJAX spinner appears after changing the value of
paratype1_termfield1
, butparatype1_user1
remains empty, so I'm marking this as "Needs work" - but feel free to disagree if the manual test case doesn't match yours (I based my manual test case on my client site's desired behavior, but it may be more complex than it needs to be).Comment #33
mparker17Ah! I figured out what was wrong by looking at the patch in #11... at some point, the line in
\Drupal\business_rules\Plugin\EntityReferenceSelection\BusinessRulesViewsSelection::updateDependentField
to set$subform
went missing.Here's a patch; reviews welcome.
Comment #34
mparker17Here's an initial attempt at codifying the test case in the issue summary into a FunctionalJavascript test. It was failing to find the values in the target field on my local for some reason - I suspect I'm not
$page->waitFor()i
ng properly - but I'll have to figure that out on Monday.***
On a related note, I found FunctionalJavascript tests to be failing with a
PHP Fatal error: Uncaught PDOException: SQLSTATE[42S02]: Base table or view not found: 1146 Table 'drupal8.testNNNNNNNNkey_value_expire' doesn't exist
My gut says
BusinessRulesProcessor::__destruct()
runs after PHPUnit has deleted the table. Commenting out the line that tries to modifykey_value_expire
fixes the issue...(EDIT: a code snippet used to be here, but was found to be a Really Bad Idea in #3187013-17: Error: Call to a member function prepare() on null after updating to Drupal 9.1.0 / PHP 7.4.11 so I've removed the code snippet for safety!)
... going to have to figure that one out on Monday too (and probably file another ticket to fix). The question is, why does that line exist and is it safe to delete? i.e.: will removing it cause
key_value_expire
to grow without constraints, like #2931611-11: Honeypot key value entries never expire (effectively)? 😱Comment #35
mparker17Okay; here's a patch with a passing test (once
$keyvalue->deleteAll();
is deleted/commented fromsrc/Util/BusinessRulesProcessor.php::__destruct()
- going to work on that next).Several things were wrong; mainly that I was creating users and trying to assign values for the wrong field name (field_user_term) due to a typo when I originally captured the configuration for the test module. I also switched to using
$this->assertSession()->assertWaitOnAjaxRequest();
instead of my ownwaitFor()
logic (which was hard to get correct). And I captured the user's form display and modified the form display for the node type to make it easier when you install the test module for manual testing.Reviews welcome.
Comment #36
mparker17Note that #3133687: Wrap keyvalue delete in BusinessRulesProcessor destruct includes a similar test; if that gets merged first, we should probably update this patch so the test itself and the test module says, essentially, "go look over there for a similar test that doesn't involve paragraphs" and vice-versa.
Comment #38
mparker17It was merged; so here's an updated patch.
Comment #40
mparker17The interdiff in the last comment got mangled because I hadn't rebased my old branch; sorry about that....
Comment #42
mparker17Turns out I also need to tell Testbot to install the paragraphs module in the test environment so it is ready for the tests that involve it.
Comment #45
mparker17Ah, yes, I'd forgotten about this... test_dependencies cannot be added in a patch...
From the documentation (emphasis mine)...
... so I daresay this is still cool, as it passes locally for me.
Comment #46
mparker17Marking as fixed as per @colan's commit.
Comment #48
calinh CreditAttribution: calinh commentedThis current topic is about the parent field inside the same paragraph with the dynamically dependent child field.
I am very interested to have the parent field outside the paragraph - directly inside a node - and the dynamically dependent child field to be inside the paragraph, together with other normal fields.
Any idea on how this scenario can be solved? Using what other modules? Thank you.