Props with enum should handle empty string or NULL value

Created on 3 December 2024, 3 months ago

Problem/Motivation

With table component in USB, I have the following errors:

Drupal\Core\Render\Component\Exception\InvalidComponentException: [borders] NULL value found, but a string or an object is required. This may be because the property is empty instead of having data present. If possible fix the source data, use the |default() twig filter, or update the schema to allow multiple types./n[borders] Does not have a value in the enumeration ["bordered","borderless"]/n[responsive] NULL value found, but a string or an object is required. This may be because the property is empty instead of having data present. If possible fix the source data, use the |default() twig filter, or update the schema to allow multiple types./n[responsive] Does not have a value in the enumeration ["responsive","responsive-sm","responsive-md","responsive-lg","responsive-xl","responsive-xxl"] in Drupal\Core\Theme\Component\ComponentValidator->validateProps() (line 203 of core/lib/Drupal/Core/Theme/Component/ComponentValidator.php).

Note that I started to put a default value in header_color and footer_color props but I had the same problem.

Proposed resolution

It should be possible to inject an empty string or NULL value for presenter templates and not get an error.

Remaining tasks

Find a generic solution.

🐛 Bug report
Status

Active

Version

2.0

Component

Code

Created by

🇫🇷France Grimreaper France 🇫🇷

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Merge Requests

Comments & Activities

  • Issue created by @Grimreaper
  • 🇫🇷France just_like_good_vibes PARIS

    this was supposed to be properly handled in enum prop normalisation :)
    i guess it may not be totally the cass

  • 🇫🇷France pdureau Paris

    Can you take it Mikael?

  • 🇫🇷France just_like_good_vibes PARIS

    of course i will post the code :)

  • Pipeline finished with Failed
    3 months ago
    Total: 403s
    #358606
  • 🇫🇷France just_like_good_vibes PARIS

    i don't remember if it makes sense to indicate a default value in the json schema definition of a prop?
    by the way, the enum prop type normalization is giving a try to get the default enum value from the "default" when no value was selected.
    in the case which is submitted here, i just checked, and borders indicate no default.

    i have updated the code, with many bonus, including the management of minItems and maxItems, in the case of EnumList and EnumSet.
    please review

  • Pipeline finished with Failed
    3 months ago
    Total: 366s
    #358653
  • 🇫🇷France just_like_good_vibes PARIS

    some tests are failing, i will correct that

  • Pipeline finished with Canceled
    3 months ago
    Total: 74s
    #358715
  • Pipeline finished with Success
    3 months ago
    Total: 323s
    #358716
  • 🇫🇷France Grimreaper France 🇫🇷

    Hi,

    Thanks, it fixes the fatal error.

    But I have "Warning: Array to string conversion in Drupal\ui_patterns\Plugin\UiPatterns\PropType\EnumPropType::convertValueToEnumType() (line 55 of modules/contrib/ui_patterns/src/EnumTrait.php)."

  • 🇫🇷France just_like_good_vibes PARIS

    hum your warning, is strange, can i reproduce?
    it means an array has been passed to the convertValueToEnumType
    which means two options :
    - there is a little bug somewhere, an array is passed to the function but it should not. we could correct or add an additional check
    - you have a little bug somewhere, you inject an array in an enum value

  • Hello ,

    I applied the patch but this warning , is still displaying

    Warning: Array to string conversion in Drupal\ui_patterns\Plugin\UiPatterns\PropType\EnumPropType::convertValueToEnumType() (line 55 of modules/contrib/ui_patterns/src/EnumTrait.php)

  • 🇫🇷France just_like_good_vibes PARIS

    Hello, has someone a stacktrace please. it will help me accelerate the fix :)

  • 🇫🇷France Grimreaper France 🇫🇷

    Go on /filter/tips with UI Suite Bootstrap.

    4 times this message:

    Warning: Array to string conversion in Drupal\ui_patterns\Plugin\UiPatterns\PropType\EnumPropType::convertValueToEnumType() (line 55 of modules/contrib/ui_patterns/src/EnumTrait.php).
    Drupal\ui_patterns\Plugin\UiPatterns\PropType\EnumPropType::convertValueToEnumType() (Line: 82)
    Drupal\ui_patterns\Plugin\UiPatterns\PropType\EnumPropType::normalizeEnumValue() (Line: 50)
    Drupal\ui_patterns\Plugin\UiPatterns\PropType\EnumPropType::normalize() (Line: 135)
    Drupal\ui_patterns\Template\TwigExtension->normalizeProps() (Line: 44)
    __TwigTemplate_ac01da381f695b64e61edbe37177194b->doDisplay() (Line: 393)
    Twig\Template->yield() (Line: 349)
    Twig\Template->display() (Line: 364)
    Twig\Template->render() (Line: 35)
    Twig\TemplateWrapper->render() (Line: 1468)
    Twig\Extension\CoreExtension::include() (Line: 190)
    __TwigTemplate_c902dc39b27371fbbe38f115885cd968->doDisplay() (Line: 393)
    Twig\Template->yield() (Line: 349)
    Twig\Template->display() (Line: 364)
    Twig\Template->render() (Line: 35)
    Twig\TemplateWrapper->render() (Line: 33)
    twig_render_template() (Line: 348)
    Drupal\Core\Theme\ThemeManager->render() (Line: 491)
    Drupal\Core\Render\Renderer->doRender() (Line: 248)
    Drupal\Core\Render\Renderer->render() (Line: 455)
    Drupal\filter\Plugin\Filter\FilterHtml->tips() (Line: 342)
    _filter_tips() (Line: 30)
    Drupal\filter\Controller\FilterController->filterTips()
    call_user_func_array() (Line: 123)
    Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 638)
    Drupal\Core\Render\Renderer->executeInRenderContext() (Line: 121)
    Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext() (Line: 97)
    Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 181)
    Symfony\Component\HttpKernel\HttpKernel->handleRaw() (Line: 76)
    Symfony\Component\HttpKernel\HttpKernel->handle() (Line: 53)
    Drupal\Core\StackMiddleware\Session->handle() (Line: 48)
    Drupal\Core\StackMiddleware\KernelPreHandle->handle() (Line: 28)
    Drupal\Core\StackMiddleware\ContentLength->handle() (Line: 32)
    Drupal\big_pipe\StackMiddleware\ContentLength->handle() (Line: 106)
    Drupal\page_cache\StackMiddleware\PageCache->pass() (Line: 85)
    Drupal\page_cache\StackMiddleware\PageCache->handle() (Line: 48)
    Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle() (Line: 51)
    Drupal\Core\StackMiddleware\NegotiationMiddleware->handle() (Line: 36)
    Drupal\Core\StackMiddleware\AjaxPageState->handle() (Line: 51)
    Drupal\Core\StackMiddleware\StackedHttpKernel->handle() (Line: 741)
    Drupal\Core\DrupalKernel->handle() (Line: 19)
    require() (Line: 4)
    

    Maybe at this moment it is a presenter template problem.

  • Hello

    You can check the backtrace as well :

    Warning: Array to string conversion in Drupal\ui_patterns\Plugin\UiPatterns\PropType\EnumPropType::convertValueToEnumType() (line 55 of modules/contrib/ui_patterns/src/EnumTrait.php).
    Drupal\ui_patterns\Plugin\UiPatterns\PropType\EnumPropType::convertValueToEnumType() (Line: 82)
    Drupal\ui_patterns\Plugin\UiPatterns\PropType\EnumPropType::normalizeEnumValue() (Line: 50)
    Drupal\ui_patterns\Plugin\UiPatterns\PropType\EnumPropType::normalize() (Line: 135)
    Drupal\ui_patterns\Template\TwigExtension->normalizeProps() (Line: 44)
    __TwigTemplate_334574a22004c680180d4b985021aae5->doDisplay() (Line: 393)
    Twig\Template->yield() (Line: 133)
    __TwigTemplate_e86990e63ac9a8958177906e049b2989___1883007922->doDisplay() (Line: 393)
    Twig\Template->yield() (Line: 44)
    __TwigTemplate_e86990e63ac9a8958177906e049b2989->doDisplay() (Line: 393)
    Twig\Template->yield() (Line: 349)
    Twig\Template->display() (Line: 364)
    Twig\Template->render() (Line: 35)
    Twig\TemplateWrapper->render() (Line: 234)
    Drupal\Core\Template\TwigEnvironment->renderInline() (Line: 54)
    Drupal\Core\Render\Element\InlineTemplate::preRenderInlineTemplate()
    call_user_func_array() (Line: 113)
    Drupal\Core\Render\Renderer->doTrustedCallback() (Line: 870)
    Drupal\Core\Render\Renderer->doCallback() (Line: 432)
    Drupal\Core\Render\Renderer->doRender() (Line: 504)
    Drupal\Core\Render\Renderer->doRender() (Line: 248)
    Drupal\Core\Render\Renderer->render() (Line: 484)
    Drupal\Core\Template\TwigExtension->escapeFilter() (Line: 350)
    __TwigTemplate_5fe55ef133dd49a36129acb810c34267->doDisplay() (Line: 393)
    Twig\Template->yield() (Line: 132)
    __TwigTemplate_68497508b486f09be9d402a27922d59c___966479196->doDisplay() (Line: 393)
    Twig\Template->yield() (Line: 44)
    __TwigTemplate_68497508b486f09be9d402a27922d59c->doDisplay() (Line: 393)
    Twig\Template->yield() (Line: 349)
    Twig\Template->display() (Line: 364)
    Twig\Template->render() (Line: 35)
    Twig\TemplateWrapper->render() (Line: 234)
    Drupal\Core\Template\TwigEnvironment->renderInline() (Line: 54)
    Drupal\Core\Render\Element\InlineTemplate::preRenderInlineTemplate()
    call_user_func_array() (Line: 113)
    Drupal\Core\Render\Renderer->doTrustedCallback() (Line: 870)
    Drupal\Core\Render\Renderer->doCallback() (Line: 432)
    Drupal\Core\Render\Renderer->doRender() (Line: 504)
    Drupal\Core\Render\Renderer->doRender() (Line: 248)
    Drupal\Core\Render\Renderer->render() (Line: 484)
    Drupal\Core\Template\TwigExtension->escapeFilter() (Line: 70)
    __TwigTemplate_470d9e9f567b87d05f0942f00dd67993->doDisplay() (Line: 393)
    Twig\Template->yield() (Line: 134)
    __TwigTemplate_530ee8b86764a8d9fd757aae145ed775___2102825069->doDisplay() (Line: 393)
    Twig\Template->yield() (Line: 44)
    __TwigTemplate_530ee8b86764a8d9fd757aae145ed775->doDisplay() (Line: 393)
    Twig\Template->yield() (Line: 349)
    Twig\Template->display() (Line: 364)
    Twig\Template->render() (Line: 35)
    Twig\TemplateWrapper->render() (Line: 234)
    Drupal\Core\Template\TwigEnvironment->renderInline() (Line: 54)
    Drupal\Core\Render\Element\InlineTemplate::preRenderInlineTemplate()
    call_user_func_array() (Line: 113)
    Drupal\Core\Render\Renderer->doTrustedCallback() (Line: 870)
    Drupal\Core\Render\Renderer->doCallback() (Line: 432)
    Drupal\Core\Render\Renderer->doRender() (Line: 504)
    Drupal\Core\Render\Renderer->doRender() (Line: 248)
    Drupal\Core\Render\Renderer->render() (Line: 484)
    Drupal\Core\Template\TwigExtension->escapeFilter() (Line: 100)
    __TwigTemplate_09bf4e6a13e892c19452995ad4dfe69a->doDisplay() (Line: 393)
    Twig\Template->yield() (Line: 131)
    __TwigTemplate_11050f9a6b3f273dd95417ba9ba45576___543805536->doDisplay() (Line: 393)
    Twig\Template->yield() (Line: 44)
    __TwigTemplate_11050f9a6b3f273dd95417ba9ba45576->doDisplay() (Line: 393)
    Twig\Template->yield() (Line: 349)
    Twig\Template->display() (Line: 364)
    Twig\Template->render() (Line: 35)
    Twig\TemplateWrapper->render() (Line: 234)
    Drupal\Core\Template\TwigEnvironment->renderInline() (Line: 54)
    Drupal\Core\Render\Element\InlineTemplate::preRenderInlineTemplate()
    call_user_func_array() (Line: 113)
    Drupal\Core\Render\Renderer->doTrustedCallback() (Line: 870)
    Drupal\Core\Render\Renderer->doCallback() (Line: 432)
    Drupal\Core\Render\Renderer->doRender() (Line: 504)
    Drupal\Core\Render\Renderer->doRender() (Line: 504)
    Drupal\Core\Render\Renderer->doRender() (Line: 248)
    Drupal\Core\Render\Renderer->render() (Line: 484)
    Drupal\Core\Template\TwigExtension->escapeFilter() (Line: 95)
    __TwigTemplate_fbf4573c412e03b9fa52d6676493a707->block_content() (Line: 437)
    Twig\Template->yieldBlock() (Line: 73)
    __TwigTemplate_fbf4573c412e03b9fa52d6676493a707->doDisplay() (Line: 393)
    Twig\Template->yield() (Line: 349)
    Twig\Template->display() (Line: 364)
    Twig\Template->render() (Line: 35)
    Twig\TemplateWrapper->render() (Line: 33)
    twig_render_template() (Line: 348)
    Drupal\Core\Theme\ThemeManager->render() (Line: 491)
    Drupal\Core\Render\Renderer->doRender() (Line: 504)
    Drupal\Core\Render\Renderer->doRender() (Line: 248)
    Drupal\Core\Render\Renderer->render() (Line: 484)
    Drupal\Core\Template\TwigExtension->escapeFilter() (Line: 77)
    __TwigTemplate_32116fbe2c68cf5d4b64c2c9dd5a4417->block_header() (Line: 437)
    Twig\Template->yieldBlock() (Line: 50)
    __TwigTemplate_32116fbe2c68cf5d4b64c2c9dd5a4417->doDisplay() (Line: 393)
    Twig\Template->yield() (Line: 349)
    Twig\Template->display() (Line: 364)
    Twig\Template->render() (Line: 35)
    Twig\TemplateWrapper->render() (Line: 33)
    twig_render_template() (Line: 348)
    Drupal\Core\Theme\ThemeManager->render() (Line: 491)
    Drupal\Core\Render\Renderer->doRender() (Line: 248)
    Drupal\Core\Render\Renderer->render() (Line: 484)
    Drupal\Core\Template\TwigExtension->escapeFilter() (Line: 87)
    __TwigTemplate_cd925203836eab760af9154fdf9e5f81->doDisplay() (Line: 393)
    Twig\Template->yield() (Line: 349)
    Twig\Template->display() (Line: 364)
    Twig\Template->render() (Line: 35)
    Twig\TemplateWrapper->render() (Line: 33)
    twig_render_template() (Line: 348)
    Drupal\Core\Theme\ThemeManager->render() (Line: 491)
    Drupal\Core\Render\Renderer->doRender() (Line: 248)
    Drupal\Core\Render\Renderer->render() (Line: 158)
    Drupal\Core\Render\MainContent\HtmlRenderer->Drupal\Core\Render\MainContent\{closure}() (Line: 638)
    Drupal\Core\Render\Renderer->executeInRenderContext() (Line: 153)
    Drupal\Core\Render\MainContent\HtmlRenderer->renderResponse() (Line: 90)
    Drupal\Core\EventSubscriber\MainContentViewSubscriber->onViewRenderArray()
    call_user_func() (Line: 111)
    Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch() (Line: 186)
    Symfony\Component\HttpKernel\HttpKernel->handleRaw() (Line: 76)
    Symfony\Component\HttpKernel\HttpKernel->handle() (Line: 53)
    Drupal\Core\StackMiddleware\Session->handle() (Line: 48)
    Drupal\Core\StackMiddleware\KernelPreHandle->handle() (Line: 28)
    Drupal\Core\StackMiddleware\ContentLength->handle() (Line: 32)
    Drupal\big_pipe\StackMiddleware\ContentLength->handle() (Line: 106)
    Drupal\page_cache\StackMiddleware\PageCache->pass() (Line: 85)
    Drupal\page_cache\StackMiddleware\PageCache->handle() (Line: 50)
    Drupal\ban\BanMiddleware->handle() (Line: 48)
    Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle() (Line: 51)
    Drupal\Core\StackMiddleware\NegotiationMiddleware->handle() (Line: 36)
    Drupal\Core\StackMiddleware\AjaxPageState->handle() (Line: 51)
    Drupal\Core\StackMiddleware\StackedHttpKernel->handle() (Line: 741)
    Drupal\Core\DrupalKernel->handle() (Line: 19)

  • 🇫🇷France just_like_good_vibes PARIS

    thanks.
    I wonder if, the prop is a simple enum, but the value injected is an array...

    on that case :
    - is the prop supposed to be a list of enum?
    OR
    - is the value supposed to scalar instead of a table

  • 🇫🇷France just_like_good_vibes PARIS

    i just added a new test to avoid the warning, but it won't solve your problem of an array being injected instead of a scalar..

  • Pipeline finished with Success
    3 months ago
    Total: 330s
    #359219
  • 🇫🇷France pdureau Paris

    Indeed, EnumPropType is a scale prop type.

  • 🇫🇷France just_like_good_vibes PARIS

    ready for review (and merge :) )

  • Pipeline finished with Success
    3 months ago
    Total: 334s
    #359336
  • Pipeline finished with Skipped
    3 months ago
    #359604
  • Pipeline finished with Skipped
    3 months ago
    #359605
  • 🇫🇷France Grimreaper France 🇫🇷

    Hi,

    Don't know if related but now I have:

    Drupal\Core\Render\Component\Exception\InvalidComponentDataException: Unable to render component "ui_suite_bootstrap:alert". A render array or a scalar is expected for the slot "heading" when using the render element with the "#slots" property in Drupal\Core\Render\Element\ComponentElement->generateComponentTemplate() (line 118 of core/lib/Drupal/Core/Render/Element/ComponentElement.php).
    

    When on the components library

  • Pipeline finished with Failed
    3 months ago
    Total: 40s
    #360199
  • Pipeline finished with Failed
    3 months ago
    Total: 44s
    #360233
  • Pipeline finished with Failed
    3 months ago
    Total: 45s
    #360238
  • Pipeline finished with Failed
    3 months ago
    Total: 373s
    #360235
  • Pipeline finished with Failed
    3 months ago
    Total: 33s
    #360266
  • Pipeline finished with Failed
    3 months ago
    Total: 53s
    #360270
  • Merge request !286Resolve #3491369 "Fix suite" → (Closed) created by just_like_good_vibes
  • 🇫🇷France Grimreaper France 🇫🇷

    Bug aside.

    // If a type is defined, return the first enum value.

    I don't think getting the first enum value is a solution.

    I want the prop to remain optional, so without value.

  • Pipeline finished with Canceled
    3 months ago
    Total: 2127s
    #360304
  • Pipeline finished with Failed
    3 months ago
    Total: 514s
    #360345
  • Pipeline finished with Failed
    3 months ago
    Total: 642s
    #360359
  • 🇫🇷France just_like_good_vibes PARIS

    "I want the prop to remain optional, so without value."
    for this, it is a bit more tricky to do.
    if you prop is of type "string", and you don't declare any "default",
    and you still want an empty string as default :) ?

    is empty string a possible enum value ?
    and also i would rather put empty string as default...
    because sometimes enum could have different types, mixed types..etc

    i am curious about what Pierre thinks about that. maybe i am completly wrong in my approach.

  • 🇫🇷France Grimreaper France 🇫🇷

    Empty string is ok in the case of a string type, I have discussed with Pierre about that yesterday or tuesday.

    We just don't want to have to declare an empty enum value at each enum.

    But like you said let's wait to get Pierre's feedback.

  • 🇫🇷France Grimreaper France 🇫🇷
  • 🇫🇷France Grimreaper France 🇫🇷
  • Pipeline finished with Canceled
    3 months ago
    Total: 971s
    #360373
  • Pipeline finished with Success
    3 months ago
    Total: 1475s
    #360386
  • 🇫🇷France just_like_good_vibes PARIS

    yes we need to figure out the options.

    First, how things are declared using SDC, in json schema

    - type
    - required
    - default

    The current code in normalize is trying to get the "default", like this :

    return static::normalizeEnumValue($value, $enum) ?? static::enumDefaultValue($definition);
    

    We are discussing the possibilities of changing the enumDefaultValue returned.

    when there is not "default" declared in json schema, and when the type is explicitely defined (and would be further checked by SDC)
    we indeed return the first enum value.
    Perhaps we could refine this :
    - if required is defined and true in the definition, we returned the first enum value (and not empty string)
    - otherwise : depending on the type, we try to return a default 'empty' value .
    -- type can be an array or a scalar if i am not wrong. when string is a compatible type, we return empty string,
    -- otherwise, what do we return ? first enum value?

    one again, we are in an edge case, where :
    - the definition has not indicated a default value,
    - the value passed is not part of the enum declared
    - the enum is explicitely typed and the value will be validated.
    - we try to guess a default valid value to avoid a failed validation, and the first enum is not good.

    in the case of enum of type string, when declared without required, one would expect that it means optional with default value being empty string.

  • 🇫🇷France just_like_good_vibes PARIS

    I just submitted the new proposition.
    When no default value is defined for an enum :
    - if enum has type compatible with string, and if not required, the default value is now empty string
    - otherwise default value is first enum value

  • Pipeline finished with Success
    3 months ago
    Total: 325s
    #360507
  • Pipeline finished with Failed
    3 months ago
    Total: 931s
    #361249
  • Pipeline finished with Success
    3 months ago
    Total: 12326s
    #361268
  • Pipeline finished with Canceled
    2 months ago
    Total: 98s
    #370875
  • Pipeline finished with Success
    2 months ago
    Total: 176s
    #370878
Production build 0.71.5 2024