1

I have a table which contains some fields to show summarized data in "Complaint" controller's "Index" action. With clicking the id of a table data, I am showing the details of complaint in another controller's action. (Detail/Index)

The table that I listed summarized data is below.

 @foreach (var item in Model)
            {
                <tr>
                    <td>
                        <a href="@Url.Action("Index", "Detail", new { id = item.Id })">
                            #
                        </a>
                    </td>

                        <td>@item.Employee.Name</td>

                        <td>@item.Dealer.Name</td>

                        <td>@item.Customer.Name</td>

When I click on the tag it correctly route me to Index page of Details controller with Id. What I want is instead of showing it on a new page, I want to show it inside a modal.

Details/Index page is below.

  @foreach (var item in Model)
                {
                    <div class="card-body">
                        <h5 class="card-title text-black-50 font-weight-bold text-center">Complaint Number : @item.ComplaintId</h5>
                        <hr />
                        <br />

                        <hr />

                            <p class="card-text">Employee Name : @item.Complaint.Employee.Name</p>
                            <p class="card-text">Phone Number : @item.Complaint.Employee.Phone</p>
                            <p class="card-text">City: @item.Complaint.Employee.City </p>
                            <p class="card-text">E-mail: @item.Complaint.Employee.Email </p>
                        }                          
                            <p class="card-text">Dealer Name : @item.Complaint.Dealer.Name</p>
                            <p class="card-text">Phone Number : @item.Complaint.Dealer.Phone</p>
                            <p class="card-text">City: @item.Complaint.Dealer.City </p>
                            <p class="card-text">E-mail: @item.Complaint.Dealer.Email </p>
                        }

I found this topic which have almost an equal problem with me but I couldn't figure it out.

Getting Bootstrap's modal content from another page

I am using bootstrap 4 btw since I saw some comments that bootstrap 4 deleted something about remote modal or smth like that.

Thank you for your kind help and time.

Finagle
  • 25
  • 5

1 Answers1

1

Solution #1 - iframe inside modal

One solution is you can have just one modal loaded on the page with an iframe in it. Each time you click on the tag, you use javascript to change the source of the iframe to the correct url and manually open the modal.

HTML

Instead of build the url for each complaint, you can stuff the detail id with data-, which can be used later by the javascript/jQuery method.

<table class="table table-hover">
    <tbody>
        @foreach (var item in Model)
        {
            <tr>
                <td>
                    <a class="complaint-detail" data-complaint-detail-id="@item.Id">
                        #
                    </a>
                </td>
                <td>@item.Employee.Name</td>
                <td>@item.Dealer.Name</td>
                <td>@item.Customer.Name</td>
            </tr>
         }
    </tbody>
</table>

<!-- Modal template -->
<div id="complaint-detail-modal" class="modal fade">
    <div class="modal-content">
        <div class="modal-header">...</div>
        <div class="modal-body">
            <iframe frameborder="0" />
        </div>
        <div class="modal-footer">...</div>
    </div>
</div>

JavaScript

$(function() {
    // Bind the click event of each anchor
    $('a.complaint-detail').click(function(){
        let detailId = $(this).data('complaint-detail-id'),
            url = '@Url.Action("index", "detail", new { area = "" })/' + detailId,
            $modal = $('#complaint-detail-modal'),
            $iframe = $modal.find('iframe');

        // Change the source of the iframe to the url
        $iframe.prop('src', url);    // Or you can use $iframe.attr('src', url);

        // Manually trigger the modal
        $modal.modal('show');

        return false;
    });
});

Solution #2 - with help of 3rd party library

Another solution is to build the complaint detail url the way you did, and hook up a 3rd party library that handles iframe content better than just a regular bootstrap modal. I will show you how to do it using fancybox (http://fancyapps.com/fancybox/3/).

HTML

You don't need to load a bootstrap modal template onto the page this time. Instead, you need an additional class as the fancybox's handle. I called it popup-fancy.

<table class="table table-hover">
    <tbody>
        @foreach (var item in Model)
        {
            <tr>
                <td>
                    <a class="popup-fancy" 
                        href="@Url.Action("index", "detail", new { area = "", id = item.Id })">
                        #
                    </a>
                </td>
                <td>@item.Employee.Name</td>
                <td>@item.Dealer.Name</td>
                <td>@item.Customer.Name</td>
            </tr>
         }
    </tbody>
</table>

JavaScript

I assume you follow fancybox's documentation to successfully load the library. Then you need to define its initialization globally. Now here I define 4 selectors because I want to have 4 different sizes of the popups based on the name of the selector. You don't have to do that if you only plan to have 1 size.

$(function() {
    $().fancybox({
        selector: 'a.popup-fancy',
        type: 'iframe',
        baseClass: 'fancybox-md',
        iframe: {
            preload: false
        }
    });

    $().fancybox({
        selector: 'a.popup-fancy-lg',
        type: 'iframe',
        baseClass: 'fancybox-lg',
        iframe: {
            preload: false
        }
    });

    $().fancybox({
        selector: 'a.popup-fancy-xl',
        type: 'iframe',
        baseClass: 'fancybox-xl',
        iframe: {
            preload: false
        }
    });

    $().fancybox({
        selector: 'a.popup-fancy-xxl',
        type: 'iframe',
        baseClass: 'fancybox-xxl',
        iframe: {
            preload: false
        }
    });
});

See here I duplicated the code just so that I can have different base css class correspond to different selector. On fancybox documentation it also supports data- attribute too but I like my method better - don't want to pollute HTML.

CSS (SASS)

Now you can define those custom css classes defined in the javascript section to adjust the width of the fancy popup.

.fancybox-md {
    .fancybox-content {
        max-width: 36.75rem;
    }
}

.fancybox-lg {
    .fancybox-content {
        max-width: 65.625rem;
    }
}

.fancybox-xl {
    .fancybox-content {
        max-width: 78.75rem;
    }
}

.fancybox-xxl {
    .fancybox-content {
        max-width: calc(100% - 3rem);
    }
}

Disclaimers

I wrote everything by hand so they're not tested.

David Liang
  • 20,385
  • 6
  • 44
  • 70