Create fields dynamically and set in the model

3

I'm developing a registration, where I have my fields according to my model:

public class Autor
{
    [Key]
    public int IdAutor { get; set; }
    public string Nome { get; set; }
    public DateTime DataNascimento { get; set; }
}

That is, in my file .cshtml will have the inputs of Model .

So far so good, now, for example, if I want to add another Autor dynamically, without leaving the page, using AJAX , in fact, make the call:

 $(document).ready(function() {

        $("#addItem").click(function () {
            $.ajax({
                type: 'GET',
                url: '@Url.Action("AdicionarNovoAutor", "Autores")',
                success: function (html)
                {
                    $("#addnovo").append(html);
                },
                error: function (html)
                {
                    console.log("Erro");
                }
            });

        });        
});

So, when I click on my button #addItem I go to my Controller and return a PartialView of my inputs , follow PartialView :

@model List<MVC1.Models.Autor>
@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()
    <div class="form-horizontal">
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        <div class="form-group">
            @Html.LabelFor(model => model[0].Nome, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model[0].Nome, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model[0].Nome, "", new { @class = "text-danger" })
            </div>
        </div>
        <div class="form-group">
            @Html.LabelFor(model => model[0].DataNascimento, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model[0].DataNascimento, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model[0].DataNascimento, "", new { @class = "text-danger" })
            </div>
        </div>
    </div>
}
@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

This code goes to my div, but in my Controller I can not get the ones I added, follow the Controller when I go to Create :

public ActionResult AdicionarNovoAutor(List<Autor> autores)
    {
        autores.Add(new Autor());

        return PartialView("~/Views/Autores/_AutorPartial.cshtml", autores);
    }

In this case, I'm trying to pass as a parameter a list of Authors, I do not know if it's right. I hope you understand my problem, thank you and I look forward to your help.

    
asked by anonymous 03.12.2015 / 19:10

1 answer

1

Come on, we have several errors ... DEBUGAR / DEPURATE code is the best tool to find errors

  • You are making a GET request (via AJAX) to the AddNewAuthor method, this method expects an Author list as a parameter, however in your Javascript code, which does the AJAX request, you are not passing those that have already been created back to the control, if you debug your code, you will see that the authors parameter is arriving null in the controller. But this is not a problem, because this, as I will explain the front is useless ...
  • You do not have to send back to the controller the list of authors already filled in by the user, just to add new fields (authors), this is a front-end task, not the backend, unless you do some data processing does not make sense of all this data traffic.
  • If you really need to send the data back just to add one more, change the action to POST, change the javascript to send the data via POST and actually send the data, via property data of the jQuery AJAX module that you is using
  • Your partial view has 4 problems (see items 5, 6, 7 and 8 below).
  • You are rendering the scripts every time you call the partial view (the "Scripts" region at the end), you only need them 1x on your page, ideally you should put that call in the _Layout or in the same complete View, that's not what's making your code not work as expected, but that's a mistake.
  • The model of your partial view points to a list of Author @model List<MVC1.Models.Autor> , but nowhere in your partial view are you treating it as a list (there is no for, no foreach or one of / while), which again makes it useless to move to the AddNewAuthor method as discussed in item 1.
  • You are using @Html.BeginForm in the partial view, this means that every time you call the partial view, a new form will be created on the final page, when submitting the data, only the data of a form will be sent to the controller, as each form only has 1 author, you will lose the information entered in the other fields.
  • You are creating the fields in the partial view as if it were a simple template, but you want an Array / Author list, so you need to tell the HTML that each field of the view belongs to an array by adding brackets at the end of the name of field nomedocampo[]
  • Let's go to the functional example:

    Javascript - functions to add new fields on the screen and monitor the click on the #addItem button - newAutor.js

    $(document).ready(function(){
        $("#addItem").click(adicionaNovosCampos);
        adicionaNovosCampos(); //já chama a função para exibir os campos do primeiro autor
    });
    
    function adicionaNovosCampos(){
        var html = "Nome: <input type='text' name='Nome[]' /><br />Data de nascimento: <input type='date' name='DataNascimento[]' />";
        $("#formulario").append(html);
    }
    

    HTML - the main view, no partial view - NewAutor.cshtml

    @using(Html.BeginForm("Salvar","Autor", FormMethod.Post)){
        <div id="formulario"></div>
        <button type="button" class="btn btn-info" id="addItem">Adicionar novo autor</button>
        <button type="submit" class="btn btn-success">Salvar</button>
    }
    @section Scripts {
         @Scripts.Render("~/bundles/jquery")
         <script type="text/javascript" src="novoAutor.js"></script>
    }
    

    Controller - with the actions of displaying the View and the method to save the data in a supposed database - Author.cs

    public ActionResult NovoAutor() {
        return View();
    }   
    
    [HttpPost]
    public ActionResult Salvar(Autor[] autores) {
        var db = new DatabaseContext();
        foreach(var autor in autores)
            db.Autor.Add(autor);
        db.SaveChanges();
    }
    

    Well, that above is just one practical example (untested, now written on Stack Overflow) as it would be to add new fields in dynamically display on demand and saving send the items to control as well.

    As you can see, is a very basic example, which has no "style" and no validation of data, only did run what you were in trouble, is up to you to understand and modify to be fully functional your need!

    Of course this should serve as a study for you to enhance your knowledge along with it, I recommend reading the following article: ASP. NET Wire Format for Model Binding to Arrays, Lists, Collections, Dictionaries

        
    10.01.2017 / 06:27