2017-09-19 4 views
1

J'ajoute dynamiquement des éléments à un formulaire de demande. Utiliser la vue partielle pour ajouter/supprimer les éléments mais en soumettant la vue principale, les valeurs ne sont pas liées. Ma question est de savoir comment faire la même chose.Soumettre des données avec une vue partielle ajoutée dynamiquement au contrôleur en utilisant ViewModels ne fonctionne pas

Avoir vérifié quelques questions similaires here et here Mais n'a pas pu trouver ce qui manque.

En utilisant 2 ViewModels, pour la vue principale (demande) et pour la vue partielle (LineItems) et BeginCollectionItem utilisé pour ajouter dynamiquement des éléments.

code:

ViewModels

public class EnquiryVM 
    { 
     public int ID { get; set; } 

     [Required] 
     public string EnquiryNumber { get; set; } 
     public int ClientID { get; set; } 
     public IEnumerable<SelectListItem> Clients { get; set; } 
     public Client Client { get; set; } 
     public int ItemID { get; set; } 
     public List<EnquiryLineItem> LineItems { get; set; } 

    } 
public class EnquiryLineItemVM 
    { 
     public int ID { get; set; } 
     [Required] 
     public string ItemDesc { get; set; } 
     public int Quantity { get; set; } 
     public int ManufacturerId { get; set; } 
     public IEnumerable<SelectListItem> ManufacturerList { get; set; } 
    } 

Vues: principales:

@model ViewModel.EnquiryVM 

@using (Html.BeginForm("Create", "Enquiries", FormMethod.Post)) 
{ 
    @Html.AntiForgeryToken() 

    <div class="form-horizontal"> 

     <hr /> 
     @Html.ValidationSummary(true, "", new { @class = "text-danger" }) 



     <div class="form-group"> 
      @Html.LabelFor(model => model.EnquiryNumber, htmlAttributes: new { @class = "control-label col-md-2" }) 
      <div class="col-md-3"> 
       @Html.EditorFor(model => model.EnquiryNumber, new { htmlAttributes = new { @class = "form-control" } }) 
       @Html.ValidationMessageFor(model => model.EnquiryNumber, "", new { @class = "text-danger" }) 
      </div> 
     </div> 





     <div class="form-group"> 
      @Html.LabelFor(model => model.ClientID, "Client", htmlAttributes: new { @class = "control-label col-md-2" }) 
      <div class="col-md-3"> 

       @Html.DropDownListFor(u => u.ClientID, (IEnumerable<SelectListItem>)Model.Clients, "--Select--") 
       @Html.ValidationMessageFor(model => model.ClientID, "", new { @class = "text-danger" }) 
      </div> 
     </div> 

     <div id="LineItems"> 
      // @using (Html.BeginForm()) // do we require again here since this will be like nested form? tested commenting still not working 
      // { 
       <div id="editorRowsLineitems"> 
        @foreach (var item in Model.LineItems) 
        { 
         @Html.Partial("_CreateEnquiryItem", item) 
        } 
       </div> 
       @Html.ActionLink("Add Items", "CreateLineItem", null, new { id = "addItem", @class = "button" }); 
      // } 
     </div> 
     <div class="form-group"> 
      <div class="col-md-offset-2 col-md-10"> 
       <input type="submit" value="Create" class="btn btn-default" /> 
      </div> 
     </div> 
    </div> 
} 

<div> 
    @Html.ActionLink("Back to List", "Index") 
</div> 

@section Scripts { 
    @Scripts.Render("~/bundles/jqueryval") 
<script type="text/javascript"> 
    $(function() { 
     $('#addItem').on('click', function() { 
      $.ajax({ 
       url: '@Url.Action("CreateLineItem")', 
        cache: false, 
        success: function (html) { 
         $("#editorRowsLineitems").append(html); 

         $("form").removeData("validator"); 
         $("form").removeData("unobtrusiveValidation"); 
         $.validator.unobtrusive.parse("form"); 
        } 
       }); 
       return false; 
      }); 
     $('#editorRowsLineitems').on('click', '.deleteRow', function() { 
       $(this).closest('.editorRow').remove(); 
      }); 
     $('form').data('validator', null); 
     $.validator.unobtrusive.parse($('form')); 
    }); 


</script> 
} 

vue partielle:

@model ViewModels.EnquiryLineItemVM 

<div class="editorRow"> 
    @using (Html.BeginCollectionItem("ItemList")) 
    { 
     <table class="table"> 

      <tr> 
       <td> 
        @Html.EditorFor(model => model.ItemDesc) 

       </td> 
       <td> 
        @Html.EditorFor(model => model.Quantity) 

       </td> 

       <td> 
        @Html.DropDownListFor(model => model.ManufacturerId, Model.ManufacturerList, "--Please Select--") 

       </td> 
       <td> 

        <a href="#" class="deleteRow">Delete</a> 
       </td> 
      </tr> 
     </table> 

    } 

Controller:Comment puis-je mapper les valeurs de la ligne ajoutée dynamiquement au ViewModel (EnquiryVM) afin que je puisse l'insérer dans la base de données.? Merci pour votre patience et votre temps.

Répondre

1

Le nom de votre propriété de collection est LineItems donc votre code pour générer ses contrôles doit être

@using (Html.BeginCollectionItem("LineItems")) // not ..("ItemList") 
{ 
    .... 
} 

afin qu'il génère des entrées avec name="LineItems[xxxx].ItemDesc" etc, plutôt que votre utilisation actuelle qui génère name="ItemList[xxxx].ItemDesc" (où xxxx est le Guid)

Comme une note de côté, le code dans votre méthode POST lancera une exception si ModelState est invalide parce que vous retournez la vue et ne pas repeupler la propriété IEnumerable<SelectListItem> Clients. Reportez-vous The ViewData item that has the key 'XXX' is of type 'System.Int32' but must be of type 'IEnumerable' pour une explication détaillée. En outre, les 2 dernières lignes de votre script pour ajouter des éléments ($('form').data('validator', null); $.validator.unobtrusive.parse($('form')); doivent être supprimées (la réparation du validateur coûte cher et vous le faites deux fois - une fois avant d'ajouter le html (les 2 lignes ci-dessus) et une fois après ajouter le code html

+0

Voir aussi modifier (dernier paragraphe) –

+0

Merci Stephen. maintenant, je suis ce que vous essayez de signaler en ce qui concerne la propriété de collection en question précédente. Je ne l'a changé un seul endroit, mais a oublié de correspondre avec le nom de la propriété depuis Je ne sais pas comment cela fonctionne en interne, mais votre explication a aidé à savoir comment fonctionne la BCI et comment elle s'applique – user2695433

+0

Je vais me déplacer pour répondre à votre autre question bientôt (j'espère) :) –