Problem/Motivation

We are planning to rewrite UI Patterns upon SDC. To achieve this, we are proposing a few changes and additions:


Today, #slots property of ComponentElement accepts only render arrays.

If something else is send, there is a fatal error:

Unable to render component "%s". A render array is expected for the slot "%s" when using the render element with the "#slots" property

We believe such a strong behaviour and expected verbosity don't fit with developers expectations and may hurt SDC adoption.

Steps to reproduce

When using component render element, instead of doing this:

[
     '#type' => 'component',
    '#component' => 'ui_patterns_test:close_button',
    '#slots' => [
       "foo" => [
           "#plain_text" => "Bar",
       ]
   ],
    '#props' => []
];

Do that:

[
    '#type' => 'component',
    '#component' => 'ui_patterns_test:close_button',
    '#slots' => [
      'foo' => "Bar",
    ],
    '#props' => []
];

Proposed resolution

More or less something like that:

@@ -105,13 +105,10 @@ class ComponentElement extends RenderElement {
     $template .= sprintf('{%% embed \'%s\' %%}', $id);
     $template .= PHP_EOL;
     foreach ($slots as $slot_name => $slot_value) {
-      if (!Utilities::isRenderArray($slot_value)) {
-        $message = sprintf(
-          'Unable to render component "%s". A render array is expected for the slot "%s" when using the render element with the "#slots" property',
-          $id,
-          $slot_name
-        );
-        throw new InvalidComponentDataException($message);
+      if (!Utilities::isRenderArray($slot_value) && \is_scalar($slot_value)) {
+        $slot_value = [
+          "#plain_text" => (string) $slot_value,
+        ];
       }
       $context[$slot_name] = array_reduce(
         $slots_alter_callbacks,

With update of related tests.

Remaining tasks

If there is a chance for this change to be accepted, we (UI Patterns team) can propose a merge request soon.

We have one month before the release of Drupal 10.2.0-alpha1.

API changes

It seems safe. Nothing breaking.

Issue fork drupal-3391702

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:

Comments

pdureau created an issue. See original summary.

g4mbini’s picture

Issue summary: View changes
idiaz.roncero’s picture

+1

e0ipso’s picture

I think this is in line with the Robustness Principle, and I am in favor.

What happens if a non-string scalar is passed? Do we trigger the error then, do we cast it to a string, or do we find an appropriate render array to use for each scenario?

pdureau’s picture

What happens if a non-string scalar is passed? Do we trigger the error then, do we cast it to a string, or do we find an appropriate render array to use for each scenario?

Let's raise the InvalidComponentDataException you are currently raising.

pdureau’s picture

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

pdureau’s picture

Before doing any modifications, I got some failures from module's tests:

1) Drupal\Tests\sdc\Kernel\ComponentRenderInvalidTest::testInvalidDefinitionModule
Failed asserting that exception of type "Drupal\sdc\Exception\InvalidComponentException" is thrown.
2) Drupal\Tests\sdc\Kernel\ComponentRenderInvalidTest::testInvalidDefinitionTheme
Failed asserting that exception of type "Drupal\sdc\Exception\InvalidComponentException" is thrown.

Maybe I did something wrong while setting up my phpunit test environement.

Those failures will stay after my modification, so I hope I will not miss a test case.

pdureau’s picture

Status: Active » Needs review

Hi Mateu,

Here is the merge request: https://git.drupalcode.org/project/drupal/-/merge_requests/5044

I have also updated the checkInvalidSlot test:

       '#slots' => [
-        'banner_body' => 'I am an invalid render array.',
+        'banner_body' => new stdClass(),
       ],

I wanted to use a PHP array which is not a render array instead of stdClass() . However, it seems Utilities::isRenderArray() is returning TRUE for any array, not only render array. Am I right? If yes, do we need to fix this too?

smustgrave’s picture

Status: Needs review » Needs work

CC failure in MR

Have not tested.

pdureau’s picture

Status: Needs work » Needs review
smustgrave’s picture

Status: Needs review » Reviewed & tested by the community

Rebased to run test-only feature

There was 1 failure:
1) Drupal\Tests\sdc\Kernel\ComponentRenderTest::testRender
Failed asserting that exception message 'Unable to render component "sdc_test:my-banner". A render array is expected for the slot "banner_body" when using the render element with the "#slots" property' contains 'Unable to render component "sdc_test:my-banner". A render array or a scalar is expected for the slot "banner_body" when using the render element with the "#slots" property'.
/builds/issue/drupal-3391702/vendor/phpunit/phpunit/src/Framework/Constraint/Constraint.php:122
/builds/issue/drupal-3391702/vendor/phpunit/phpunit/src/Framework/Constraint/Constraint.php:55
/builds/issue/drupal-3391702/vendor/phpunit/phpunit/src/Framework/TestResult.php:728
FAILURES!
Tests: 2, Assertions: 26, Failures: 1.

Which is good.

The change looks good and matches the proposed solution. Only question I have is even though SDC is experimental will it need a CR for the new way to pass things?

e0ipso’s picture

Agreed on the RTBC. I think this improves DX a bit.

Thanks for this!

lauriii made their first commit to this issue’s fork.

  • lauriii committed 76fac09c on 11.x
    Issue #3391702 by pdureau, smustgrave, e0ipso: SDC ComponentElement:...

  • lauriii committed 27097189 on 10.2.x
    Issue #3391702 by pdureau, smustgrave, e0ipso: SDC ComponentElement:...

  • lauriii committed 7c8c61a3 on 10.1.x
    Issue #3391702 by pdureau, smustgrave, e0ipso: SDC ComponentElement:...
lauriii’s picture

Version: 11.x-dev » 10.1.x-dev
Status: Reviewed & tested by the community » Fixed

Created a CR and committed 76fac09 and pushed to 11.x. Cherry-picked all the way to 10.1.x because SDC is experimental. Thanks!

Status: Fixed » Closed (fixed)

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