Unplanned
Last Updated: 30 Jul 2024 15:06 by Bram
Telerik Admin
Created on: 08 Jan 2024 14:26
Category: UI for Blazor
Type: Feature Request
6
Revise TelerikRootComponent usage in static Blazor apps with islands of interactivity

This public feature request:

  • Explains how the TelerikRootComponent works.
  • Outlines the problems of the current software design in static .NET 8 Blazor apps.
  • Measures customer demand for a major change that may possibly resolve the current limitations.

How the TelerikRootComponent Works

Historically, the TelerikRootComponent was designed with the following purposes:

  • To host and render all Telerik Blazor popups as RenderFragments. This means that all popups are rendered where the TelerikRootComponent is defined in the application's component hierarchy. In most cases, correct popup position requires the TelerikRootComponent to wrap all the content on the web page. Otherwise the correct position is not guaranteed and this is documented. In addition, the TelerikRootComponent instance is a CascadingValue, which allows it to collect all popup RenderFragments.
  • The TelerikRootComponent exposes parameters for global application-wide Telerik settings, such as icon type or RTL support. This is another reason why it makes sense to have a single TelerikRootComponent that wraps all the page content.

Problems and Limitations in .NET 8 Blazor Static Apps

.NET 8 Blazor apps with "Per Component" interactivity location create a big challenge for the above state of affairs:

  • Cascading values do not pass across render mode boundaries. .NET 8 includes a new feature for passing cascading values to interactive components (builder.Services.AddCascadingValues()), but this mechanism does not support passing of RenderFragments, because they are not JSON serializable. This brings the requirement that the TelerikRootComponent is part of an interactive component hierarchy.
  • When the TelerikRootComponent is in a non-layout .razor file, it triggers more re-renders than normally. They are related to internal MediaQuery instances and all popups, which the root component manages.

So, developers who work with a globally static app with specific interactive components ("islands of interactivity") may need to:

  • Place the TelerikRootComponent somewhere inside the component hierarchy, so it can't wrap all the page content. This will lead to wrong popup position.
  • Use multiple TelerikRootComponents. This requires to define the same parameters for each TelerikRootComponent instance.

Next Steps

All developers who develop static .NET 8 Blazor apps with "Per Component" interactivity location:

  1. Please vote for this feature request, so that we can measure how many customers are affected by the described limitations.
  2. Post here and describe:
    • Why do you need to use apps with "Per Component" interactivity.
    • Your specific challenges with the current TelerikRootComponent setup.
3 comments
Bram
Posted on: 30 Jul 2024 15:06
In a per page interactive setup we noticed the TelerikRootComponent invoking multiple renders. While this does not affect functionality, it probably affects performance.

Preferably we would use Blazor in a per component interactive setup, with islands of interactivity where they can be an added value. We currently use a per page interactive setup (with different layouts) as this is the only way possible with TelerikRootComponent without breaking the popup location of Telerik Components. 
In our enterprise application we require static pages for security considerations in login, logout & password reset pages. Some legacy (javascript) modules are easier to implement in a static page. Also, a full interactive blazor setup had some issues, for example with enhanced navigation.

I am aware of .Net Core 9.0 allowing per page static rendering with a global interactive rendermode, but besides these issues we had, from a personal point of view it makes more sense to start with a static website and add interactivity when needed, especially for large enterprise applications.
Dale
Posted on: 24 Jan 2024 15:01

I've also wanted to move to a more per component interactivity model but Telerik doesn't support this model in the best way. I could see this becoming more of a problem for the following users.

  • Existing customers (me) wanting to move to globally static apps with interactive components. I'm sure as more people want to take advantage of Blazor 8 you might hear more complaining about this issue.
  • People new to Blazor that want to mix static, server and web assembly. This group of users may be looking for a UI frame work that best supports this model.

I hope Telerik puts this on the roadmap for sometime this year. I hope this can be implemented in a way that doesn't cause significant breaking changes.

Blake
Posted on: 19 Jan 2024 23:45

Hello,

I am commenting on this post to describe the issues that I have with the TelerikRootComponent with .NET 8 Blazor.

First, requiring the TelerikLayout.razor with TelerikRootComponent and the ChildContent RenderFragment breaks Blazor's enhanced navigation. In Blazor with .NET 8 if you navigate between pages that share static resources those resources are detected by Blazor and not reloaded when navigating so the web app imitates a single-page application. With the TelerikLayout and TelerikRootComponent being passed to the MainLayout's @Body the app thinks there are no shared resources and therefore acts like a Http-Html call and response application breaking the enhanced navigation. 

Second, requiring shared components from the MainLayout to be in the TelerikRootComponent in the TelerikLayout breaks the system when it comes to using the Per-Page/Component level interactivity option and static pages. For example, in my team's current project, we have many pages with Telerik Blazor components and use the TelerikLayout with TelerikRootComponent and it works almost completely fine besides the double calling of OnInitializedAsync(). But for the static pages, like the profile page scaffolded from Microsoft Identity, I cannot use the TelerikLayout and TelerikRootComponent because of the render mode requirement and double call of OnInitializedAsync. If I don't use the TelerikLayout then my profile pages are loaded into the empty MainLayout since everything is required to be in the TelerikLayout. This issue has forced me to use the workaround of having two different MainLayouts. One for Telerik component pages and one for static pages. This was the easiest workaround to keep many layouts the same and not have errors or exceptions.