Gracefully handle components in active development: ensure great DX
>>> [!note] Migrated issue <!-- Drupal.org comment --> <!-- Migrated from issue #3532514. --> Reported by: [heyyo](https://www.drupal.org/user/474388) Related to !196 !153 !223 !219 !205 !1299 >>> <h3 id="overview">Overview</h3> <p><em>Follow-up for <span class="drupalorg-gitlab-issue-link drupalorg-gitlab-link-wrapper"><a href="https://git.drupalcode.org/project/canvas/-/work_items/3470422" class="drupalorg-gitlab-link">https://git.drupalcode.org/project/canvas/-/work_items/3470422</a></span>.</em></p> <pre>&nbsp; /**<br>&nbsp;&nbsp; * Whether the logic powering this component is broken.<br>&nbsp;&nbsp; *<br>&nbsp;&nbsp; * Typical example: a developer is developing an SDC, and while developing is<br>&nbsp;&nbsp; * testing it in Canvas. They're even renaming the SDC. It'd be a terrible DX<br>&nbsp;&nbsp; * if this caused the associated Component config entity to switch to the<br>&nbsp;&nbsp; * fallback version.<br>&nbsp;&nbsp; *<br>&nbsp;&nbsp; * @see \Drupal\canvas\Entity\Component::getComponentSourcePluginId()<br>&nbsp;&nbsp; * @return bool<br>&nbsp;&nbsp; */<br>&nbsp; public function isBroken(): bool;</pre><p>&hellip; but there's more we could detect!</p> <p>Quoting <span class="drupalorg-gitlab-issue-link drupalorg-gitlab-link-wrapper"><a href="https://git.drupalcode.org/project/canvas/-/work_items/3470422" class="drupalorg-gitlab-link">https://git.drupalcode.org/project/canvas/-/work_items/3470422</a></span>:</p> <blockquote><h3>Out of scope: handle more breakage scenarios when developing components</h3> <p>There's <em>more</em> things that can <u>fundamentally</u> break a component instance though:</p> <ol> <li>&#9989; (<del>this</del> <em>that</em> issue) the underlying component disappeared from the <code>ComponentSource</code> (whether deleted or renamed) </li><li>&#10060; the set of <em>required</em> explicit inputs increased (SDC terminology: "props") &mdash; <em>decreasing is not a problem!</em> </li><li>&#10060; the set of <em>required</em> explicit inputs changed (SDC terminology: "props") aka a required explicit input was renamed </li><li>&#10060; the shape of an explicit input (SDC terminology: "props") changed, e.g. a <code>type: string</code> becoming a <code>type: integer</code> </li></ol> <p>&#9888;&#65039; Currently, there's also ways to break things in Canvas' UI that <u>are not fundamental</u>, such as passing an optional prop that either no longer exists or has been renamed. (That currently triggers the validation in <code>\Drupal\canvas\Plugin\Canvas\ComponentSource\GeneratedFieldExplicitInputUxComponentSourceBase::getDefaultStaticPropSource()</code> but arguably should not. See @heyyo's <span class="drupalorg-gitlab-issue-link project-issue-status-info project-issue-status-7"><a href="https://www.drupal.org/project/canvas/issues/3532514" title="Status: Closed (fixed)">#3532514: Gracefully handle components in active development: ensure great DX</a></span>.)</p> <p>(This may cause garbage values though, for that we have <span class="drupalorg-gitlab-issue-link drupalorg-gitlab-link-wrapper"><a href="https://git.drupalcode.org/project/canvas/-/work_items/3524401" class="drupalorg-gitlab-link">https://git.drupalcode.org/project/canvas/-/work_items/3524401</a></span>.) </p></blockquote> <p>This issue is about:</p> <ul> <li>fixing the 1 &#9888;&#65039; , which is what most comments on this issue have been about so far, see especially @heyyo's #18</li> <li>fixing the 3 &#10060;, the first 2 correspond to what @catch wrote in #6, the 3rd was not yet discussed here</li> </ul> <h3 id="proposed-resolution">Proposed resolution</h3> <ol> <li>&#9989; Track which explicit inputs <em>are required</em> in the versioned information in a <code>Component</code> config entity for: <ul> <li>&#9989; <code>GeneratedFieldExplicitInputUxComponentSourceBase</code>-based implementations (SDC + code components) &rarr;<br> <pre>diff --git a/config/schema/canvas.schema.yml b/config/schema/canvas.schema.yml<br>index 7c7c57ee6..e5aa02441 100644<br>--- a/config/schema/canvas.schema.yml<br>+++ b/config/schema/canvas.schema.yml<br>@@ -459,6 +459,9 @@ canvas.generated_field_explicit_input_ux:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sequence:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; type: mapping<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mapping:<br>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; required:<br>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; type: boolean<br>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; label: 'Required prop'<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; field_type:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; type: string<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; label: 'Default field type'</pre><p> &rarr; <a href="https://git.drupalcode.org/project/canvas/-/merge_requests/205">MR 205</a> </p> </li><li>&#9989; &hellip; which will require an update path &rarr; <a href="https://git.drupalcode.org/project/canvas/-/merge_requests/219">MR 219</a> </li><li>&#8505;&#65039; This also enables important future work: [3463996] and <span class="drupalorg-gitlab-issue-link drupalorg-gitlab-link-wrapper"><a href="https://git.drupalcode.org/project/canvas/-/work_items/3509115" class="drupalorg-gitlab-link">https://git.drupalcode.org/project/canvas/-/work_items/3509115</a></span>. </li></ul> </li><li>&#9989; Update <code>GeneratedFieldExplicitInputUxComponentSourceBase</code> to stop relying on the live code implementation (the underlying SDC or code component) whenever possible and rely on the <code>prop_field_definitions</code> in the <code>Component</code> config entity instead: <ol> <li>&#9989; <code>::buildComponentInstanceForm()</code> should stop calling <code>::getDefaultStaticPropSource(&hellip;, validate_prop_name: TRUE)</code> &mdash; pass <code>FALSE</code> instead. Consider only calling that if A) assertions are on (indicating a developer) and B) Twig developer mode is off (because it'd otherwise get in the way <em>while</em> developing the SDC!)<br> &rarr;ended up happening in <span class="drupalorg-gitlab-issue-link drupalorg-gitlab-link-wrapper"><a href="https://git.drupalcode.org/project/canvas/-/work_items/3470422" class="drupalorg-gitlab-link">https://git.drupalcode.org/project/canvas/-/work_items/3470422</a></span> </li><li>&#9989; Update <code>::buildComponentInstanceForm()</code> and <code>::getDefaultStaticPropSource()</code> to maximally rely on <code>prop_field_definitions</code> in the <code>Component</code> &mdash; which also means we're finally respecting the prop order defined in the SDC/code component! &#129395;<br> &rarr; <a href="https://git.drupalcode.org/project/canvas/-/merge_requests/196">MR 196</a> </li></ol> </li> <li>&#9989; Ensure that even an exception while constructing the render array for a component instance in <code>GeneratedFieldExplicitInputUxComponentSourceBase::renderComponent()</code> cannot trigger a PHP fatal error: wrap that also in the <code>RenderSafeComponentContainer</code>, specifically in <code>Component::normalizeForClientSide()</code>, this ensures that the list of available components to instantiate correctly at runtime reflects what is broken and not &rarr; <a href="https://git.drupalcode.org/project/canvas/-/merge_requests/196">MR 196</a> </li><li>&#128683; <del>Consider renaming: <code>::isValid()</code>?</del> &rarr; not stable-blocking, defer that to the overall goal of making the component source plugin API public &amp; stable in <span class="drupalorg-gitlab-issue-link drupalorg-gitlab-link-wrapper"><a href="https://git.drupalcode.org/project/canvas/-/work_items/3520484" class="drupalorg-gitlab-link">https://git.drupalcode.org/project/canvas/-/work_items/3520484</a></span>. </li></ol> <h3 id="ui-changes">User interface changes</h3> <p>Rather than just "Component is broken" in<br> <img src="https://www.drupal.org/files/issues/2025-09-26/Captura%20de%20pantalla%202025-09-26%20a%20las%2013.52.36.png">, when "verbose error logging" is enabled, you'd instead see something much more detailed/helpful, both inside Canvas and on the live site:<br> <img src="https://www.drupal.org/files/issues/2025-10-09/Screenshot%202025-10-09%20at%2023.01.51.png" alt="Screenshot"><br> <img src="https://www.drupal.org/files/issues/2025-10-09/Screenshot%202025-10-09%20at%2023.02.10.png" alt="Screenshot"></p> > Related issue: [Issue #3536277](https://www.drupal.org/node/3536277) > Related issue: [Issue #3523841](https://www.drupal.org/node/3523841) > Related issue: [Issue #3521221](https://www.drupal.org/node/3521221)
issue