Blazored / Modal

A powerful and customizable modal implementation for Blazor applications.
https://blazored.github.io/Modal/
MIT License
786 stars 186 forks source link

Support Bootstrap/custom modal markup #167

Closed SeattleDiver closed 4 years ago

SeattleDiver commented 4 years ago

Modify the BlazoredModalInstance.razor component to support bootstrap, and other templates, when emitting HTML markup.

I suggest creating a Modal.Framework enumeration that includes: Blazored, Bootstrap, Custom, etc.

When adding the BlazoredModal component to the MainLayout, the user can supply this value as an attribute (i.e. <BlazoredModal Framework="Bootstrap"> ) to configure all modals to render with their specified framework; Framework.Blazored could continue as the default preventing any breaking changes to existing implementations.

When the Modal.Framework has been specified, the BlazorModalInstance.razor component would emit bootstrap modal HTML elements with the appropriate structure, layout and css classes, instead of the default markup as currently implemented.

Also, a method can be provided to supply custom Markup for the modal, allowing for specialized layout and HTML for more advanced layouts.

Alternatively, fork the branch and create bootstrap compatible markup and styles.

chrissainty commented 4 years ago

Thanks for suggesting this @SeattleDiver.

I think we can certainly look at developing this into the modal.

AmarjeetBanwait commented 4 years ago

I think we should break markup into peices eg. Header, body and footer and of-course container. also with their respective classes. there can also be cross button class and icon I think here fluent apis can come handy as I suggested in 25 Add Fluent Apis

eg

Modal
.AddHeaderClass("modal-header")
.AddCloseIconMarkup("<i class="close"></i>")
....
chrissainty commented 4 years ago

The way I was thinking about doing this was to have entirely different versions of the modal markup for the various CSS frameworks. I think we need to do this as the HTML structure needs to be different between CSS frameworks.

AmarjeetBanwait commented 4 years ago

Yes that will be good if user want entirely different template. but think about of changing just class names or adding extra classes or changing just close icon template.

SeattleDiver commented 4 years ago

I'm willing to take this on this weekend. What are your rules for contributing to the project? What kind of designs/documentation do you need to proceed?

dfkeenan commented 4 years ago

Hi,

This project looks quite good. but I was also hoping to use custom dialogs (bootstrap).

I have had a quick and dirty attempt of an idea here: https://github.com/dfkeenan/Modal/commit/6bcb0185c96bf66e1cde3e60d06a4b7b2af7a041

Perhaps customizing it via ModalOptions would be a better user experience. They way I did it was quicker to implement. Also not sure how you would use the bootstrap dialog footer this way. Bootstrap also doesn't support all the positioning options etc.

chrissainty commented 4 years ago

@dfkeenan Thanks for the enthusiasm!

I've had a look over what you've done so far and it looks decent. I would suggest using generics over types though for the ModalService if that's the implementation we go with.

chrissainty commented 4 years ago

@SeattleDiver My apologies, I've completely missed your comment offering help. Last week was a bit crazy.

@dfkeenan @SeattleDiver Perhaps before we go any further it would be best to agree on a design between the three of us and then decide how we're going to get it built.

What do you all think?

dfkeenan commented 4 years ago

Did you mean change ModalService to something like ModalService<TModalInstance> instead?

That's how I started but there are a couple of spots that cast a IModalService to ModalService. I guess there could be a ModalService<TModalInstance> that inherits from a ModalService base class. I whipped this proof of concept up quickly and didn't have time to try that.

I have been playing with some other Blazor libraries over the weekend and thought that it might be good to have a general purpose library the works much like this one does. That could be used for modals, toasts or anything you like. Have something like (with better names):

This way the ComponentHostService could be used as a factory for any type of component and communicate back to what ever created it. As long as it has a HostedComponentInstance parameter and/or injects a ComponentHostService. You could have multiple ComponentHosts that some how determine if the HostedComponentInstance should be hosted in it.

You could then use these as base classes for the "Blazored.Modal" and "Blazored.Toast" libraries.

I waffled on a bit there.

SeattleDiver commented 4 years ago

Chris, DFKeenan, I'm still coming up to speed on authoring Blazor components so I may be a little offsides here, but could this feature be implemented by refactoring the BlazorModalInstance class into a Blazor Templated Component utilizing RenderFragments to let the implementor create all the markup for the modal dialog from inside the template. This would go a long way to allow implementations to use all the custom markup anyone would ever want.

Thoughts?

chrissainty commented 4 years ago

@SeattleDiver I've thought about the same thing. I'm currently playing around with a couple of ideas and that is one of them. I think that ultimately the answer will be a hybrid solution. We could use templating to offer developers a way of implementing a completely bespoke modal. But I think providing an out-of-the-box solution for common frameworks such as Bootstrap and Material is also required.

dfkeenan commented 4 years ago

I have implemented a ModalOptions.UseCustomLayout property. If you set this to true it replaces the whole content of the BlazoredModalInstance with the Component you use.

dfkeenan commented 4 years ago

Hey @chrissainty , I have made more improvements that allow you to do like:

<BlazoredModal>
    <ModalTemplate>
        <div class="modal-backdrop fade show" @onclick="context.Cancel"></div>
        <div class="modal fade show d-block" style="pointer-events: none;" tabindex="-1" role="dialog">
            <div class="modal-dialog " role="document">
                <div class="modal-content border-warning">
                    <div class="modal-header bg-warning text-white">
                        <h5 class="modal-title">@context.Title</h5>
                        <button type="button" class="close" aria-label="Close" @onclick="context.Close">
                            <span aria-hidden="true">&times;</span>
                        </button>

                    </div>
                    <div class="modal-body">
                        <CascadingValue Value="@context">
                            @context.Content
                        </CascadingValue>
                    </div>
                </div>
            </div>
        </div>
    </ModalTemplate>
</BlazoredModal>

It's in https://github.com/dfkeenan/Modal/commit/dd4bc32e8c9eb27a320a6c290cd5f7d251c42ec0 . Would you like me to do another PR for this? I wasn't sure what to do to samples so I only used this in the BlazerServer sample.