Create fields dynamically and set in model

Asked

Viewed 1,051 times

3

I am developing a register, 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 get the inputs of Model.

So far so good, now, for example, if I want to add one more 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 my button #addItem go on my Controller and return a PartialView of my inputs, follows the 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’t 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 don’t know if it’s right. I hope you understand my problem, thank you and I look forward to your help.

  • I let you try to understand. You have a view and want to add new fields to html, and when you save, do you have to go to all these fields? 1 - If the fields are all previously known, it is easier. You don’t even have to return partialview. Create the new fields via jquery. In your POST, you send the list as you do.

  • @jpgrassi Good morning, that’s right, I’m creating my fields via jQuery only that there in the controller he can not read the ones I created. when you speak in my POST, is in @Html.Beginform or in the POST AJAX?

  • So, I believe that what you are trying to do (pass the model at the time of the return of partialview) will not work. I have already implemented something similar but I used Angularjs. I was adding the fields on the normal screen via javascript and adding the "authors" in an array of objects. When I was going to save, I would send a POST by passing the list of authors to my controller.

  • I did some research, maybe this will help: http://stackoverflow.com/questions/15148103/mvc-4-how-do-i-pass-model-datato-a-partial-view

  • @jpgrassi I tried here but it didn’t work, do you have skype? or we can chat?

1 answer

1

Come on, we got a lot of mistakes... DEBUG/DEBUG code is the best tool to locate errors

  1. You are making a GET request (via AJAX) to the method Add, this method expects a Author list as parameter, however in your Javascript code, which makes the AJAX request, you are not passing the ones already created back to the control, if you debug your code, you will see that the parameter authors is coming null no controller. But this is not even a problem, because this, as I will explain the front is useless...
  2. There is no reason to send back to the controller the list of authors already filled by the user, just to add new fields (authors), this is a front-end tasknot back-end end, unless you do some data processing it doesn’t make sense all this data traffic.
  3. If you really need to send back the data just to add one more, change the action to POST, change the javascript to send the data via POST and send the data actually, via the property of the jQuery AJAX module you are using
  4. Your partial view has 4 problems (see items 5, 6, 7 and 8 below).
  5. You are rendering the scripts every time you call the partial view (the region "Scripts" at the end), you only need them 1x on your page, ideal is to put this call in _Layout or the same complete View, that is not what is making your code not work as expected, but this is a mistake.
  6. Your partial view model points to an author list @model List<MVC1.Models.Autor>, but nowhere in your partial view are you treating it as a list (there is no for, no foreach, no/while), which again makes it useless to pass to the method Add as mentioned in item 1.
  7. You are using @Html.BeginFormin partial view, this means that each 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 has only 1 author, you will lose the data informed in the other fields.
  8. You are creating the fields in the partial view as if it were a simple template, but you want an Author array/list, so you need to tell HTML that each view field belongs to an array, adding brackets at the end of the field name 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 - newAuthor.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 - New.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 to display the View(form) and the method to save the data to 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, this above is just a practical (untested, now written in Stack Overflow) example of how it would be to add new fields on the screen dynamically on demand and how to save send items to control as well.

As you will notice, it is a very basic example, which has no "stylization" and no validation of the data, I just made work what you were having problems, it is up to you to understand and modify to stay fully functional your need!

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

Browser other questions tagged

You are not signed in. Login or sign up in order to post.