how to add jquery change event to radio buttons inside a grid - asp.net-mvc

I have two radio buttons - Approve and Deny in Telerik MVC grid, also applied jquery buttonset() on them. I needcheck which radio button is selected on each row. tried to do that on jquery change event but it's not firing up. Any thought?
<div id="ApprovalDetail" class="content">
<%
//To make columns visible/invisible
string Actions = (string)ViewData["Actions"];
//To store data back in Model
for (int i = 0; i < Model.idrequest.Length; i++)
{
%>
<%=Html.HiddenFor(model => model.idrequest[i].RequestDetailsId, new {#id="hiddenRequestDetailsId"+i.ToString()} )%>
<%=Html.HiddenFor(model => model.idrequest[i].Approved, new {#id="hiddenApproved"+i.ToString()} )%>
<%
}
Html.Telerik().Grid(Model.idrequest)
.Name("IdRequest")
.DataKeys(dataKeys =>
{
dataKeys.Add(r => r.RequestDetailsId).RouteKey("RequestDetailsId");
}
)
.Columns(columns =>
{
columns.Bound(r => r.RequestDetailsId);
columns.Bound(r => r.EmpId);
columns.Bound(r => r.Name);
columns.Bound(r => r.Email);
columns.Bound(r => r.ADSId);
columns.Bound(r => r.Action);
columns.Bound(r => r.Role);
if (Actions != null)
{
if (Actions.Contains("Suspend"))
{
columns.Bound(r => r.SuspensionDate).Format("{0:MM/dd/yyyy}").Width(100);
columns.Bound(r => r.SuspensionReason);
}
if (Actions.Contains("Reactivate"))
columns.Bound(r => r.ReactivationDate).Format("{0:MM/dd/yyyy}").Width(100);
if (Actions.Contains("Delegate"))
{
columns.Bound(r => r.DelegateOwner);
columns.Bound(r => r.DelegationStartDate).Format("{0:MM/dd/yyyy}").Width(100);
columns.Bound(r => r.DelegationEndDate).Format("{0:MM/dd/yyyy}").Width(100);
}
}
columns.Template(r =>
{
%>
<div class="radioStyle">
<%= Html.RadioButton(r.RequestDetailsId.ToString(), 1, false, new { #id = "yes_Approve" + r.RequestDetailsId.ToString(), #group = "Approval" })%><label
for="yes_Approve<%= r.RequestDetailsId %>">Approve</label>
<%= Html.RadioButton(r.RequestDetailsId.ToString(), 2, false, new { #id = "no_Approve" + r.RequestDetailsId.ToString(), #group = "Approval" })%><label
for="no_Approve<%= r.RequestDetailsId %>">Deny</label>
</div>
<%
}).Title("Approve");
})
.Pageable(paging => paging.Enabled(true).PageSize(10))
.KeyboardNavigation()
.Filterable(filtering => filtering.Enabled(true))
.Sortable(sorting => sorting.Enabled(true))
.Groupable(grouping => grouping.Enabled(true))
.Resizable(resizing => resizing.Columns(true))
.Render();
%>
</div>
<script type="text/javascript">
$(document).ready(function () {
//visuals
$(function () {
$("#approveRequest").button();
$(".radioStyle").buttonset();
});
$('#IdRequest :radio[group=Approval]').each(function () {
$(this).change(function () { alert("aa"); });
});
</script>

Grid is binding after onDocumentReady. So you need to use special telerik grid event OnRowBound.
Use .ClientEvents(c=>c.OnRowBound("bindGridRow"))
Where bindGridRow your function that bind onchange event to radio button in single row.

You can use grid's OnLoad event to bind change event handler:
.ClientEvents(events => events.OnLoad("BindOnChange"))
function BindOnChange(e){
// this - IdRequest
$(this).change(OnRadio_Change);
}
function OnRadio_Change(e){
var $radio = $(e.target);
alert($radion.is(':checked'));
// var $tr = $(this).closest('tr');
}

used this jquery code -
<script type="text/javascript">
$(document).ready(function () {
//visuals
$(function () {
$("#approveRequest").button();
$(".radioStyle").buttonset();
});
$('.label-class').click(LabelClicked);
function LabelClicked() {
var input = $('#' + $(this).attr('for'));
if (input) {
var selected = input.val();
InputChanged(selected);
}
return true;
}
function InputChanged(selected) {
var val = (selected.toString().split('_'))[0];
var detailsId = (selected.toString().split('_'))[1];
var approval = false;
if (val == "yesApprove")
approval = true;
var count = $("#Count").val();
for (var i = 0; i < count; i++) {
if ($("#hiddenRequestDetailsId" + i).val() == detailsId) {
$("#hiddenApproved" + i).val(approval);
}
}
}
// $('#IdRequest :radio[group=Approval]').each(function () {
// alert(this.name);
// $(this).change(function () { alert("aa"); });
//
// });
//client side validation
$.validator.setDefaults({
highlight: function (input) {
$(input).addClass("ui-state-highlight");
},
unhighlight: function (input) {
$(input).removeClass("ui-state-highlight");
}
});
$("#requestForm").validate({
submitHandler: function (form) {
$('form input[type=submit]').attr('disabled', 'true').addClass('ui-state-disabled');
form.submit();
}
});
});
</script>

Related

Kendo Multiselect Data Read Without Caching

#(Html.Kendo().MultiSelect()
.Name(Html.Name(ReflectionExtensions.GetName((IAddressViewModel x) => x.SuburbId)).ToString())
.DataTextField("DisplayName")
.DataValueField("Id")
.Placeholder("Select products...")
.AutoBind(false)
.DataSource(source =>
{
source.Read(read =>
{
read.Action("GetSuburbsByCountry", "Data").Data("siberia.address.filterSuburbByCountryIdParameter");
})
.ServerFiltering(true);
})
When i click on this kendo multiselect component it send a ajax call to the server get data, but i click on it again it does not send a ajax request. it show cached(previously returned data). i need to send ajax call each time.(need mvc wrapper, transport -> cache : false).
#(Html.Kendo().MultiSelect()
.Name(Html.Name(ReflectionExtensions.GetName((IAddressViewModel x) => x.SuburbId)).ToString())
.DataTextField("DisplayName")
.DataValueField("Id")
.Placeholder("Select Suburb")
.AutoBind(false)
.Events(e => { e.Filtering("siberia.address.onSuburbFiltering"); })
.MinLength(1)
.DataSource(source =>
{
source.Read(read =>
{
read.Action("GetSuburbsByCountry", "Data").Data("siberia.address.filterSuburbByCountryIdParameter");
})
.ServerFiltering(true);
})
-------------------------------------------------------------------------
function onSuburbFiltering() {
var currentSuburbId = '#' + prefix + 'SuburbId';
$(currentSuburbId).data().kendoMultiSelect.dataSource.read();
}
-------------------------------------------------------------------------
function filterSuburbByCountryIdParameter() {
var currentCountryId = '#' + prefix + 'CountryId';
var currentSuburbId = '#' + prefix + 'SuburbId';
var selectedCountry = $(currentCountryId).data("kendoDropDownList").value();
var surburbFilterText = $(currentSuburbId).data("kendoMultiSelect")._prev;
return {
SelectedCountryId: selectedCountry,
Text: surburbFilterText
}
}

Kendo UI Grid - How to save current radio button state

I am currently able to submit all records on my Kendo Grid back to the controller, but it does not reflect the latest state of the radio button. I dont want to have to click on a cell multiple times, to go into edit mode, nor use an edit button. I want to simply be able to make a radio button selection, click save and have the current state be reflected on my controller.
Razor View
#model IEnumerable<ECM.DAL.ViewModels.Roles.AcctAppUserRoles>
#using ECM.DAL.Infrastructure.Managers
#using GridEditMode = Kendo.Mvc.UI.GridEditMode
#{
ViewBag.applicationType = (int)SystemWideConfiguration.ApplicationTypes.ECM;
ViewBag.acctId = RightsManager.AccountId;
}
#(Html.Kendo().Grid(Model)
.Name("EcmRolesGrid")
.Columns(columns =>
{
columns.Bound(x => x.IsActive).Width(46)
.ClientTemplate("<input type='radio' name='isActive' value='#= IsActive #' # if (IsActive) { # checked='checked' # } # />")
.Title("Select Role")
.HtmlAttributes(new {style = "text-align:center"});
columns.Bound(r => r.RoleName).Width(75);
columns.Bound(r => r.RoleDescription).Width(125);
})
.HtmlAttributes(new { style = "height:340px;" })
.Editable(editable => editable.Mode(GridEditMode.InLine))
.DataSource(dataSource => dataSource
.Ajax()
.ServerOperation(false)
.Model(model => model.Id(p => p.UserId))
.Read(read => read.Action("GetApplicationAndAccountRoles", "User", new { applicationType = ViewBag.applicationType, acctId = ViewBag.acctId, userId = ViewBag.EcmRoleUserId.ToString() }))
.Update(update => update.Action("SaveApplicationRoles", "User")))
)
Controller:
[AcceptVerbs(HttpVerbs.Post)]
[HandleAjaxReturnableException]
public void SaveApplicationRoles(IEnumerable<AcctAppUserRoles> updatedRoles)
{
var userRoleDal = new UserRoleDal();
var roleDal = new RoleDal();
var applicationId = Guid.Empty;
var userId = Guid.Empty;
if (updatedRoles != null)
...
Javascript (I am using this because I have several tabs in this view with several grids)
function EcmRolesGridHasChanges() {
$.ajax({
url: 'user/SaveApplicationRoles',
cache: false,
type: 'POST',
contentType: 'application/json;',
charset:'utf-8',
data: JSON.stringify($("#EcmRolesGrid").data().kendoGrid._data)
});
}
Let me give you a visual as well....
When the grid is initially loaded the "Order Entry" Role is selected.
(Not showed)
I'll now choose "Limited User"
When I click save this is what I get on the controller:
I was expecting the first one to be false, second true and third false.
Any ideas?
Thank you.
You need to set the model on radio button click to let the grid know that particular row has been set as dirty therefore fire update event with updated model values
so add this on radio button click..
***************************Grid*******************
columns.Bound(x => x.IsActive).Width(46)
.ClientTemplate("<input type='radio' name='isActive' value='#= IsActive #' # if (IsActive) { # checked='checked' # } # onclick='radioBoxClick(this)' />")
**********************Script********************
//checkbox click function
function radioBoxClick(e) {
grid = $("kendoGrid").data().kendoGrid;
var dataItem = grid.dataItem($(e).closest('tr'));
var model = grid.dataSource.get(dataItem.UserId);
model.set("isActive", e.checked ? 1 : 0);
}
Minor modification to the answer that Shaz and Jayesh Goyani provided.
The function below goes over the other radio buttons and sets it to false.
function radioBoxClick(e) {
var grid = $("#EcmRolesGrid").data().kendoGrid;
var elementCount = grid.dataSource._data.length;
var dataItem = grid.dataItem($(e).closest('tr'));
var model = grid.dataSource.get(dataItem.RoleId);
model.set("IsActive", e.checked ? 1 : 0);
for (var i = 0; i < elementCount; i++) {
var elem = grid.dataSource._data[i];
if (elem.RoleId != model.RoleId)
elem.set("IsActive", 0);
}
}

Telerik MVC Grid, rebind after ajax delete from custom command?

I've got a Telerik MVC Grid and I am trying to have the grid rebind after deleting an item.
here is my grid:
#(Html.Telerik().Grid(Model.Item).Name("Items").Sortable().Scrollable(x => x.Height(400)).Filterable().Pageable(x => x.PageSize(20))
.Pageable()
.Columns(columns =>
{
columns.Bound(x => x.Equipment.Location.Building.Name).Title("Building");
columns.Bound(x => x.Equipment.Location.Room).Width(150);
columns.Bound(x => x.Number).Title("Number").Width(150);
columns.Command(commands =>
{
if (Model.CanViewHistory)
{
commands
.Custom("ViewHistory")
.Text("History")
.ButtonType(GridButtonType.Text)
.SendState(false)
.DataRouteValues(x => x.Add(y => y.Id).RouteKey("id"))
.Action("Index", "ItemHistory");
}
if (Model.CanEdit)
{
commands
.Custom("Edit")
.Text("Edit")
.ButtonType(GridButtonType.Image).ImageHtmlAttributes(new { #class = "t-icon t-edit t-test" })
.DataRouteValues(x => x.Add(y => y.Id).RouteKey("id"))
.SendState(false)
.Action("Save", "Items");
commands
.Custom("Delete").HtmlAttributes(new { onclick = "return confirm('Are you sure you want to delete this item?')" })
.Text("Delete").Ajax(true)
.ButtonType(GridButtonType.Image).ImageHtmlAttributes(new { #class = "t-icon t-delete t-test" })
.DataRouteValues(x => x.Add(y => y.Id).RouteKey("id"))
.SendState(false)
.Action("Delete", "Items", new { Area = "Apps" });
}
}).Title("Actions");
}).ClientEvents(events => events.OnComplete("onComplete")))
And my method to call after delete executes is:
<script type="text/javascript">
function onComplete() {
$("#Items").data("tGrid").rebind();
}
</script>
Action:
public ActionResult Delete(Guid id)
{
Item item = _itemService.GetOne(x => x.Id == id);
_itemService.Delete(item);
return RedirectToAction("Index");
}
The action works, the item does actually get deleted, but the grid does not refresh, only after manually reloading the page will the deleted item be gone. In my console when I click the delete button I get the following error:
Uncaught ReferenceError: xhr is not defined telerik.grid.min.js:1
What am I doing wrong?
Edit: Using Kirill's method below removes my error, but the grid still doesn't refresh, the javascript is sucessfully being called and getting to the rebind() command though.
You should not return ViewResult from this method. You should return JsonResult.
public JsonResult Delete(Guid id)
{
try
{
Item item = _itemService.GetOne(x => x.Id == id);
_itemService.Delete(item);
return Json(new { result = true });
}
catch
{
return Json(new { result = false });
}
}
And onComplete should be:
function onComplete(e) {
if (e.name == "Delete") {
var result = e.response.result;
if(result==true)
$("#Items").data("tGrid").rebind();
else{
alert("Error on deleting")
}
}
}
UPDATE
This works with Ajax binding.
#(Html.Telerik().Grid<ItemType>.Name("Items")
.Sortable().Scrollable(x => x.Height(400))
.Filterable().Pageable(x => x.PageSize(20))
//you should add this line:
.DataBinding(dataBinding => dataBinding.Ajax().Select("Select", "Items"))
.Columns(columns =>
{
columns.Bound(x => x.Equipment.Location.Building.Name).Title("Building");
columns.Bound(x => x.Equipment.Location.Room).Width(150);
columns.Bound(x => x.Number).Title("Number").Width(150);
columns.Command(commands =>
{
if (Model.CanViewHistory)
{
commands.Custom("ViewHistory")
.Text("History")
.ButtonType(GridButtonType.Text)
.SendState(false)
.DataRouteValues(x => x.Add(y => y.Id).RouteKey("id"))
.Action("Index", "ItemHistory");
}
if (Model.CanEdit)
{
commands.Custom("Edit")
.Text("Edit")
.ButtonType(GridButtonType.Image)
.ImageHtmlAttributes(new { #class = "t-icon t-edit t-test" })
.DataRouteValues(x => x.Add(y => y.Id).RouteKey("id"))
.SendState(false)
.Action("Save", "Items");
commands.Custom("Delete")
.HtmlAttributes(new { onclick = "return confirm('Are you sure you want to delete this item?')" })
.Text("Delete")
.Ajax(true)
.ButtonType(GridButtonType.Image)
.ImageHtmlAttributes(new { #class = "t-icon t-delete t-test" })
.DataRouteValues(x => x.Add(y => y.Id).RouteKey("id"))
.SendState(false)
.Action("Delete", "Items", new { Area = "Apps" });
}
}).Title("Actions");
})
.ClientEvents(events => events.OnComplete("onComplete")))
and you should add action to get data to grid:
[GridAction]
public JsonResult GetChangeHistory(Guid stockCompanyId)
{
IEnumerable<ItemType> items = ... //code to get items.
return Json(new GridModel<ItemType>(items));
}
I assume that element of items collection is of type ItemType.

Kendo UI Grid Only Expand One Row at a Time

I have a Kendo Grid which I would like to only be able to expand one row at a time for detail editing. What is the simplest way to do this?
#(Html.Kendo().Grid<MyModel>()
.Name("MyGrid")
.ClientDetailTemplateId("MyTemplate")
.Columns(columns =>
{
columns.Bound(b => b.Code);
columns.Bound(b => b.Name);
columns.Bound(b => b.Description);
...
columns.Command(cmd => { cmd.Edit(); cmd.Destroy(); });
})
.ToolBar(toolbar => toolbar.Create())
.Editable(editable => editable.Mode(GridEditMode.InLine))
.DataSource(dataSource => dataSource
.Ajax()
.Model(model => model.Id(a => a.Id))
.Create(create => create.Action("Create", "SysMaint", new { id = Model.ProjectId }))
.Read(read => read.Action("Read", "SysMaint", new { projectId = Model.ProjectId }))
.Update(update => update.Action("Update", "SysMaint"))
.Destroy(destroy => destroy.Action("Destroy", "SysMaint"))
)
)
<script id="MyTemplate" type="text/kendo-tmpl">
#(Html.Kendo().TabStrip()
.Name("TabStrip_#=Id#")
.SelectedIndex(0)
.Items(items =>
{
items.Add().Text("A").LoadContentFrom("MyPartialA", "SysMaint", new { id = "#=Id#" });
items.Add().Text("B").LoadContentFrom("MyPartialB", "SysMaint", new { id = "#=Id#" });
})
.ToClientTemplate()
)
</script>
Ends up this is really simple. Just add these few lines.
...
.Update(update => update.Action("Update", "SysMaint"))
.Destroy(destroy => destroy.Action("Destroy", "SysMaint"))
)
.Events(events => events.DetailExpand("detailExpand"))
)
<script type="text/javascript">
var expandedRow;
function detailExpand(e) {
// Only one open at a time
if (expandedRow != null && expandedRow[0] != e.masterRow[0]) {
var grid = $('#MyGrid').data('kendoGrid');
grid.collapseRow(expandedRow);
}
expandedRow = e.masterRow;
}
</script>
I hope this helps somebody.
That works except it does not remove the old detail row. Add the bit marked NEW to remove each previously opened detail row.
if (expandedRow != null && expandedRow != e.masterRow[0]) {
var grid = $('#RequestsGrid').data('kendoGrid');
grid.collapseRow(expandedRow);
expandedRow[0].nextElementSibling.remove(); //NEW
}
expandedRow = e.masterRow;
Building on Trey's answer, this version will work generically for any grid (using #vikasde's suggestion), and will also work when you have nested grids, so that the child grid when invoking the detailExpand, won't collapse its parent grid row as a side effect.
<script type="text/javascript">
function detailExpand(ev) {
var expandedRow = $(ev.sender.wrapper).data('expandedRow');
// Only one open at a time
if (expandedRow && expandedRow[0] != ev.masterRow[0]) {
var grid = $(ev.sender.wrapper).data('kendoGrid');
grid.collapseRow(expandedRow);
}
$(ev.sender.wrapper).data('expandedRow', ev.masterRow);
}
</script>
Further to the answers already here, I found that by combining hatchet's and Danny Blue's answers and using the DetailCollapse event works nicely, and will remove the underlying detail content if a row is collapsed manually.
MVC Grid configuration:
.Events(ev =>
{
ev.DetailExpand("detailExpand");
ev.DetailCollapse("detailCollapse");
})
Page scripts:
function detailExpand(ev) { // Credit hatchet
var expandedRow = $(ev.sender.wrapper).data('expandedRow');
// Only one open at a time
if (expandedRow && expandedRow[0] !== ev.masterRow[0]) {
var $grid = $(ev.sender.wrapper).data('kendoGrid');
$grid.collapseRow(expandedRow);
}
$(ev.sender.wrapper).data('expandedRow', ev.masterRow);
}
function detailCollapse(ev) {
var expandedRow = $(ev.sender.wrapper).data('expandedRow');
expandedRow.next().remove(); // Credit Danny Blue
}

How to pass values from telerik mvc ajax grid to controller

I have 2 telerik mvc ajax grids which needs to be populated based on the selected row on the first grid.
below is my code:
#(Html.Telerik().Grid<PurchaseRequest>()
.Name("grdPurchaseRequest")
.DataBinding(binding => binding.Ajax()
.Select("GetPurchaseRequests", "PurchaseOrder"))
.DataKeys(keys => keys
.Add(o => o.PurchaseRequestID))
.Columns(cols =>
{
cols.Bound(c => c.PurchaseRequestID).ReadOnly().Hidden();
cols.ForeignKey(c => c.ProjectID,(System.Collections.IEnumerable)ViewData["prProjects"],
"ProjectID", "ProjectName");
cols.Bound(c => c.FullName);
cols.Bound(c => c.RequestDate).Format("{0:MM/dd/yyyy}");
cols.Bound(c => c.Remarks);
cols.Bound(c => c.CheckedBy);
cols.Bound(c => c.ApprovedBy);
})
.ClientEvents(clientEvents => clientEvents.OnRowSelect("onRowSelected"))
.RowAction(row =>
{
row.Selected = row.DataItem.PurchaseRequestID.Equals(ViewData["id"]);
})
.Pageable()
.Sortable()
.Filterable()
.Selectable()
)
====Second GRID=====
This the the second Grid that will be populated based on the selected record on the first grid
#(Html.Telerik().Grid<PurchaseRequestDetail>().HtmlAttributes(new { style = "width: 50%" })
.Name("grdDetails")
.DataKeys(keys => keys
.Add(o => o.PurchaseRequestDetailID)
.RouteKey("PurchaseRequestDetailID"))
.Columns(cols =>
{
cols.ForeignKey(c => c.ItemID, (System.Collections.IEnumerable)ViewData["prItems"],
"ItemID", "ItemName").Width(200).Title("Description");
cols.Bound(d => d.ItemQuantity).Width(100).Title("Quantity");
cols.Bound(d => d.ItemValue).Width(100).Title("Value per quantity").Format("Php {0:###,###.00}");
cols.Bound(d => d.TotalPrice).Width(500).Format("Php {0:###,###.00}")
.Aggregate(aggs => aggs.Sum())
.ClientFooterTemplate("Php <#= $.telerik.formatString('{0:n}', Sum) #>");
})
.DataBinding(binding => binding.Ajax()
.Select("GetPurchaseRequestDetails", "PurchaseOrder", new { purchaseRequestID = "<#= PurchaseRequestID #>" }))
.ClientEvents(clientEvents => clientEvents.OnDataBinding("onDataBinding"))
.Pageable()
.Sortable()
)
the Script code
<script type="text/javascript">
var purchaseRequestID;
var purchaseRequestName;
function onRowSelected(e) {
var detailsGrid = $('#grdDetails').data('tGrid');
purchaseRequestID = e.row.cells[0].innerHTML;
purchaseRequestName = e.row.cells[1].innerHTML;
// update ui text
$('#purchaseRequestName').text(purchaseRequestName);
// rebind the related grid
//alert(purchaseRequestID);
//location.href = "/PurchaseOrder/Index/" + purchaseRequestID;
detailsGrid.rebind();
}
function onDataBinding(e) {
e.data = $.extend(e.data, { purchaseRequestID: purchaseRequestID });
}
below is the code in the controller:
[HttpPost]
public ActionResult Create(PurchaseOrder purchaseorder)
{
if (ModelState.IsValid)
{
HERE, I WANT TO BE ABLE TO GET AND SAVE THE SELECTED ROW IN THE VIEW
//purchaseorder.PurchaseRequestID = ViewBag.SelectedID;
db.PurchaseOrders.Add(purchaseorder);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.SupplierID = new SelectList(db.Suppliers, "SupplierID", "Name", purchaseorder.SupplierID);
ViewBag.OfficeID = new SelectList(db.Offices, "OfficeID", "OfficeName", purchaseorder.OfficeID);
return View(purchaseorder);
}
Thanks
In case some of you might encounter the same problem,
I used the HiddenFor to solve this. Please suggest if you have a better way than this.
#Html.HiddenFor(model => model.PurchaseRequestID)
and then i updated the script
<script type="text/javascript">
var purchaseRequestID;
var purchaseRequestName;
function onRowSelected(e) {
var detailsGrid = $('#grdDetails').data('tGrid');
purchaseRequestID = e.row.cells[0].innerHTML;
purchaseRequestName = e.row.cells[1].innerHTML;
// update ui text
$('#purchaseRequestName').text(purchaseRequestName);
$('#PurchaseRequestID').val(purchaseRequestID);
detailsGrid.rebind();
}
function onDataBinding(e) {
e.data = $.extend(e.data, { purchaseRequestID: purchaseRequestID });
}

Resources