Problem/Motivation

$form['checkbox'] = [
  '#type' => 'checkbox',
  '#title' => t('Show link'),
];
$form['link'] = [
  '#type' => 'link',
  '#title' => t('Link to front page'),
  '#url' => Url::fromRoute('<front>'),
  '#states' => [
    'visible' => [
      ':input[data-drupal-selector=edit-checkbox]' => ['checked' => TRUE],
    ],
  ],
];

Expected output:
<a href="/" data-drupal-selector="edit-link" data-drupal-states="{&quot;visible&quot;:{&quot;:input[data-drupal-selector=edit-checkbox]&quot;:{&quot;checked&quot;:true}}}" id="edit-link">Link to front page</a>

Actual output:
<a href="/" data-drupal-selector="edit-link" id="edit-link">Link to front page</a>

This appears to be because \Drupal\Core\Render\Element\Link::preRenderLink moves the attributes into #options['attributes'], which would be fine... if drupal_process_states() (which adds the states to the element's #attributes) was invoked before pre_render callbacks were invoked in \Drupal\Core\Render\Renderer::doRender.

Proposed resolution

Move the invocation of drupal_process_states() before pre_render callbacks.
Update Render/Element/Link.php element adding support to js states.

Remaining tasks

none

User interface changes

None

API changes

None

Data model changes

None

Issue fork drupal-2820586

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

markcarver created an issue. See original summary.

markhalliwell’s picture

Issue summary: View changes
markhalliwell’s picture

Issue summary: View changes
markhalliwell’s picture

Issue summary: View changes
Status: Active » Needs review
Issue tags: +Needs tests
FileSize
1.64 KB
dawehner’s picture

Issue summary: View changes
Status: Needs review » Active
Issue tags: -Needs tests

Just an idea. Maybe add drupal_process_states to \Drupal\Core\Render\Element\Link::getInfo and drop #states at the end?
This technique allows render elements to provide the processing at the exact right position.

markhalliwell’s picture

Maybe add drupal_process_states to \Drupal\Core\Render\Element\Link::getInfo

If it were a \Drupal\Core\Render\Element\RenderElement::preRenderStates method, maybe. However, drupal_process_states is currently a procedural function; one that doesn't return the element which would be needed to be a #pre_render callback.

and drop #states at the end?

I'm not really sure what you mean here. This patch moves the invocation before the #pre_render callbacks are invoked because it needs to add the necessary data-drupal-states attribute before \Drupal\Core\Render\Element\Link::preRenderLink is invoked, which effectively ostracizes the #attributes array afterwards.

markhalliwell’s picture

It's also unfortunate and perhaps partially confusing that the name of the procedural function (due it's name in 7.x) is drupal_process_states.

It is really just a #pre_render type of modification. If it's going to get added to the element info, then it would need to be a #pre_render callback since it's currently executed in \Drupal\Core\Render\Renderer::doRender (always invoked) rather than a #process callback which would only ever be executed in \Drupal\Core\Form\FormBuilder::doBuildForm.

However, keep in mind that moving it to a #pre_render callback would require manually adding it to the getInfo array of an element as well. This would technically be a BC break since the current code will always check if #states exists (on any type based element or standalone render array).

markhalliwell’s picture

Status: Active » Needs review

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.0-alpha1 will be released the week of January 30, 2017, which means new developments and disruptive changes should now be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.0-alpha1 will be released the week of July 31, 2017, which means new developments and disruptive changes should now be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.0-alpha1 will be released the week of January 17, 2018, which means new developments and disruptive changes should now be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.6.x-dev » 8.7.x-dev

Drupal 8.6.0-alpha1 will be released the week of July 16, 2018, which means new developments and disruptive changes should now be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

ranjith_kumar_k_u’s picture

Re-rolled #4 for 9.3

Gauravvvv’s picture

re-roll patch #18, Attached interdiff for same.

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 10.1.x-dev

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

smustgrave’s picture

Status: Needs review » Needs work
Issue tags: +Needs Review Queue Initiative, +Needs tests

This issue is being reviewed by the kind folks in Slack, #needs-review-queue-initiative. We are working to keep the size of Needs Review queue [2700+ issues] to around 400 (1 month or less), following Review a patch or merge request as a guide.

This will need a test case to show the issue

Did not test patch yet.

joaopauloc.dev’s picture

Adding unit test for field links using states
Patch #19 didn't work with me, it was necessary to do a small fix in state.js, see changes interdiff file

joaopauloc.dev’s picture

Status: Needs work » Needs review
joaopauloc.dev’s picture

Issue tags: -Needs tests
smustgrave’s picture

Status: Needs review » Reviewed & tested by the community

Tested on Drupal 10.1.x with a standard install.
Picked a random module with a form, in this case admin_toolbar, and added


$form['checkbox'] = [
  '#type' => 'checkbox',
  '#title' => t('Show link'),
];
    $form['link'] = [
      '#type' => 'link',
      '#title' => t('Link to front page'),
      '#url' => Url::fromRoute('<front>'),
      '#states' => [
        'visible' => [
          ':input[data-drupal-selector=edit-checkbox]' => ['checked' => TRUE],
        ],
      ],
    ];

Verified the data-drupal-selector wasn't there and the link was appearing.
Applied the fix and the attribute was there and the link was hidden until I checked the box.

Good job with the tests!

Gauravvvv’s picture

Updating attribution

longwave’s picture

Status: Reviewed & tested by the community » Needs work
  1. +++ b/core/misc/states.js
    @@ -714,9 +714,15 @@
    +      // Check if target is a link.
    +      if (e.target.tagName === 'A') {
    

    This feels a bit too hardcoded, and the comment doesn't explain *why* we are doing this. Maybe we should add .js-form-item to the link itself when #states is used, then I think we could leave the JavaScript alone?

  2. +++ b/core/tests/Drupal/FunctionalJavascriptTests/Core/Form/JavascriptStatesTest.php
    @@ -103,11 +104,13 @@ protected function doCheckboxTriggerTests() {
    +    $this->assertFalse($link->isVisible());
    

    In #994360: #states cannot check/uncheck checkboxes elements we added a third round of tests in this method to ensure the state was correctly reset after unchecking the checkbox again; we should add the same check for this change.

myha’s picture

I made that work for 9.5 by add 'container' element and put states here. Link added inside 'container'.

joaopauloc.dev’s picture

Working on issues

joaopauloc.dev’s picture

Hello @longwave,
I added the third round validating the checkbox. Also, I updated the commend on state.js explaining better why we update the element.

I agree with you that's is too hard-coded. But at the same time, in this case, should be hard coded, because we need to check if the element is a link tag. What do you think if we keep it as it is but explain why we are doing this?

About your suggestions I think is a good idea, maybe we should have a new js class to state.js handle these cases instead of checking the element tag, in the future, we could have more elements using this feature by just adding this class. My only concern about this idea is the link state won't work out of the box, we should add a new class to the link form element. I guess that we can't use the already existing class(js-form-item, .js-form-submit, .js-form-wrapper) because the links are not wrapped by them.

Regards.

joaopauloc.dev’s picture

Status: Needs work » Needs review
smustgrave’s picture

Status: Needs review » Reviewed & tested by the community

Seems the points brought up in #29 have been addressed.

Version: 10.1.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

longwave’s picture

The comment for the A tag case needs rewording, but I'm not sure what to suggest.

joaopauloc.dev’s picture

Status: Needs work » Needs review
smustgrave’s picture

Status: Needs review » Reviewed & tested by the community

Change makes sense.

If the committer get to it first need to remove duplicate // from the states.js, but didn't think it was enough to hold up.

@joaopauloc.dev if you see this before the committer mind removing that please.

Thanks

joaopauloc.dev’s picture

Removed.
Thanks @smustgrave.

lauriii’s picture

Status: Reviewed & tested by the community » Needs review

Added comment to the MR

smustgrave’s picture

Status: Needs review » Reviewed & tested by the community

Left a comment back.

quietone’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: +Needs issue summary update

I'm triaging RTBC issues.

After reading the issue summary I wonderws if drupal_process_states, mentioned in the proposed resolution, was still in use. So, I searched and found and found that it was deprecated in 2019, #3000068: Deprecate drupal_process_states(). I am tagging for an issue summary update.

Reading the comments, I see that @lauriii has asked for a less risky solution. I think that warrants setting this back for work.

I am setting back to NW.

joaopauloc.dev’s picture

Issue summary: View changes

joaopauloc.dev’s picture

Status: Needs work » Needs review
  • New mr created from 11.x
  • Added support to js/state for links in Link element as @lauriii suggested
smustgrave’s picture

Status: Needs review » Reviewed & tested by the community
Issue tags: -Needs issue summary update

Removing summary update tag as that was done in #49

lauriii’s picture

Status: Reviewed & tested by the community » Needs work

Nice! The current approach looks less scary. I posted few comments on the MR but I think we're getting there

joaopauloc.dev’s picture

Status: Needs work » Needs review
smustgrave’s picture

Seemed to have some test failures so rerunning

smustgrave’s picture

Status: Needs review » Needs work

Have reran the tests a few times but seems something is breaking.

joaopauloc.dev’s picture

Status: Needs work » Needs review

Fixed the unit test that was failing.

smustgrave’s picture

Status: Needs review » Reviewed & tested by the community

Didn't see a test-only patch and the test-changes feature of gitlab is blocking me.

So ran locally without the changes to core/misc/states.js core/lib/Drupal/Core/Render/Element/Link.php

There was 1 failure:

1) Drupal\FunctionalJavascriptTests\Core\Form\JavascriptStatesTest::testJavascriptStates
Failed asserting that true is false.

/var/www/html/vendor/phpunit/phpunit/src/Framework/Constraint/Constraint.php:122
/var/www/html/vendor/phpunit/phpunit/src/Framework/Constraint/Constraint.php:55
/var/www/html/web/core/tests/Drupal/FunctionalJavascriptTests/Core/Form/JavascriptStatesTest.php:226
/var/www/html/web/core/tests/Drupal/FunctionalJavascriptTests/Core/Form/JavascriptStatesTest.php:65
/var/www/html/vendor/phpunit/phpunit/src/Framework/TestResult.php:728

Great!

So reviewing the change itself, shame we need specialty code for links in the states.js but confirmed it does work using the example in the IS.

All threads appear to be resolved.

Great work!

longwave’s picture

Status: Reviewed & tested by the community » Needs work

Added some comments about the comments.

joaopauloc.dev’s picture

Status: Needs work » Needs review

Comments fixed again.

smustgrave’s picture

Status: Needs review » Reviewed & tested by the community

Seems threads have been resolved.

Tested again following the IS.
Took that code snippet and added to the Performance Form.
States did not work, as both elements rendered.
Applied the MR and states work perfectly.

lauriii’s picture

Status: Reviewed & tested by the community » Fixed

Committed 9b3d27c and pushed to 11.x. Also cherry-picked to 10.2.x. Thanks!

  • lauriii committed 9b3d27c5 on 11.x
    Issue #2820586 by joaopauloc.dev, Gauravvvv, lauriii, ranjith_kumar_k_u...

  • lauriii committed 1f7edf7a on 10.2.x
    Issue #2820586 by joaopauloc.dev, Gauravvvv, lauriii, ranjith_kumar_k_u...

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.