OpenDialog Suggestion

I am just looking at the blazor components for the first time. I was wondering if you had considered adding an API to use a RenderFragment to open a dialog so instead of this:

var result = await dialogService.OpenAsync<Counter>("Counter", new Dictionary<string, object>() { { "Count", 2 } });

You could instead do this:

var result = await dialogService.OpenAsync("Counter", @<Counter Count="2" />);

Not even sure if that is possible, but it sure would be an elegant way to open a dialog.

Hi @David_Taylor,

It would indeed be elegant however the compiler would choke on @<Counter Count="2"> as it isn't valid C# code (one would open dialog from an event handler which has to be C#).

A possible solution is to convert that to manual RenderTreeBuilder calls e.g.

builder.OpenComponent<Counter>(0);
builder.AddAttribute(1, "Count", 2);
builder.CloseComponent();

Hi Atanas,
Actually it is valid C# now (or more accurately valid in a .razor file), Microsoft added it part way through development of Blazor. I think you missed the change. Try putting this into a .razor file:

@code {
    public class Demo
    {
        public RenderFragment Frag { get; set; }
    }

    void Example()
    {
        var demo = new Demo();
        demo.Frag = @<div>How are you</div>;
    }
}

You will note that will compile perfectly.

Indeed I have missed that. We will log this as a feature request.

Hi Atanas. I have got this working already using a wrapper, but yes please add it as an overload. In my example I added a utility component to the project called OpenDialog.razor as such:

@Content
@code {
    [Parameter]
    public RenderFragment Content { get; set; }
}

Then I can write this improved code:

    // We can add this wrapping method (that should really exist in RadZen.Blazor
    Task<dynamic> OpenAsync(string title, RenderFragment content) =>
        ds.OpenAsync<OpenDialog>(title, new Dictionary<string, object> { { "Content", content }});
    
    // Now we can  open a dialog using this nicer syntax
    async Task Example2() =>
        await OpenAsync("My Dialog", @<Counter count="2" />);

    // Here is another example
    async Task Example3() =>
        await OpenAsync("My Dialog", @<RadzenCard>This is my dialog</RadzenCard>);

Note how nice that syntax is for opening a simple dialog and/or passing parameters to a component. This would be a great improvement for you to add.

I also just want to say that I have only looked at your product components today, but I am very impressed with your work already.

We can also go one better and support an injected DialogService. If we include this default wrapper component (I have named OpenDialogDS.razor):

@inject DialogService  ds
@Content(ds)
@code {
    [Parameter]
    public RenderFragment<DialogService> Content { get; set; }
}

Plus this override I have simulated:

    // Wrapper for component that includes an injected DialogService
    Task<dynamic> OpenAsync(string title, RenderFragment<DialogService> content) =>
        ds.OpenAsync<OpenDialogDS>("My Dialog", new Dictionary<string, object> { { "Content", content }});
    
    // We can now open and close the Dialog
    async Task ButtonClickExample() => await OpenAsync("My Dialog", ds => 
        @<RadzenCard>
            <p>This is my content.</p>
            <RadzenButton Text="Success" Click="()=>ds.Close(true)" ButtonStyle="ButtonStyle.Success" />  
            <RadzenButton Text="Fail" Click="()=>ds.Close(false)" ButtonStyle="ButtonStyle.Danger"/>     
        </RadzenCard>);

We can then open a dialog like above. Note we can return Success or Failure. This would be super elegant to include in the lib.