vudz
vudz

Reputation: 65

How to dynamically change HTML.CheckBoxFor using Jquery

Hi Guys I have a problem, I have 3rows with users, and each row has 5 checkbox(Html.CheckBoxFor) these checkboxes are for assigning rights to these users.My problem is that when CheckBox 2 for row 1 is unchecked CheckBox 1 for row 1 should also be unchecked.But this is not happening, instead of unchecking just row 1, the whole colum for check box 1 is unchecked. Here is my Jquery function.

function setRights() {
var personalReport = document.getElementById("personalReports");
alert(personalReport.value);
personalReport.addEventListener('change', function () {
    if (personalReport.value) {
        $($("form #viewAllReports").attr('checked', false));
    }
    else {
    }
});
} 

"personalReports" and #viewAllReports" are Ids I gave to my Html.CheckboxFor(s). and this does work but not in the way I want too, and I guess what Im asking for here is, a way to uniquely identify all these row in a way that I can specify it in jquery to get the desired results thats going to affect just the row im busy with. Thanks in advance.

Here is my view code:

    <div class="chkbox">                            
        @Html.CheckBoxFor(m => m.PersonalReports, new { id = "personalReports", onclick   = "setRights();" })
    </div>
    <div class="chkbox">                            
        @Html.CheckBoxFor(m => m.ViewAllReports, new { id = "viewAllReports"})
    </div>
    <div class="chkbox">                            
        @Html.CheckBoxFor(m => m.EditAI)
    </div>
    <div class="chkbox">                            
        @Html.CheckBoxFor(m => m.ReportBranding)
    </div>
    <div class="chkbox">                            
        @Html.CheckBoxFor(m => m.PersonalizeTheme)
    </div>
    <div class="chkbox">
    @Html.CheckBoxFor(m => m.Search)
    </div>
    <div class="chkbox">
    @Html.CheckBoxFor(m => m.RequestOutOfBundleSearch)
    </div>

Upvotes: 2

Views: 13059

Answers (2)

Tohid
Tohid

Reputation: 6679

When we use Html.xxxxxxFor(m => m.property), it's always a question: how does jQuery selector get that element?

What @[gdoron] said was partially correct: Html.xxxxxxFor(m => m.property) build a HTML element with id and name equals to the property name, unless:

  1. Property is from a nested model, like: model.Address.Street
  2. Property is an array or collection, like: model.Order[0]

Although your view is simple and doesn't use any of above scenarios, I still prefer to add a HTML attribute to the elements for the sake of jQuery Selector.

The following code works perfectly for me:

@Html.CheckBoxFor(m => m.BoolValue1, new { value = "check-box-1" }) Check Box 1 (drives check box 2)
<br />
@Html.CheckBoxFor(m => m.BoolValue1, new { value = "check-box-2" }) Check Box 2


<script type="text/javascript">
    $(function () {
        $('input[value="check-box-1"]').bind('change', function () {
            personalReports_changed();
        });
    });

    function personalReports_changed() {
        if ($('input[value="check-box-1"]').attr('checked'))
            $('input[value="check-box-2"]').attr('checked', true);
        else
            $('input[value="check-box-2"]').removeAttr('checked');
    }
</script>

Upvotes: 3

Tohid
Tohid

Reputation: 6679

Although I've already answered this question, I want to bring up a relatively more complex scenario and show how could we manage checkboxes to affect on each others by using jQuery.

Scenario

  1. Imagine we have a list of book (from a database or any other repository)
  2. User can say: "I like this book."
  3. User can say: "I LOVE this book."

Rules:

  1. If user LOVEs a book, it means s/he likes it too.
  2. If user does NOT like a book, s/he canNOT LOVE it either.

Code

Models:

namespace MvcApplication1.Models
{
    public class Book
    {
        public string Title { get; set; }
        public bool IsLikeIt { get; set; }
        public bool IsLoveit { get; set; }
    }

    public class Person
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }
}

ViewModel:

namespace MvcApplication1.ViewModels
{
    public class BookViewModel
    {
        public Models.Person User { get; set; }
        public List<Models.Book> Books { get; set; }
        public BookViewModel()
        {
            Books = new List<Models.Book>();
        }
    }
}

Controlers:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        BookViewModel viewModel = new BookViewModel();

        viewModel.User = new Models.Person() 
                   { FirstName = "John", LastName = "Smith" };
        viewModel.Books.Add(new Models.Book() 
                   { Title = "Beginning ASP.NET 4: in C# and VB" });
        viewModel.Books.Add(new Models.Book() 
                   { Title = "Professional ASP.NET 4 in C# and VB" });
        viewModel.Books.Add(new Models.Book() 
                   { Title = "Pro ASP.NET MVC 3 Framework" });
        viewModel.Books.Add(new Models.Book() 
                   { Title = "Microsoft ASP.NET CODING STRATEGIES-W/ ASP .NET TEAM" });
        viewModel.Books.Add(new Models.Book() 
                   { Title = "Pro ASP.NET 4 in C# 2010, Fourth Edition" });

        return View(viewModel);
    }

    [HttpPost]
    public ActionResult Index(BookViewModel viewModel)
    {
        //save data.
        return View(viewModel);
    }

}

View (\Home\Index.cshtml):

@using MvcApplication1.Models
@model MvcApplication1.ViewModels.BookViewModel
<div>
    <p>
        User name: @Html.DisplayFor(u => u.User.FirstName)
        @Html.DisplayFor(u => u.User.LastName)</p>
</div>
<div>
    @using (Html.BeginForm())
    {
        @Html.HiddenFor(u => u.User.FirstName)
        @Html.HiddenFor(u => u.User.LastName)

        <table border="1">
            <thead>
                <tr>
                    <th>
                        I like it
                    </th>
                    <th>
                        I Love it
                    </th>
                    <th>
                        Book title
                    </th>
                </tr>
            </thead>
            <tbody>
                @for (int index = 0; index < Model.Books.Count; index++)
                {
                    <tr>
                        <td>@Html.CheckBoxFor(b => b.Books[index].IsLikeIt, new { id = string.Format("like-it-{0}", index), data_index = index })
                        </td>
                        <td>@Html.CheckBoxFor(b => b.Books[index].IsLoveit, new { id = string.Format("love-it-{0}", index), data_index = index })
                        </td>
                        <td>@Html.DisplayFor(b => b.Books[index].Title)
                            @Html.HiddenFor(b => b.Books[index].Title)
                        </td>
                    </tr>
                }
            </tbody>
        </table>
        <input type="submit" value="Submit" />
    }
</div>
<script type="text/javascript">

    $(function () {
        $('input[id^="like-it-"]').change(function (e) { likeit_clicked(e); });
        $('input[id^="love-it-"]').change(function (e) { loveit_clicked(e); });
    });

    function likeit_clicked(event) {
        if (!event.target.checked) {
            var index = $(event.target).attr('data-index');
            var loveitid = '#love-it-' + index;
            $(loveitid).attr('checked', false);
        }
    }

    function loveit_clicked(event) {
        if (event.target.checked) {
            var index = $(event.target).attr('data-index');
            var likeitid = '#like-it-' + index;
            $(likeitid).attr('checked', true);
        }
    }

</script>

View might look crappy. You can develop a better view based on your demands.

By the way, in the rendered html that MVC view engine generates, you can see long names for checkboxes:

name="Books[0].IsLikeIt"
name="Books[1].IsLikeIt"
name="Books[2].IsLikeIt"
.
.
.

but by generating our own id (id = string.Format("like-it-{0}", index)) and defining data-index attribute, jQuery is being enabled to select and change this checkboxes in appropriate manner.

Also read: HTML5 Custom Data Attributes (data-*)

Upvotes: 1

Related Questions