Send All CheckBox via Post

3

I'm trying to send all the CheckBox from my View, however, I can only send the ones that are selected via FormCollection

Controller

public ActionResult Index()
{
    List<ListaCheckBox> listacheck = new List<ListaCheckBox>();
    Random rand = new Random();

    for (int i = 0; i < 4; i++)
    {

        ListaCheckBox listaDemo = new ListaCheckBox
        {
            CD_CHECKBOX = i,
            CD_SELECIONADO = rand.Next(0,1),
            DS_CHECKBOX = "CHECK" + i
        };

        listacheck.Add(listaDemo);
    }

    return View(listacheck);
}

[HttpPost]
public ActionResult Index(FormCollection form,ListaCheckBox listaDemo)
{
    string[] formCollec = form["chek"].Split(',');
    return View();
}

Model

public class ListaCheckBox
{
    public int CD_CHECKBOX { get; set; }
    public string DS_CHECKBOX { get; set; }
    public int CD_SELECIONADO { get; set; }
}

View

@model List<Testes.Models.ListaCheckBox>

@using (Html.BeginForm())
{  
    @foreach (var item in @Model)  
    {  
        <label for="chek">@item.DS_CHECKBOX.ToString()</label>  
        <input type="checkbox" name="chek" id="check" value="@item.CD_CHECKBOX" />  
        <br />     
    }  

    <br />    
    <input type="submit" value="Envia CheckBox" />  
}

My FormColletion is receiving, but only the items that have been selected. I wish the unselected would come, too. What am I doing wrong?

    
asked by anonymous 29.04.2016 / 17:47

3 answers

1

Less gambiarra (aka Workaround), my people heheh.

André, you can use the default ASP.NET MVC Helpers . Since the value of a <input type="checkbox"/> only goes to server , if it is selected ( checked ).

In this way, you can generate your Html.CheckBoxFor(Expression<Func<TModel, Boolean>>, Object) " and receive as follows:

Controller

public ActionResult Index()
{
    List<ListaCheckBox> listacheck = new List<ListaCheckBox>();
    Random rand = new Random();

    for (int i = 0; i < 4; i++)
    {
        ListaCheckBox listaDemo = new ListaCheckBox
        {
            Id = i,
            Checked = (rand.Next(0,1) % 0) == 0,
            Description = "CHECK" + i
        };

        listacheck.Add(listaDemo);
    }

    return View(listacheck);
}

[HttpPost]
public ActionResult Index(List<ListaCheckBox> list)
{
    // aqui você pode filtrar todos os selecionados e não selecionados
    // com LINQ
    var selecionados = list.Where(l => l.Checked).ToList();
    var naoSelecionados = list.Where(l => !l.Checked).ToList();

    return View(list);
}

Model

public class ListaCheckBox
{
    public int Id { get; set; }
    public string Description { get; set; }
    public bool Checked { get; set; }
}

View

@model List<Testes.Models.ListaCheckBox>

@using (Html.BeginForm())
{  
    @for(int i = 0;i < Model.Count; i++)
    {
        <label>
            @Html.HiddenFor(m => Model[i].Id)
            @Html.HiddenFor(m => Model[i].Description)
            @item.Description
            @Html.CheckBoxFor(m => Model[i].Checked, new { @value = "True" })
        </label>
        <br />     
    }

    <br />
    <input type="submit" value="Envia CheckBox" />  
}

I hope I have helped \ o /

    
13.05.2016 / 01:12
2

This form is not good to use. FormCollection has several problems, and the correct thing is to go through strong typing.

Another thing is that you need to index each item in the list so that Model Binder can identify the elements. One suggestion would be:

@model List<Testes.Models.ListaCheckBox>

@using (Html.BeginForm())
{  
    @foreach (var item in @Model.Select((valor, i) => new { i, valor }))  
    {  
        <label for="chek">@item.valor.DS_CHECKBOX.ToString()</label>  
        <input type="hidden" name="listaDemo.index" value="@item.i" />
        <input type="checkbox" name="listaDemo[@item.i].CD_CHECKBOX" id="@("listaDemo_" + @item.i + "_CD_CHECKBOX")" value="@item.valor.CD_CHECKBOX" />  
        <br />     
    }  

    <br />    
    <input type="submit" value="Envia CheckBox" />  
}

And Controller :

[HttpPost]
public ActionResult Index(List<ListaCheckBox> listaDemo)
{
    /* Coloque sua lógica aqui */
}

Alternatively, you can use the BeginCollectionItem package to make logic easier to assemble.

It would look like this:

@model IEnumerable<TesteBool.Models.ListaCheckBox>

@using (Html.BeginForm())
{
    foreach (var item in Model.Select((valor, i) => new { i, valor }).ToList())
    {
        @Html.Partial("_Parcial", item.valor)
    }

    <br />
    <input type="submit" value="Envia CheckBox" />
}

# _Parcial.cshtml

@model TesteBool.Models.ListaCheckBox

@using (Html.BeginCollectionItem("listaDemo")) 
{ 
    <label for="chek">@Model.DS_CHECKBOX</label>
    @Html.CheckBoxFor(model => model.CD_CHECKBOX)
    <br />
}
    
29.04.2016 / 18:20
0

Without a workaround , it is not possible. This is characteristic of <input type="checkbox" /> . However, I believe that by changing the way you are treating request in your action , you should improve.

You see, you're using the same ID for all your checkboxes , this is not good. The ID value, within the HTML scope, should be unique, always.

In your scenario, I suggest adding the Model ID value to the checkbox ID :

@foreach (var item in @Model)  
{  
    <input type="checkbox" name="chek" id="[email protected]_CHECKBOX" value="@item.CD_CHECKBOX" />  
}   

So you can get one by one in action from your controller , thus revealing which ones were checked and which were not:

var rand = new Random();
for (var i = 0; i < 4; i++)
{
    var id = $"check-{i}";
    var value = form[id];
    var checked = !string.IsNullOrEmpty(value);

    if (checked) 
    {
        // campo checado
    }
    else
    {
       // campo não marcado
    }
}
    
29.04.2016 / 17:57