-
Notifications
You must be signed in to change notification settings - Fork 314
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
fixes FluentPageScript with Blazor Hybrid/MAUI and WebAssembly Standalone #1633
Conversation
As I've already said, I don't think it's a good idea to test all cases in this way: I think it would be better to look at the source of the problem: what's going wrong? const element = document.getElementById("my-element");
if (typeof element.onclick === "function") {
console.log("An onclick event handler exists for this element.");
} else {
console.log("No onclick event handler found.");
} |
I was debating submitting this PR but decided to draft one so the behaviour would consistent across the different hosting/rendering options. I agree that this definitely 'smells'. I've also discovered additional quirks related UI state not being preserved when transitioning from static rendered to Blazor rendered.
This also violates this note in the documentation regarding not coupling to render mode. All of this to provide the collapsing and expanding functionality of the FluentNavMenu when statically rendered. As for the source of problem, I'm still trying to figure that out. π. I've learned a lot about the rendering process as I've looked at this issue. I've been unable to find any detailed documentation on the transition from static rendered to interactive rendered. I've also considered but not tried:
|
I've been doing some further research looking for a root cause as per Denis's comments. I found
Data is a property inherited from Microsoft.FluentUI.AspNetCore.Components.FluentComponentBase. It is being used to prevent the script from being run
An alternative to making any code changes to the FluentUI-Blazor library would be to explicity do this in the NavMenu component on a per application basis for Blazor Hybrid/MAUI and WebAssembly hosted applications. @dvoituron @vnbaaij Thoughts?? Note: This still does not address the UI state transition issues. See #1633 (comment) |
I'm using the |
That makes sense. I forgot to include the following screenshot aboveπ. I made this change to the NavMenu component in the Blazor Hybrid/MAUI and WebAssembly hosted test applications and it effectively gave me the results I wanted. The javascript listeners were not added. Both these applications defaulted to using the Blazor provided event handler. It's basically a temporary work-around for 4.4.1. I'm currently using it in my production WebAssembly hosted application where I originally ran across this issue. π I'm still looking into a better long term fix that would also address UI state change issue. |
Indeed, I prefer to have an explicit property (for example by adding an option to |
@dvoituron I think the explicit declaration is the way to go. As I reflect on how this started and on @vnbaaij comment, Enhanced navigation should not have applied. I think this is a Blazor bug. When a Blazor Web App is first pre-rendered/statically rendered, the javascript for static SSR is sent to the browser where it's executed on the enhancedload event. When the application is ready, another render occurs but this time there is no enhancedload event. In Blazor Hybrid/MAUI and WebAssembly hosted applications, no pre-rerendering is done but the enhancedload event is still being triggered on first render. Preventing the enhancedload event from occuring would make the component behaviour consistent no matter the hosting environment. If this is truly a bug, by explicitly declaring it would make it easier to deprecate in the future when it's fixed. Assuming that using an explicit property as the approach, how should it be implemented? I see two options:
Note:
I can see pros and cons for either option. Thoughts? |
Yes, that is the ultimate goal.
I think this is the way to go.
This seems like a too specific solution for me.
The NavMenu is the only place I've added it on purpose. I anticipate that we would like to have more components that offer enhanced functionality (other than just displaying) when used in a SSR scenario. Because of the issues this is giving, I have not yet looked at which components we could use this. If we do, I expect we will be using the
I believe extra/new/better functionality is on the roadmap. I'll sk the Blazor team what is the est way to do this now. |
BackgroundI thought the root cause of the issue was that the enhancedload event was the cause of this issue so I filed an issue. After some feedback from @MackinnonBuck and attempting to create a minimal repro, I discovered a difference between how PageScript and FluentPageScript was implemented. The latter was a pretty faithful implementation in Typescript. The primary difference is was when the handler was added to the enhancedload event. In PageScript we have in BlazorPageScript.lib.module.js: export function afterWebStarted(blazor) {
customElements.define('page-script', class extends HTMLElement {
static observedAttributes = ['src'];
// We use attributeChangedCallback instead of connectedCallback
// because a page-script element might get reused between enhanced
// navigations.
attributeChangedCallback(name, oldValue, newValue) {
if (name !== 'src') {
return;
}
this.src = newValue;
unregisterPageScriptElement(oldValue);
registerPageScriptElement(newValue);
}
disconnectedCallback() {
unregisterPageScriptElement(this.src);
}
});
blazor.addEventListener('enhancedload', onEnhancedLoad);
} In FluentPageScript, this initialization is done in the index.ts file. fluentui-blazor/src/Core.Assets/src/index.ts Lines 297 to 299 in 072a938
and fluentui-blazor/src/Core.Assets/src/index.ts Lines 304 to 310 in 072a938
Why is happening?customElement fluent-page-script is always defined in index.ts. This means that attributeChangedCallback in FluentPageScript.ts is called in for any fluent-page-script tag present. This in turns calls registerPageScriptElement that calls initializePageScriptModule which then calls the onLoad in FluentNavMenu.razor.js. onLoad is triggered by attributeChangedCallback NOT by the enhancedload event. And because the customElement fluent-page-script is always defined. The Javascript handlers were always added to the toggle. FixThe fix is to move line 307 to after line 297, so the custom element is only defined for Blazor Web Apps. This fix also addresses the root cause of #1560 as well. |
With this fix, enhanced functionality will be controlled from FluentPageScript. π€ @MackinnonBuck made a comment with regards to PageScript being designed for with with π for pushing to find a root cause. |
Thanks Gary for perservering in finding the root cause! |
Pull Request
π Description
Prevents listeners from being added when running in BlazorWebView
π« Issues
Event listeners are being added to collapse/expand button for FluentNavMenu when used in Blazor Hybrid/MAUI.
Note: See comment
below for root cause
.π©βπ» Reviewer Notes
This is an addtional fix related to #1560 that did not cover Blazor Hybrid/MAUI.
The fix is based on determining if the component is running in BlazorWebView.
π Test Plan
I ran all the tests that I used for #1560. I created a new Blazor Hybrid/MAUI application created from the default template and updated it with the Fluent components to match the defaults created for a server rendered webassembly application to verify the desired behaviour.
β Checklist
General
Component-specific
β Next Steps