3

I followed a great little solution over at CodeProject for injecting partial views into bootstrap modals with no explicit ajax calls required...

https://www.codeproject.com/Tips/826002/Bootstrap-Modal-Dialog-Loading-Content-from-MVC-Pa

In a nutshell, the author does this (UPDATE: I have added modal-dialog, which the author doesn't do but is required):

_Layout

<div id="modal-container" class="modal fade" tabindex="-1" role="dialog">
   <div class="modal-dialog" role="document">
       <div class="modal-content"></div>
   </div>
</div>
<script>
    $('body').on('click', '.modal-link', function (e) {
        e.preventDefault();
        $(this).attr('data-target', '#modal-container');
        $(this).attr('data-toggle', 'modal');
    });
</script>

UPDATE - Here's the _Partial

<div class="modal-header">
</div>
<div class="modal-body">
</div>
<div class="modal-footer">
</div>

... and by doing so makes any link with class="modal-link" inject its result to the modal automatically.

Seems wonderfully simple and elegant, but just one problem: The data-target he specifies is the <div id="modal-container">. Really? Why? The content should be injected into the <div class="modal-content">, shouldn't it? But nearly everyone has no problem, and no one mentions this conundrum. For me, the solution does exactly what he's told it to, it injects into <div id="modal-container">, thereby overwriting <div class="modal-content"> with my modal-body, etc. that are the contents of my partial view, so the display is messed up -- full width of the window and transparent, because it's not going into the modal-content.

Am I missing something here?


UPDATE One of Stom's answers below is correct (I've marked it). However, as I've shown in updates above, I actually already had the <div class="modal-dialog" role="document"> in the _Layout and <div class="modal-header">, body, and footer in the _Partial. Ultimately, after this issue persisted for days, I woke up today and it just started working with no changes! Seriously? Frustrating. The problem previously was that the data-toggle was causing it to actually inject into the #modal-container, not the .modal-content. But now it started to function as Stom says the documentation says, which is that even though you set the data-toggle as the #modal-container, Bootstrap should inject it into the .modal-content. Why that was not happening before but is now, I haven't the foggiest. I haven't upgraded versions overnight or anything. Ghost problem ---

ohanaman
  • 35
  • 1
  • 8

2 Answers2

3

The content should be injected into the , shouldn't it?

Before version 3.1 it should be injected root element of modal i.e your modal-container But on version 3.1 it has changed. And now the bootstrap docs says it will be injected in modal-content.

modal-content with my modal-body, etc. that are the contents of my partial view, so the display is messed up , Why?

Because your partial view should contain modal-body and not modal-content. Also Adding modal-dialog inside model root element solves the syling issue.

So below setup should work for you:

Action Methods

public ActionResult Index()
{

return View();
}




public ActionResult GetPartialData()
{
    return PartialView("_ExamplePartial");
}

Index View

<!-- Button trigger modal -->
<a data-toggle="modal" href="@Url.Action("GetPartialData","Home")" data-target="#myModal">Click me</a>

<!-- Modal -->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
    <div class="modal-dialog" role="document">
        <div class="modal-content">

        </div>
    </div>
</div>

_ExamplePartial View

<div class="modal-header">
    <h5 class="modal-title" id="exampleModalLabel">Modal title</h5>
    <button type="button" class="close" data-dismiss="modal" aria-label="Close">
        <span aria-hidden="true">&times;</span>
    </button>
</div>

<div class="modal-body">

  <h1>Remote Partial Content</h1>

</div>

<div class="modal-footer">
    <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
    <button type="button" class="btn btn-primary">Save changes</button>
</div>

Note:

This option is deprecated since v3.3.0 and has been removed in v4.

Reference:

1. 2.

Shaiju T
  • 6,201
  • 20
  • 104
  • 196
  • _Because your partial view should contain modal-body and not modal-content. Also Adding modal-dialog inside model root element solves the syling issue._ --- Actually, my partial view already did contain the modal-header, modal-body, and modal-footer exactly per your example. And I already had the modal-dialog div as well. Sorry I didn't show it (I was trying to only show what the author showed). Oddly, without changing anything at all, I wake up today and the issue isn't happening anymore. It works perfectly! Arghhh!! I'm marking your answer as correct, but I think you should update it. – ohanaman Dec 21 '17 at 15:52
  • Hi, I'm trying to implement the exact same code but the href doesn't get executed.I think that something in the template blocks it, any idea? – Jean Jimenez Feb 10 '18 at 15:27
  • @JeanJimenez , If you are using `URLAction` then try raw url instead or paste you code in [paste bin](https://pastebin.com/) or ask a new question. – Shaiju T Feb 11 '18 at 16:08
1

Below Setup should work to inject partial view content into modal body and it doesn't mess up with your default bootstrap modal style.

Action Methods

public ActionResult Index()
{

 return View();
}


public PartialViewResult GetSomeData()
{
   System.Threading.Thread.Sleep(2000); // Just to show delay to Get data

   ViewBag.Message = "Example Data from Server"; //Using ViewBag Just for example, use ViewModel Instead

   return PartialView("~/Views/Shared/_ExamplePartial.cshtml");
}

Index View

<!-- Button trigger modal -->
<button type="button" class="btn btn-primary" id="btnGetData">
    Get Modal With Partial
</button>

<!-- Modal -->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
    <div class="modal-dialog" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title" id="exampleModalLabel">Modal title</h5>
                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                    <span aria-hidden="true">&times;</span>
                </button>
            </div>
            <div class="modal-body">
                <div id="partialViewContent">

                </div>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
                <button type="button" class="btn btn-primary">Save changes</button>
            </div>
        </div>
    </div>
</div>

_ExamplePartial View

<h2>Partial View Contents</h2>


 <h3>@ViewBag.Message</h3>


<p>Some More Static Content</p>

Script:

 <script>

    $(document).ready(function () {

        $('#btnGetData').click(function () {


            var requestUrl = '@Url.Action("GetSomeData", "Home")';

            $.get(requestUrl)

            .done(function (responsedata) {

                console.log("success");

                $("#partialViewContent").html(responsedata);

                $('#myModal').modal('show')

            })
            .fail(function () {
                alert("error");
            })
            .always(function () {
                console.log("finished");
            });

        })

        });


    </script>
Shaiju T
  • 6,201
  • 20
  • 104
  • 196
  • 1
    Thank you for taking the time, but I think you've missed the point of the article and my post. You've just used an ajax call and put it into the modal-body div. – ohanaman Dec 20 '17 at 15:27
  • Oh I see, that was a nice share. I have answered another in post , as this might help someone. But remember this has more control over the other because you can show error details to user if `ajax` request fails. – Shaiju T Dec 21 '17 at 06:24