Create form for Model List

4

I have a Model called Question:

public class Pregunta
{
    public int id { get; set; }
    public string descripcion { get; set; }
    public int peso_id { get; set; }
    public List<int> roles_id { get; set; }
    public int dimension_id { get; set; }
    public int amsa_id { get; set; }
    public int modelo_operativo_id { get; set; }
    public List<Alternativa> alternativas { get; set; }
}

And the Alternative model

public class Alternativa
{
    public int id { get; set; }
    public string descripcion { get; set; }
    public int pregunta_id { get; set; }
    public int maduracion_id { get; set; }
}

By business rule a Pregunta can have 1 or many alternatives (5 is the limit) and I need to create an alternative form depending on the value that the user selects in an element <select>

<div class="form-group">
        <label class="control-label col-md-2">Cantidad de Alternativas</label>
        <div class="col-md-10">
            <select class="form-control" id="cantidad_alternativas">
                <option value="0" selected>Seleccione cantidad</option>
                <option value="1">1</option>
                <option value="2">2</option>
                <option value="3">3</option>
                <option value="4">4</option>
                <option value="5">5</option>
            </select>
        </div>
    </div>

To do tests I did the following:

@for (int i = 0; i < 5; i++)
    {
        <div class="form-group">
            @Html.LabelFor(model => model.alternativas[i].descripcion, "Descripcion", htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.alternativas[i].descripcion, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.alternativas[i].descripcion, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.alternativas[i].maduracion_id, "Maduracion", htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.DropDownListFor(model => model.alternativas[i].maduracion_id, (SelectList)ViewBag.Maduraciones, "Seleccione Maduracion", htmlAttributes: new { @class = "form-control" })
                @Html.ValidationMessageFor(model => model.alternativas[i].maduracion_id, "", new { @class = "text-danger" })
            </div>
        </div>
    }  

Problem 1

  

How can I delimit the end of the for cycle, with the value that the user selects in <select>

    
asked by sioesi 07.06.2017 в 17:04
source

2 answers

3

I have made a solution, the truth is that it is not the one that fits me but fulfills the function I need.

Create a normal selector with HTML and I did the same cycle for that I put in my question. With the difference that all the elements that are created there will be hidden.

<div class="form-group">
        <label class="control-label col-md-2">Cantidad de Alternativas</label>
        <div class="col-md-10">
            <select class="form-control" id="cantidad_alternativas">
                <option value="0" selected>Seleccione cantidad</option>
                <option value="1">1</option>
                <option value="2">2</option>
                <option value="3">3</option>
                <option value="4">4</option>
                <option value="5">5</option>
            </select>
        </div>
    </div>

    <div id="alternativas">

    @for (int i = 0; i < 5; i++)
    {
        <div class="form_alternativas">
            <div class="form-group">
                @Html.LabelFor(model => model.alternativas[i].descripcion, "Descripcion "+i, htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.EditorFor(model => model.alternativas[i].descripcion, new { htmlAttributes = new { @class = "form-control" } })
                    @Html.ValidationMessageFor(model => model.alternativas[i].descripcion, "", new { @class = "text-danger" })
                </div>
            </div>

            <div class="form-group">
                @Html.LabelFor(model => model.alternativas[i].maduracion_id, "Maduracion "+i, htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.DropDownListFor(model => model.alternativas[i].maduracion_id, (SelectList)ViewBag.Maduraciones, "Seleccione Maduracion", htmlAttributes: new { @class = "form-control" })
                    @Html.ValidationMessageFor(model => model.alternativas[i].maduracion_id, "", new { @class = "text-danger" })
                </div>
            </div>
        </div>
    } 

    </div>

In a JQUERY function, I go through all divs within div alternativas and hide them.

$("#alternativas div").each(function () {
        if ($(this).attr("class") == "form_alternativas") {
            $(this).addClass("hidden");
        }
    });

$("#cantidad_alternativas").change(function () {
        $("#alternativas div").each(function () {
            if ($(this).attr("class") == "form_alternativas") {
                $(this).addClass("hidden");
            }
        });
        var cantidad = parseInt($("#cantidad_alternativas").val());
        $("#cantidadAlternativa").val(cantidad);
        var contador = 0;
        $("#alternativas div").each(function () {
            if (contador < cantidad)
                if ($(this).attr("class") == "form_alternativas hidden") {
                    $(this).removeClass("hidden");
                    contador++;
                }
        });
    });

Within a Hidden field I save the value of cantidad_preguntas initialized to 0, I change the value each time the user changes the select.

Finally in the controller I go through the alternatives

foreach (var item in pregunta.alternativas)
{
    if (item.descripcion != null)
    {
          AlternativaBL aBL = new AlternativaBL();
          item.pregunta_id = result.error;
          aBL.Registrar(item);
     }
}
    
answered by 07.06.2017 / 20:06
source
1

The idea would be to have the dynamic view and use .load() to load the content

First, get the value of select with javascript or jquery

$('#cantidad_alternativas').on('change',function(){
  let cantAlt = $(this).val();
  //cargamos el contenido en el contenedor que sera dinámico (peticion post)
  $('#AlterntivasContenedor').load('@Url.Action("Vista","Controlador")', {id: cantAlt });
});

The controller would be something like this:

public ActionResult CuentasEdit(int id){
 TempData["CantAlternativas"] = id;//enviar la cantidad a la vista
 return View();
}

The view would be the same as you have only the for would change the 5% by TempData["CantAlternativas"] as int . (I'm not sure if this conversion is valid)

That said to simulate the goal I did this fiddle is not as I explain in this answer but it is only a simulation, there is only than changing JsonResult by ActionResult . To clarify what comment @Flxtr , the return does not return a view with Razor, if not an HTML rendering and that is what is loaded with .load() .

Another solution is to generate the code from jQuery or Javascript:

$('#cantidad_alternativas').on('change',function(){
  for(let i = 0; i <= $(this).val(); i++){
    //cargando el dom
  }
});
    
answered by 07.06.2017 в 17:46