GithubHelp home page GithubHelp logo

Comments (25)

javiercn avatar javiercn commented on May 17, 2024 1

@vnbaaij my comment is strictly with regards to binding properties, not about binding to checkboxes, etc. There are other ways to solve that.

from fluentui-blazor.

EisenbergEffect avatar EisenbergEffect commented on May 17, 2024

@nicholasrice Is this bug a result of Blazor trying to update through the attribute and not the property (and special casing for built-ins around this scenario)? This has come up in the community again and we need to pick back up that discussion thread and drive for a resolution. We may need @chrisdholt to help with that as it may involve changes in our components to help work around the missing Blazor feature (binding to properties).

from fluentui-blazor.

vnbaaij avatar vnbaaij commented on May 17, 2024

This is also being discussed in dotnet/aspnetcore#27030. There is a solution in the PR which might be able to be baked into .NET 6

from fluentui-blazor.

nicholasrice avatar nicholasrice commented on May 17, 2024

Yea that's my understanding of the issue. I think making components work with attributes or properties is the most pragmatic approach at this point, though I do wish Blazor (and other lacking UI systems) provided explicit property and attribute bindings.

If we do end up doing the work to make components work with properties or attributes, we'll need to make sure that form-associated controls still behave correctly in some of the edge-case scenarios like form resets and form-state restoration

from fluentui-blazor.

danroth27 avatar danroth27 commented on May 17, 2024

I do wish Blazor provided explicit property and attribute bindings.

@SteveSandersonMS @javiercn Is this something we should consider in Blazor?

from fluentui-blazor.

javiercn avatar javiercn commented on May 17, 2024

@danroth27 Today Blazor only works with attributes.

We've discussed this in the past, however its not something to be done lightly since it has an impact on the language and the runtime. If we think this is important we can put it on the list for 7.0, since this needs design and time to bake as the consequences of getting it wrong are bad.

from fluentui-blazor.

vnbaaij avatar vnbaaij commented on May 17, 2024

@danroth27 Today Blazor only works with attributes.

We've discussed this in the past, however its not something to be done lightly since it has an impact on the language and the runtime. If we think this is important we can put it on the list for 7.0, since this needs design and time to bake as the consequences of getting it wrong are bad.

While I understand that you want this to be done right, waiting till 7.0 means there won't be a compelling reason to release this library until then. Ability to bind checkboxes etc is crucial.
Can an interim solution like mentioned in dotnet/aspnetcore#27030 be used to make binding possible sooner (and maybe even backported to 5.x)?

from fluentui-blazor.

vnbaaij avatar vnbaaij commented on May 17, 2024

Good to hear. Thanks! For solving this binding problem, what would be the best option, you think?

from fluentui-blazor.

apsthisdev avatar apsthisdev commented on May 17, 2024

@javiercn @vnbaaij regarding model binding with Blazor bind syntax, you have mentioned, "There are other ways to solve that." What are these other ways? How can we use the workaround in .NET 5 to model bind to FAST radio, checkbox, select, etc. …. Right now, we are stuck in our evaluation for FAST components with balzor/asp.net core model binding?

from fluentui-blazor.

SteveSandersonMS avatar SteveSandersonMS commented on May 17, 2024

What are these other ways?

I expect this refers to solutions like dotnet/aspnetcore#27030

from fluentui-blazor.

javiercn avatar javiercn commented on May 17, 2024

The components can also be updated to also update the DOM attribute, or some additional JS interop can be used to setup a callback on the element and trigger the attribute update (which should in turn trigger the event?)

from fluentui-blazor.

EisenbergEffect avatar EisenbergEffect commented on May 17, 2024

Is there some way we can plug into Blazor's JS bridge? In that code there's some conditional logic that handles built-in inputs and chooses to set their properties instead of their attributes. Could the FAST team write some JS code that hooks into that to add our elements to a "list" of special cases? That would let us teach Blazor how to handle all these scenarios without introducing special syntax in Blazor or needing to make changes in the web components themselves. Thoughts? Does Blazor provide a JS global we could monkey patch or could you provide an official JS API for this case? My team is happy to contribute that work directly to Blazor if that seems like a reasonable solution. /cc @SteveSandersonMS @javiercn

from fluentui-blazor.

apsthisdev avatar apsthisdev commented on May 17, 2024

@javiercn , @EisenbergEffect , I am not a DOM expert but i tried few solutions on hooking up some JS code with Blazor components. And Model binding now seems to work. It is definitely a hack but is this something that can work reliably till you guys provide a long term solution. Do you see any issues with the approach below ?

BlazorFastCheckBox.razor

    <fast-checkbox @ref="_element" id="@Id" checked="@CurrentValue" @onchange="@OnChangeHandlerAsync" disabled="@Disabled">
        @ChildContent
    </fast-checkbox>
        /// <summary>
        /// The @onchange handler for the fast-checkbox. We are introducing a hack here to force model bind with the underlying field.
        //  We rely on the checked class being applied when user changes the checked state.
        //  Verify with ms team that this is reliable and an acceptable work around.
        /// <param name="args"></param>
        /// <returns></returns>
        /// </summary>
        /// <param name="args"></param>
        /// <returns></returns>
        private async Task OnChangeHandlerAsync(ChangeEventArgs args)
        {
                if (Disabled)
                {
                    return;
                }

                if (Id == null)
                {
                    await JsInteropService.AlertAsync("Id not provided for check box. Model binding requires a unique id.");
                    return;
                }

                // TODO:
                // https://github.com/microsoft/fast/issues/4782
                // https://github.com/microsoft/fast/issues/4248
                // https://github.com/microsoft/fast-blazor/issues/39
                // There are known issues around checkbox not model binding. For now we use the onchange event to get the HTML element and check it class list.
                // Fast component adds checked to class list to indicate checked state.
                bool checkedState = await JsInteropService.HasClass(Id, "checked");

                // For prerendering onchange event is called before the HTML is updated with checked class !
                if (RenderMode == "ServerPrerendered" || RenderMode == "WebAssemblyPrerendered")
                {
                    // TODO: HACK
                    // Another issue is for prerendering, onchange event is called before the updated HTML is rendered. So HasClass returns the previous 'checked' state.
                    // Since this is a toggle and value is true or false just flip the checkedState to indicate the new value.
                    checkedState = !checkedState;
                }

                // Update the model bind value.
                await ValueChanged.InvokeAsync(checkedState);

                // Make sure the edit context is notified of field change.
                EditContext.NotifyFieldChanged(FieldIdentifier);
        }

from fluentui-blazor.

EisenbergEffect avatar EisenbergEffect commented on May 17, 2024

Interesting. It could be a little brittle basing it on the presence of a class. I think that might go away eventually. I'd like to get @nicholasrice's opinion on that as well as @chrisdholt. Does the JsInteropService provide a way to get a property value? Maybe that could be added and we could use that API. We could make this backward compatible with some conditional compilation to fall back to the class check too.

For the checking by Id, could we generate one if one isn't provided so that we don't have to pass that cost along to the developer?

In general, I'm not opposed to adding this sort of code in the few places it's needed if that enables the key scenario.

from fluentui-blazor.

nicholasrice avatar nicholasrice commented on May 17, 2024

The async nature of DOM updates in FAST concerns me with this approach, where the class might not have changed prior to event emission depending on implementation details. We also generally try to not hoist classes onto the host element because it's very easy for libraries to clobber those classes (obviously checkbox is an exception), though in those cases we use attribute selectors which could theoretically be leveraged.

At some point we hope to use custom states / pseudo classes instead of real classes for some cases like this, at which point classes and attributes will go away, but it is unclear how long we'll be waiting for browser-support.

from fluentui-blazor.

EisenbergEffect avatar EisenbergEffect commented on May 17, 2024

Updating this thread with a link to our RFC which we believe will address all the form binding issues: microsoft/fast#5119

We'll be discussing this next week. Please weigh in on the RFC with any relevant feedback. Thank you everyone for your patience in this!

from fluentui-blazor.

plaisted avatar plaisted commented on May 17, 2024

Not sure if this is same issue or new, but the FluentSelect component does not work for setting the current value.

Looking at source it's binding to the fluent-select value attribute:

  • The fluent-select is thin wrapper around the fast-select component in fast-foundation.
  • fast-select shows no Attribute for value, only a Property for setting / viewing the value in the spec.
  • I see fast-select extends FormAssociated which may have an attribute for value but doesn't seem to do anything:
var select = document.querySelector('fast-select');
select.value = "value"; // works!
select.setAttribute("value", "value") // does nothing, not sure if this would work anyway after component created

Might be making some incorrect assumptions as I'm not familiar with how blazor binds data to native webcomponents, working with the base fast-component doesn't work either with value:

<fast-select value="xxx"> <!-- does not show xxx as value -->
    <fast-option value="yyy">yyy</fast-option>
    <fast-option value="xxx">xxx</fast-option>
</fast-select>

Is this a blazor implementation issue or is the fast-select supposed to work with a value attribute?

from fluentui-blazor.

EisenbergEffect avatar EisenbergEffect commented on May 17, 2024

@plaisted A few different things to note here:

  • This library currently only has wrappers for the fluent- components, not the fast- components. They are both based on the same foundation components though, so fixes we make in foundation should correct both design systems, regardless of whether these wrappers are being used or not.
  • The above RFC is absolutely related to the bugs with the select in general. The fix proposed should correct all our form components.
  • There is likely an additional issue with the select. A couple of people from our team have been talking about making some improvements around selected values for the select. I think those would either happen shortly after implementing the rfc or at the same time, depending on resources.

from fluentui-blazor.

plaisted avatar plaisted commented on May 17, 2024

Thanks, I crisscrossed fluent- with fast- but the the issue occurs in both components for the select. Sounds like something not working with select since other form controls work with the value attribute. I'll keep an eye on the RFC progress but for now will use another select implementation as blazor is very tedious to interop with web component properties.

from fluentui-blazor.

javiercn avatar javiercn commented on May 17, 2024

@javiercn , @EisenbergEffect , I am not a DOM expert but i tried few solutions on hooking up some JS code with Blazor components. And Model binding now seems to work. It is definitely a hack but is this something that can work reliably till you guys provide a long term solution. Do you see any issues with the approach below ?

BlazorFastCheckBox.razor

    <fast-checkbox @ref="_element" id="@Id" checked="@CurrentValue" @onchange="@OnChangeHandlerAsync" disabled="@Disabled">
        @ChildContent
    </fast-checkbox>
        /// <summary>
        /// The @onchange handler for the fast-checkbox. We are introducing a hack here to force model bind with the underlying field.
        //  We rely on the checked class being applied when user changes the checked state.
        //  Verify with ms team that this is reliable and an acceptable work around.
        /// <param name="args"></param>
        /// <returns></returns>
        /// </summary>
        /// <param name="args"></param>
        /// <returns></returns>
        private async Task OnChangeHandlerAsync(ChangeEventArgs args)
        {
                if (Disabled)
                {
                    return;
                }

                if (Id == null)
                {
                    await JsInteropService.AlertAsync("Id not provided for check box. Model binding requires a unique id.");
                    return;
                }

                // TODO:
                // https://github.com/microsoft/fast/issues/4782
                // https://github.com/microsoft/fast/issues/4248
                // https://github.com/microsoft/fast-blazor/issues/39
                // There are known issues around checkbox not model binding. For now we use the onchange event to get the HTML element and check it class list.
                // Fast component adds checked to class list to indicate checked state.
                bool checkedState = await JsInteropService.HasClass(Id, "checked");

                // For prerendering onchange event is called before the HTML is updated with checked class !
                if (RenderMode == "ServerPrerendered" || RenderMode == "WebAssemblyPrerendered")
                {
                    // TODO: HACK
                    // Another issue is for prerendering, onchange event is called before the updated HTML is rendered. So HasClass returns the previous 'checked' state.
                    // Since this is a toggle and value is true or false just flip the checkedState to indicate the new value.
                    checkedState = !checkedState;
                }

                // Update the model bind value.
                await ValueChanged.InvokeAsync(checkedState);

                // Make sure the edit context is notified of field change.
                EditContext.NotifyFieldChanged(FieldIdentifier);
        }

I would have done this at the JS layer directly by capturing a reference to the element with a @ref and attaching a handler to update the value attribute and trigger the event.

from fluentui-blazor.

EisenbergEffect avatar EisenbergEffect commented on May 17, 2024

PR is now up with the new current-value feature which will solve this issue for all form controls: microsoft/fast#5298 Once that is merged, we'll add the new property to the wrappers. Thank you everyone for your patience on this. We needed to find a solution that would work best with multiple libraries and frameworks, which we could also bring to W3C as a recommendation to help improve the built-in form elements in the future (without breaking the web).

from fluentui-blazor.

EisenbergEffect avatar EisenbergEffect commented on May 17, 2024

We've merged and released the first fix to improve form components in general. We're now working on a couple of additional fixes for checkboxes and radios. We believe those will go in this week.

from fluentui-blazor.

EisenbergEffect avatar EisenbergEffect commented on May 17, 2024

In terms of the Blazor integration, we're close to merging the .NET 6 work. After that we'll update the Blazor components to take advantage of the new features.

from fluentui-blazor.

EisenbergEffect avatar EisenbergEffect commented on May 17, 2024

One more PR related to this is under review here: microsoft/fast#5326

from fluentui-blazor.

EisenbergEffect avatar EisenbergEffect commented on May 17, 2024

Both core FAST PRs are now merged. We're also about to merge an update to the Blazor wrappers. We'll have one more Blazor wrapper update after that and then we should be able to close this as done.

from fluentui-blazor.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.