Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve the dev experience when a user doesn't apply an interactive render mode to a component that requires interactivity #57009

Open
danroth27 opened this issue Jul 25, 2024 · 11 comments
Labels
area-blazor Includes: Blazor, Razor Components enhancement This issue represents an ask for new feature or an enhancement to an existing one

Comments

@danroth27
Copy link
Member

danroth27 commented Jul 25, 2024

Rendering components statically by default with no user feedback that interactive features won’t work is a major usability issue right now with Blazor. It’s not currently an error to render an interactive component statically, because interactive components are often prerendered statically. But accidentally rendering a component statically when you wanted it to be interactive is common. We should think about how we can help users out with this issue.

@dotnet-issue-labeler dotnet-issue-labeler bot added the area-blazor Includes: Blazor, Razor Components label Jul 25, 2024
@danroth27 danroth27 changed the title Improve the dev experience when a user doesn Improve the dev experience when a user doesn't apply an interactive render mode to a component that requires interactivity Jul 25, 2024
@akorchev
Copy link

This has become the bane of our existence (as a Blazor component vendor) so I more than welcome the discussion.

@javiercn
Copy link
Member

javiercn commented Jul 26, 2024

@danroth27 we could have a [RequiresInteractivity] attribute and throw an exception otherwise or similar.

Nevermind, as per the comment below, the new APIs available in 9.0 enable this scenario

@javiercn
Copy link
Member

@akorchev with the new APIs in .NET 9.0 you can check the rendermode and throw if there isn't any defined.

@akorchev
Copy link

Wouldn't I have to add such check to all 70+ components we have though? I would much prefer a built-in solution that doesn't require developers to add runtime render mode checks. We would do it if there is no other way but what about all other developers that don't know of rendering modes and wonder why <button @onclick="..."> doesn't work?

Can't you throw an exception at runtime if EventCallbackFactory.Create is used in static rendering mode?

@javiercn
Copy link
Member

Can't you throw an exception at runtime if EventCallbackFactory.Create is used in static rendering mode?

No, because that's a perfectly valid thing to do for interactive components that support prerendering. Whatever solution we could come up with here would require you to modify all the components that require interactivity. Otherwise, it would be a massive breaking change for our customers.

That said, it's reasonably easy to achieve this by placing this logic in a base class and inheriting from it. You either do that on each of your components, or if you are defining them in razor files, use an _Imports.razor to specify the base class.

@akorchev
Copy link

No, because that's a perfectly valid thing to do for interactive components that support prerendering.

I thought we are discussing SSR here not prerendering. Aren't they different? What is the valid use case for using events in SSR when they will never be raised? Or do you mean that a distinction between SSR and prerendering can't be made? If the latter is true then your suggestion for checking the current render mode won't work either.

That said, it's reasonably easy to achieve this by placing this logic in a base class and inheriting from it.

I've heard of base classes :) What is the .NET 9 API which can be used to get the current rendering mode?

@boukenka
Copy link

From the release notes ASP.NET Core in .NET 9 Preview 5 - Release Notes

ComponentBase (and by extension your components) offers a new Platform property 
(soon to be renamed RendererInfo) that exposes Name and IsInteractive properties.

Platform.Name answers the question "Where is my component currently running?" and it 
can be Static, Server, WebAssembly, or WebView.
Platform.IsInteractive indicates whether the component is currently interactive (not Static).
ComponentBase also exposes a new AssignedRenderMode property, which provides the IComponentRenderMode value
defined in the component hierarchy (if any). This value is most useful during prerendering, 
as it lets you know how the component will render after prerendering so that you can render different content.

From the releases notes ASP.NET Core in .NET 9 Preview 6 - Release Notes

The ComponentPlatform class was renamed to RendererInfo. The Platform properties on 
ComponentBase and RenderHandle were also renamed to RendererInfo.

@akorchev
Copy link

Thanks!

I have the following remaining questions:

  1. What is the valid use case of rendering interactive components in SSR? @javiercn said throwing an exception is a breaking change. I think interactive components just don't work in SSR so they are already broken. That's the issue we are dealing with almost every day and the reason I am so interested in resolving it somehow.
  2. Are prerendering and SSR the same thing under the hood? (that would answer my first question).
  3. If prerendering and SSR are the same - how would a runtime check solve the issue? If not - why is throwing an exception a breaking change?

@javiercn
Copy link
Member

What is the valid use case of rendering interactive components in SSR? @javiercn said throwing an exception is a breaking change. I think interactive components just don't work in SSR so they are already broken. That's the issue we are dealing with almost every day and the reason I am so interested in resolving it somehow.

There's plenty of components that can work with just by rendering HTML and offer interactivity through standard web semantics (form posts) which Blazor supports from .NET 8.0+ and onwards.

Are prerendering and SSR the same thing under the hood?

Prerendering is a subset of SSR, but its mandatory when your component is not interactive (otherwise nothing would get rendered) from there your component might register handlers when running interactively or define named forms to handle SSR actions.

If prerendering and SSR are the same - how would a runtime check solve the issue? If not - why is throwing an exception a breaking change?

You can throw inside your components if you require InteractiveServer or InteractiveWebassembly to work. The framework can't make that choice, as a general component can perfectly function without such interactivity.

In general, is a design principle that interactivity is not required for components to render. Just because you can't interact with a component doesn't mean the page should completely stop working.

@MackinnonBuck MackinnonBuck added this to the .NET 10 Planning milestone Jul 29, 2024
@MackinnonBuck MackinnonBuck added the enhancement This issue represents an ask for new feature or an enhancement to an existing one label Jul 29, 2024
@akorchev
Copy link

There's plenty of components that can work with just by rendering HTML and offer interactivity through standard web semantics (form posts)

I was asking specifically about interactive components - ones that need to handle DOM events e.g. @onclick, @ondrop, @onchange. What is the use case for rendering such components in SSR? They would obviously not work.

The framework can't make that choice, as a general component can perfectly function without such interactivity.

There are many cases for components that won't work - any component that handles a DOM event won't work.

Just because you can't interact with a component doesn't mean the page should completely stop working.

That's a problem for me. Interactive components appear broken in SSR as no DOM event ever fires. Thus I suggest an exception is thrown. I still don't think there is a valid use case for rendering interactive components in SSR. What is the purpose of rendering a button whose @onclick would never fire?

@akorchev
Copy link

We keep getting "your components don't work out of the box" threads so I decided to link some of them here. Maybe it would bring more context. I think the following forum threads show that Blazor beginners struggle with understanding what rendering modes are and how to use them to enable interactivity.

  1. https://forum.radzen.com/t/out-of-box-simple-dropdown-no-data-showing/18146
  2. https://forum.radzen.com/t/problem-with-bind-value-in-dialog/18137
  3. https://forum.radzen.com/t/cannot-get-the-radzen-blazor-arc-gauge-to-work/17927
  4. https://forum.radzen.com/t/radzen-components-doesnt-work-in-net-8/17825/
  5. https://forum.radzen.com/t/trouble-using-panelmenu-in-navigation/17814
  6. https://forum.radzen.com/t/button-click-event-does-not-react/17723
  7. https://forum.radzen.com/t/does-radzen-components-support-net-8/14325
  8. https://forum.radzen.com/t/dropdown-data-list-cannot-open-and-expand-in-the-serverside-razor/17388
  9. https://forum.radzen.com/t/dialogservice-not-open-in-net-8-using-web-assembly-render-mode/17358
  10. https://forum.radzen.com/t/components-in-webassembly-not-firing-events/17376
  11. https://forum.radzen.com/t/lot-of-beginner-problems/17189
  12. https://forum.radzen.com/t/function-events-dont-occur-in-mainlayout/17109
  13. https://forum.radzen.com/t/submit-invalidsubmit-not-triggered/17107
  14. https://forum.radzen.com/t/blazor-notificationservice-not-working/17015
  15. https://forum.radzen.com/t/problems-with-scheduler-opening-dialog/15815
  16. https://forum.radzen.com/t/header-with-interactive-mode-cuts-off-the-body/16953
  17. https://forum.radzen.com/t/radzen-profile-menu-not-showing-up/16893
  18. https://forum.radzen.com/t/radzen-data-grid-sorting-filtering-functionality-not-working/16871
  19. https://forum.radzen.com/t/datagrid-paging-looks-correct-but-is-not-functional/16861
  20. https://forum.radzen.com/t/radzen-dialog-notification-not-working/16564
  21. https://forum.radzen.com/t/radzen-blazor-button-click-not-firing/3853
  22. https://forum.radzen.com/t/problem-with-httpcontext-and-interactive-rendering/16167
  23. https://forum.radzen.com/t/keypress-blocked-on-dialogs-in-interactiveauto-mode/16779
  24. https://forum.radzen.com/t/layout-icon-sidebar-example-not-reacting-to-user-input/16649
  25. https://forum.radzen.com/t/rendermode-in-blazor-web-app/16608
  26. https://forum.radzen.com/t/radze-dialog-blazor/16358
  27. https://forum.radzen.com/t/radzendatagrid-in-weather-component/16235
  28. https://forum.radzen.com/t/notification-not-working-with-net8/15414
  29. https://forum.radzen.com/t/per-page-component-auto-render-mode-never-switches-to-wasm/16064
  30. https://forum.radzen.com/t/radzen-control-not-react-to-click-event-in-mainlayout-razor/16032
  31. https://forum.radzen.com/t/wasm-template-w-client-side-only-reg-service-and-server-side-part-net-8/15900
  32. https://forum.radzen.com/t/how-to-set-correctly-radzenswitch-render-mode-net-8/15884
  33. https://forum.radzen.com/t/dialog-and-net8-0/15738
  34. https://forum.radzen.com/t/radzenpanelmenuitem-unexpected-behavior-based-on-rendermode/15564
  35. https://forum.radzen.com/t/dialog-support-in-net-8/15547
  36. https://forum.radzen.com/t/updated-to-5-0-issuse/18042
  37. https://forum.radzen.com/t/radzenupload-change-will-not-be-triggert/17935
  38. https://forum.radzen.com/t/radzendropdowndatagrid-change-event-not-triggering/15783/2
  39. https://forum.radzen.com/t/radzenmediaquery-with-javascript-event-callback-for-static-page/15625
  40. https://forum.radzen.com/t/using-radzen-components-in-identity-ui-net-8/15719/7

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-blazor Includes: Blazor, Razor Components enhancement This issue represents an ask for new feature or an enhancement to an existing one
Projects
None yet
Development

No branches or pull requests

5 participants