web-dev-qa-db-fra.com

Afficher une vue partielle dans un popup modal

J'ai une vue partielle appelée Search.cshtml que j'affiche dans/Home/Index. Dans ce fichier, j'ai un formulaire HTML qui recherche et extrait/Vues/Comptes/Index avec les résultats de la recherche. Je souhaite afficher ces résultats dans la fenêtre contextuelle modale de la vue Recherche.

Lorsque je clique sur Rechercher (entrée sumbit) dans le code ci-dessous, je reçois un modal vide.

Je suis toujours novice en matière de MVC. J'ai essayé quelques résultats différents trouvés sur Stack Overflow, mais je n'ai pas réussi à trouver la résolution. Le code ci-dessous me donne au moins une fenêtre contextuelle modale, même si elle est vide.

Est-ce que je manque quelque chose de incroyablement simple? J'ai tout essayé dans le corps modal ci-dessous (Html.Action, RenderAction, Partial, RenderPartial) et rien ne semble fonctionner. Aussi, suis-je en train d'aboyer le mauvais arbre là-bas?

J'ai quelques captures d'écran et le code ci-dessous.

/Accueil/Index avec recherche vue partielle

Modal de recherche vide

Recherche.cshtml 

@model CustomerRelationshipManager.Models.Search

@{ViewBag.Title = "Search";}
@using (Html.BeginForm("Index", "Accounts", new { id = "searchForm" }))
{

<div style="border: solid 1px #ccc; padding: 30px 0 30px 30px; border-radius: 5px;
    width: 325px; margin: auto; display: table;">
    <table>
        <tr>
            <td valign="top">
                Search By:
            </td>
            <td>
                @Html.DropDownList("Search_Type", "Search_Type")
            </td>
        </tr>
        <tr>
            <td valign="top"></td>
            <td>
                @Html.TextBox("Search_String")
            </td>
        </tr>
        <tr>
            <td></td>
            <td>
                <input type="submit" data-toggle="modal" data-target="#myModal" value="Search" />
            </td>
        </tr>
    </table>
</div>

<div class="modal fade" id="myModal">
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
                <h4 class="modal-title">Modal title</h4>
            </div>
            <div class="modal-body">
                @{Html.Action("Index","Accounts");}
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
                <button type="button" class="btn btn-primary">Save changes</button>
            </div>
        </div><!-- /.modal-content -->
    </div><!-- /.modal-dialog -->
</div><!-- /.modal -->

}

HomeController.cs

    public ActionResult Search()
    {
        List<SelectListItem> items = new List<SelectListItem>();
        items.Add(new SelectListItem() { Text = "Account Number", Value = "Account_ID" });
        items.Add(new SelectListItem() { Text = "Last Name", Value = "Last_Name" });
        items.Add(new SelectListItem() { Text = "Phone Number", Value = "Phone_Number" });
        ViewBag.Search_Type = items;
        return PartialView();
    }

    [HttpPost]
    [AllowAnonymous]
    public ActionResult Search(Search search)
    {

        return PartialView("~/Accounts/Index");
        //return RedirectToAction("Index", "Accounts");
    }

AccountController.cs (je veux appeler Index () depuis ce contrôleur)

public ActionResult Index(string Search_Type, string Search_String)
    {
        if (Search_String == null)
        {
            var accounts = db.Accounts
                .Include(a => a.Account_Type)
                .Include(a => a.Account_Person)
                .Include(a => a.Account_Address)
                .Include(a => a.Account_Contact);
            return PartialView(accounts.ToList());
        }
        else
        {
            if (Search_Type == "Account_ID")
            {
                var accounts = db.Accounts
                .Include(a => a.Account_Type)
                .Include(a => a.Account_Person)
                .Include(a => a.Account_Address)
                .Include(a => a.Account_Contact)
                .Where(a => a.Account_ID.ToString() == Search_String);
                return PartialView(accounts.ToList());
            }
            else if (Search_Type == "Last_Name")
            {
                var accounts = db.Accounts
                .Include(a => a.Account_Type)
                .Include(a => a.Account_Person)
                .Where(b => b.Account_Person.Any(c => c.Person.Last_Name.StartsWith(Search_String)))
                .Include(a => a.Account_Contact)
                .Include(a => a.Account_Address);
                return PartialView(accounts.ToList());
            }
            else if (Search_Type == "Phone_Number")
            {
                var accounts = db.Accounts
                .Include(a => a.Account_Type)
                .Include(a => a.Account_Person)
                .Include(a => a.Account_Contact)
                .Where(b => b.Account_Contact.Any(c => c.Contact.Value == Search_String && c.Contact.Contact_Type.Name.Contains("Phone")))
                .Include(a => a.Account_Address);
                return PartialView(accounts.ToList());
            }
            else
            {
                var accounts = db.Accounts
                    .Include(a => a.Account_Type)
                    .Include(a => a.Account_Person)
                    .Include(a => a.Account_Address)
                    .Include(a => a.Account_Contact);
                return PartialView(accounts.ToList());
            }
        }

Compte Index.cshtml (je veux l'afficher dans la fenêtre contextuelle modale)

@model IEnumerable<CustomerRelationshipManager.Models.Account>

@{
ViewBag.Title = "Home";
}

<h2>Index</h2>

<p>
@Html.ActionLink("Create New", "Create")
</p>
<table class="table">
<tr>
    <th>Account #</th>
    <th>Contact Name(s)</th>
    <th>Address</th>
    <th>Contact</th>
</tr>
w2
@foreach (var item in Model)
{
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.Account_ID)
            <span>&nbsp;</span>
        </td>
        <td>
            @foreach (var i in item.Account_Person)
            {
                <span>
                    <b>@Html.DisplayFor(x => i.Person_Type.Name)</b>
                    <br />
                    @Html.DisplayFor(x => i.Person.First_Name)
                    &nbsp;
                    @Html.DisplayFor(x => i.Person.Last_Name)
                </span>
                <br />
            }
        </td>
        <td>
            @foreach (var i in item.Account_Address)
            {
                <span>
                    <b>@Html.DisplayFor(x => i.Address_Type.Name)</b>
                    <br />
                    @Html.DisplayFor(x => i.Address.Address1)
                    <br />
                    @Html.DisplayFor(x => i.Address.Address2)
                    @if (i.Address.Address2 != null)
                    { <br />}
                    @Html.DisplayFor(x => i.Address.City)
                    &nbsp;
                    @Html.DisplayFor(x => i.Address.State)
                    &nbsp;
                    @Html.DisplayFor(x => i.Address.Postal_Code)
                    <br />
                    @Html.DisplayFor(x => i.Address.Country)
                    <br />
                </span>
            }
        </td>
        <td>
            @foreach (var i in item.Account_Contact)
            {
                <span>
                    <b>@Html.DisplayFor(x => i.Contact.Contact_Type.Name)</b>
                    <br />
                    @Html.DisplayFor(x => i.Contact.Value)
                    <br />
                </span>

            }

        </td>
        <td>
            @Html.ActionLink("Edit", "Edit", new { id = item.Account_ID }) |
            @Html.ActionLink("Details", "Details", new { id = item.Account_ID }) |
            @Html.ActionLink("Delete", "Delete", new { id = item.Account_ID })
        </td>
    </tr>
}

1
Nyhack56

Avec votre code actuel, lorsque l’utilisateur clique sur le bouton Soumettre, il soumet un formulaire normal, car le bouton Soumettre se trouve à l’intérieur d’une balise form. Dans votre cas d'utilisation, vous devriez détourner l'événement javascript de forme normale submit à l'aide de javascript et effectuer un appel ajax à votre méthode d'action, où il utilisera les paramètres search_type et search_string pour obtenir les données filtrées et renvoyer un résultat d'affichage partiel. Ce résultat de vue partielle correspond au balisage HTML que vous souhaitez afficher dans la boîte de dialogue modale. Une fois que votre appel ajax a reçu la réponse du serveur, mettez à jour le contenu du corps de la boîte de dialogue modale avec cette réponse et lancez la boîte de dialogue modale.

@using (Html.BeginForm("Index", "Accounts", FormMethod.Post, new { id = "searchForm" }))
{
    <div>
        <input type="text" name="Search_String" />
        <input type="submit" id="submit" value="Search" />
    </div>
}    
<div class="modal fade" id="myModal">
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header">
                <button type="button" class="close" 
                                      data-dismiss="modal" aria-label="Close">
                    <span aria-hidden="true">&times;</span>
                </button>
                <h4 class="modal-title">Modal title</h4>
            </div>
            <div class="modal-body">
            </div>
            <div class="modal-footer">
                <button type="button" class="btn" data-dismiss="modal">Close</button>
                <button type="button" class="btn btn-primary">Save changes</button>
            </div>
        </div><!-- /.modal-content -->
    </div><!-- /.modal-dialog -->
</div><!-- /.modal -->

Ayez maintenant du code javascript, qui écoute l'événement de soumission de votre formulaire de recherche et force le comportement normal (soumission de formulaire normal) à la place de soumettre un formulaire ajax.

$(document).ready(function () {

    $('#searchForm').submit(function (e) {
        e.preventDefault();
        var $form = $(this);

        $.post($form.attr("action"), $form.serialize()).done(function (res) {
            $mymodal = $("#myModal");
            //update the modal's body with the response received
            $mymodal.find("div.modal-body").html(res);
            // Show the modal
            $mymodal.modal("show");
        });
    });

});

Vous devez maintenant vous assurer que votre méthode d’action Index renvoie une vue partielle (pour qu’elle n’exécute aucun code de présentation, mais uniquement le code de cette vue).

[HttpPost]
public ActionResult Index(string Search_Type, string Search_String)
{
    // Your existing filtering code goes here.
    return PartialView(accounts.ToList());
}
0
Shyju

Je l'ai compris!

  1. J'ai déplacé le modal en dehors de HTML.BeginForm dans Search.cshtml. Ensuite, j'ai simplifié la saisie sur le formulaire et supprimé les propriétés data-toggle et data-target.

    @model CustomerRelationshipManager.Models.Search
    
    @{
      ViewBag.Title = "Search";
    }
    @using (Html.BeginForm("Index", "Accounts", FormMethod.Post, new { id = "searchForm" }))
    {
    
    <div style="border: solid 1px #ccc; padding: 30px 0 30px 30px; border-radius: 5px;
    width: 325px; margin: auto; display: table;">
        <table>
        <tr>
            <td valign="top">
                Search By:
            </td>
            <td>
                @Html.DropDownList("Search_Type", "Search_Type")
            </td>
        </tr>
        <tr>
            <td valign="top"></td>
            <td>
                @Html.TextBox("Search_String")
            </td>
        </tr>
        <tr>
            <td></td>
            <td>
                <input type="submit" id="submit" value="Search" />
            </td>
        </tr>
    </table>
    </div>
    }
    <div class="modal fade" id="myModal">
        <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
                <h4 class="modal-title">Modal</h4>
            </div>
            <div class="modal-body">
    
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
                <button type="button" class="btn btn-primary">Save changes</button>
            </div>
        </div><!-- /.modal-content -->
    </div><!-- /.modal-dialog -->
    

  2. J'ai déplacé le javascript au bas du fichier partagé _layout.cshtml.

    @Scripts.Render("~/bundles/jquery")
    @Scripts.Render("~/bundles/bootstrap")
    @RenderSection("scripts", required: false)
    
    <script type="text/javascript">
    $(document).ready(function () {            
        $('#searchForm').submit(function (e) {
            e.preventDefault();
            var $form = $(this);
            $.post($form.attr("action"), $form.serialize()).done(function (res) {
                $mymodal = $("#myModal");
                //update the modal's body with the response received
                $mymodal.find("div.modal-body").html(res);
                // Show the modal
                $mymodal.modal("show");
            });
        });
    
       });
    
  3. Après avoir compris cela, j'ai eu une erreur LINQ que j'ai découverte en définissant un point d'arrêt dans la fonction Index () de mon AccountsController. Une fois que j'ai résolu ce problème, l'action Index () de mon compte AccountController est apparue dans ma fenêtre contextuelle modale.

HomeController Search () Boîte de dialogue modale Affichage de AccountsController Index ()

Merci pour votre aide, Shyju!

0
Nyhack56