fluentui-blazor icon indicating copy to clipboard operation
fluentui-blazor copied to clipboard

feat: allow to pass parameters to dialogs

Open MarvinKlein1508 opened this issue 1 year ago • 2 comments

🙋 Feature Request

I'm writing this feature request as a result of my discussion, which can be found here: https://github.com/microsoft/fluentui-blazor/discussions/2443

The issue here is to collect and exchange feedback regarding the DialogService within this library. In my opinion, the current way dialogs work isn't very useful in many cases because their use case only fits in very specific ways.

😯 Current Behavior

Currently, you can only bind to components that implement either IDialogContentComponent or IDialogContentComponent<T>. In addition, you cannot pass additional parameters to the dynamic component. You either need to add them to your model or create custom parameters that inherit from DialogParameters and cast them within your component every time. Both ways result in much boilerplate code, which is hard to maintain.

💁 Possible Solution

I would like to be able to use this kind of syntax:

private Modal _editModal = default;

protected override async Task ShowEditModalAsync(Customer? input = null)
{
// Provide parameters as dictionary
    var parameters = new Dictionary<string, object>
    {
        { nameof(CustomerForm.Model), input ?? new() },
        { nameof(CustomerForm.OnCancel), EventCallback.Factory.Create(this, _editModal.HideAsync) }, // Bind to modal close if you want
        { nameof(CustomerForm.OnSave), EventCallback.Factory.Create<Customer>(this, SaveAsync) } // Bind to other methods which has an input parameter
    };

    string modalTitle = input is null ? "New customer" : "Edit customer";

    await _editModal.ShowAsync<CustomerForm>(modalTitle, parameters: parameters);
}

The component itself should then create an instance of the provided component and fill all parameters. It would be even better if I could pass functions from the dialog itself as parameters.

🔦 Context

I want to pass additional parameters from outside to my dynamic component. For example, some sort of filters or rules for displaying content within the component itself.

In addition, I want to be able to use any component as a dynamic component for a dialog without having to implement the IDialogContentComponent or IDialogContentComponent<T> interfaces every time.

💻 Examples

Let's say I have a component that displays a user list and allows me to filter them by name. So, I provide a filter class named UserFilter, which contains both age and username attributes.

Now, I have certain views. The first view should always display users above the age of 18. The other one can be changed according to the user's needs. So, I don't want the user to change the value for the age filter in view 1.

In Blazor, I would achieve this like this:

View 1:

<UserSearch Filter="MyFilter" AllowToChangeAge="false" />

View 2:

<UserSearch Filter="MyFilter" AllowToChangeAge="true" />

The alternative would be to apply this property to my filter class, but I don't want to change my filter model. In some cases, I cannot change the class at all since I cannot modify the original source files.

MarvinKlein1508 avatar Jul 30 '24 11:07 MarvinKlein1508

Hi,

Because of vacation period, this will not see much activity in the coming weeks from my side.

vnbaaij avatar Jul 30 '24 12:07 vnbaaij

@vnbaaij don't worry. I just wanted to sort this one out of my large post because this is really important to me. Have a nice vacation! :)

MarvinKlein1508 avatar Jul 30 '24 13:07 MarvinKlein1508

I support this request strongly. This would be very useful.

Nowadays I create separated class just for combining few objects from page from which I open Dialog. But I have more and more features/forms in my app so maintenance is getting harder.

ZnowuJa avatar Nov 29 '24 13:11 ZnowuJa

Hi @vnbaaij

I've done some research on this. In my opinion the biggest downside of the FluentDialog is the direct implementation of the Content property.

This limits the use of this component by a lot. Since v5 will introduce a lot of breaking changes anyways I would like to suggest to get rid of the TData implementation all together. Instead of the content you should allow the user to pass a Dictionary<string, object?> as paramters for the specified generic component. Those parameters should then be bound to the DynamicComponent which is currently only passing a Content parameter. See: https://github.com/microsoft/fluentui-blazor/blob/a83077bf6434ef143e90d2661e0e4efe6a1b2a72/src/Core/Components/Dialog/FluentDialog.razor#L31 & https://github.com/microsoft/fluentui-blazor/blob/a83077bf6434ef143e90d2661e0e4efe6a1b2a72/src/Core/Components/Dialog/Services/DialogInstance.cs#L22

This will allow the user to pass as many parameters as they want to the generic component which allows for much more complex implementations.

Let me think what you think about this approach.

MarvinKlein1508 avatar Dec 18 '24 15:12 MarvinKlein1508

@dvoituron is already working on that for v5 (code is in the dev-v5 branch)...

  • Any component can be displayed (no need to implement an interface)
  • Any type can be passed to any [Parameter] property (e.g. Name and Age)

Example call:

var parameters = new DialogParameters(factory =>
{
    factory.Title = "My title";

    factory.Content.Add(nameof(SimpleDialog.Name), "John");
    factory.Content.Add(nameof(SimpleDialog.Age), 20);

    factory.OnStateChange = (e) =>
    {
   
     Console.WriteLine($"Dialog state changed: {e.State}");
    };
});
        
var dialog = await DialogService.ShowDialogAsync<SimpleDialog>(parameters);
var result = await dialog.Result;

https://github.com/user-attachments/assets/02ad968e-6d7d-42c8-974c-58a3094b26df

vnbaaij avatar Dec 18 '24 16:12 vnbaaij

@vnbaaij you guys are my heros! I can't wait to get my hands on this!

MarvinKlein1508 avatar Dec 18 '24 16:12 MarvinKlein1508

We aim to please! But getting this out will probable still take a while...

vnbaaij avatar Dec 18 '24 16:12 vnbaaij

Yea sure! At least I know that the end will come! :)

MarvinKlein1508 avatar Dec 18 '24 16:12 MarvinKlein1508

I've taken another look on the draft by @dvoituron . I must say, I really really like this factory approach! Good job.

MarvinKlein1508 avatar Dec 18 '24 17:12 MarvinKlein1508

Also very much looking forward to this release, as I'm currently looking for a way to reduce db calls within dialogs to retrieve data that the parent component already has but is not the target of the dialogservice.

JD2005L avatar Jan 04 '25 18:01 JD2005L

You can find the first samples and the documentation at this address.

https://fluentui-blazor-v5.azurewebsites.net/Dialog

dvoituron avatar Jan 04 '25 22:01 dvoituron

@dvoituron @vnbaaij is there any way to get this in v4 as some kind of extension package? This would really help me out a lot.

MarvinKlein1508 avatar Feb 25 '25 16:02 MarvinKlein1508

@dvoituron @vnbaaij is there any way to get this in v4 as some kind of extension package? This would really help me out a lot.

Not in v4. That will be included in v5.

dvoituron avatar Feb 25 '25 16:02 dvoituron

I'm closing this as completed since it has been integrated in v5 already.

MarvinKlein1508 avatar Apr 08 '25 07:04 MarvinKlein1508