SAP / ui5-webcomponents

UI5 Web Components - the enterprise-flavored sugar on top of native APIs! Build SAP Fiori user interfaces with the technology of your choice.
https://sap.github.io/ui5-webcomponents/
Apache License 2.0
1.45k stars 253 forks source link

ui5-tabcontainer | svelte #8514

Open ash-uncover opened 2 months ago

ash-uncover commented 2 months ago

Bug Description

ui5-tabcontainer is raising error when switching tab when used in svelte framework

Affected Component

ui5-tabcontainer

Expected Behaviour

we should be able to switch between tabs

Isolated Example

https://github.com/ash-uncover/ui5-webcomponents-svelte-issue

Steps to Reproduce

  1. Clone https://github.com/ash-uncover/ui5-webcomponents-svelte-issue
  2. npm install
  3. npm run dev -- --open
  4. try to switch from Tab1 to Tab2 > see error in the console

Log Output, Stack Trace or Screenshots

TabContainerTemplate.lit.ts:15 Uncaught TypeError: Cannot read properties of undefined (reading 'effectiveHidden') at TabContainer2.block84 (TabContainerTemplate.lit.ts:15:278) at TabContainer2.block013 (TabContainerTemplate.lit.ts:7:1425) at executeTemplate (executeTemplate.ts:17:18) at TabContainer2.render (UI5Element.ts:162:10) at updateShadowRoot (updateShadowRoot.ts:21:26) at TabContainer2._render (UI5Element.ts:707:4) at renderImmediately (Render.ts:44:15) at RenderQueue.process (RenderQueue.ts:64:4) at Render.ts:67:30

Priority

High

UI5 Web Components Version

1.23.0

Browser

Chrome

Operating System

No response

Additional Context

No response

Organization

No response

Declaration

ash-uncover commented 2 months ago

Note that this is working fine when using pure client side rendering

pskelin commented 2 months ago

Svelte seems to remove attributes it didn't add during its hydration step. We have seen this with other frameworks too. This is what happens:

  1. Svelte sends the <ui5-tab> markup to the client
  2. The import @ui5/webcomponents/dist/Tab.js is executed and the custom element is defined
  3. The custom element adds a ui5-tab attribute to its host so the element becomes <ui5-tab ui5-tab>
  4. Svelte hydration runs and removes the ui5-tab attribute because it was not there on the server: <ui5-tab>
  5. Some logic that the TabContainer runs depends on this attribute being present and breaks

Basically the custom element logic runs before the hydration is what is causing the problem.

I couldn't find a way to modify the svelte behaviour other than turning off SSR completely. So instead as a workaround, if the custom element is defined after the hydration, adding the attribute by the custom element will be ok.

I tried this by making all imports dynamic, this way the define of each custom element will run a bit later. I change Main.svelte to this:

<script>
  import('@ui5/webcomponents/dist/Label.js')
  import('@ui5/webcomponents/dist/Tab.js')
  import('@ui5/webcomponents/dist/TabContainer')
</script>

This seems to fix the issue, but it is not 100% synchronized with the svelte hydration. It would be best if there is a svelte hook for running code after hydration, but I couldn't find any.

Please let me know if this works for you.

PS. there is a svelte issue without a resolution for this: https://github.com/sveltejs/svelte/issues/7379

And the code where the attributes are removed: https://github.com/sveltejs/svelte/blob/svelte%404.2.12/packages/svelte/src/runtime/internal/dom.js#L706 This code seems fully refactored in the main branch, so perhaps the next svelte release will fix this...