Kendo MVC Wrappers client side validation - asp.net-mvc

I'm using the Kendo UI Server Side Wrappers to create a grid to manage (CRUD) a list of messages in our system. The model is very simple and it only requires that the message is 150 characters or less. To enforce the message length I'm using the following data annotation in my model:
[StringLength(150, ErrorMessage = "Message exceeded the maximum length allowed. Please ensure you message is no longer than 150 characters")]
Here's what my grid looks like:
#model OperatorMessageListModel
#{
TransactionStatusType status = Model.TransactionStatus;
ViewBag.Title = String.Format("{0} Transaction Operator Messages", status);
string header = string.Format("{0} Transaction Messages", status);
string messagesTableId = string.Format("{0}TransactionOperatorMessagesGrid", status);
}
<h2>#header</h2>
#(Html.Kendo().Grid(Model.OperatorMessages)
.Name(messagesTableId)
.TableHtmlAttributes(new { style = "width: 50% height:75%" })
.Columns(columns =>
{
columns.Bound(m => m.Message).Title("");
columns.Bound(m => m.Index).Hidden(true);
if (!Model.IsInherited) //only edit if you own the list and there's anyhting to edit
{
columns.Command(cmd =>
{
cmd.Edit().UpdateText("Save");
cmd.Destroy();
}).Width("20%");
}
})
.Pageable()
.Scrollable(s => s.Enabled(false))
.ToolBar(cmd =>
{
if (!Model.IsInherited) //you can add messages to the lists that you own
{
cmd.Create().Text("Add new message");
}
if (!Model.OwnedByRoot && Model.OperatorMessages.Any()) //if the root owns this it can't override or inherit its own list.
{
var actionName = Model.IsInherited ? "OverrideTrasactionMessageList" : "InheritTrasactionMessageList";
cmd.Custom().Text(Model.OverrideOrInheritButtonText).Action(actionName, "OperatorMessage", new { Model.OrgId, Model.TransactionStatus });
}
}
)
.Editable(editable => editable.Mode(GridEditMode.InLine))
.DataSource(ds => ds
.Server()
.Model(model => model.Id(m => m.Index))
.Create(c => c.Action("CreateTransactionMessage", "OperatorMessage", new { #Model.OrgId, #Model.TransactionStatus }))
.Read(c => c.Action("List", "OperatorMessage", new { #Model.OrgId, #Model.TransactionStatus }))
.Update(c => c.Action("EditTransactionMessage", "OperatorMessage"))
.Destroy(c => c.Action("DeleteTrasactionMessage", "OperatorMessage"))
)
)
Here's the controller code:
[HttpPost]
public ActionResult CreateTransactionMessage([DataSourceRequest] DataSourceRequest request,
OperatorMessageModel newMessage, string OrgId,
string TransactionStatus)
{
_transactionOperatorMessageService.AddOperatorMessage(OrgId, TransactionStatus, newMessage,
CurrentUser.Name());
return RedirectToAction("List", new {OrgId, TransactionStatus});
}
When the user enters a message longer than 150 characters, I expect the validation message to be displayed to the user. Additionally, the form not to be posted back to the controller. Everything works as expcted in Chrome and Firefox. However, in IE8 the message is displayed but the form is still posted back to the controller. Has anyone seen this?

Related

Kendo Grid: Foreign Key Dropdown does not update grid cell after update

I have a Kendo MVC grid that contains a nullable property (short) that is bound as a foreign key and uses a dropdown list as an editor template. I am also using inline editing.
When the property value is null, the dropdown list selected value does not get set into the grid cell after the update button is clicked. This works fine if incell editing is used. I am looking for a workaround that will solve my problem. I am including a stripped down version of my code below
Everything works if the nullable value is set to a non-null value.
GRID
#(Html.Kendo().Grid<AssetViewModel>()
.Name("DealAssets")
.Columns(c =>
{
c.Bound(x => x.Name);
c.ForeignKey(x => x.AssetTypeID, (IEnumerable<SelectListItem>)ViewBag.AssetTypeList, "Value", "Text");
c.ForeignKey(x => x.SeniorityTypeID, seniorityTypeList, "Value", "Text").EditorTemplateName("GridNullableForeignKey");
c.ForeignKey(x => x.RateBaseID, rateBaseList, "Value", "Text").EditorTemplateName("GridNullableForeignKey"); ;
c.Command(m => { m.Edit(); m.Destroy(); });
})
.ToolBar(toolbar => toolbar.Create().Text("Add New Asset"))
.Editable(x => x.Mode(GridEditMode.InLine))
.DataSource(ds => ds
.Ajax()
.Model(model => model.Id(request => request.ID))
.Read(read => read.Action("ReadAssets", "Deal", new { id = Model.ID }))
.Create(create => create.Action("CreateAsset", "Deal", new { currentDealID = Model.ID }))
.Update(update => update.Action("UpdateAsset", "Deal"))
.Destroy(destroy => destroy.Action("DeleteAsset", "Deal"))
)
)
EDITOR TEMPLATE
#model short?
#{
var controlName = ViewData.TemplateInfo.GetFullHtmlFieldName("");
}
#(
Html.Kendo().DropDownListFor(m => m)
.Name(controlName)
.OptionLabel("- Please select -")
.BindTo((SelectList)ViewData[ViewData.TemplateInfo.GetFullHtmlFieldName("") + "_Data"])
)
UPDATE ACTION
public ActionResult UpdateAsset([DataSourceRequest] DataSourceRequest request, int ID)
{
var dealAsset = DataContext.DealAssets.SingleOrDefault(o => o.ID == ID);
if (dealAsset != null)
{
if (TryUpdateModel(dealAsset.Asset, new[] {"Name","AssetTypeID","SeniorityTypeID","RateBaseID" }))
{
DataContext.SaveChanges();
}
}
return Json(new[] { new AssetViewModel(dealAsset) }.ToDataSourceResult(request, ModelState), JsonRequestBehavior.AllowGet);
}
Telerik just recently added a new HTML attribute, data_value_primitive, to their selectlist that addresses the issue above. The new attribute should be added in the foreign key editor template and set to true.
Html.Kendo().DropDownListFor(m => m)
.Name(controlName)
.OptionLabel("- Please select -")
.BindTo((SelectList)ViewData[ViewData.TemplateInfo.GetFullHtmlFieldName("") + "_Data"])
**.HtmlAttributes(new { data_value_primitive = true})**
This last section is a modification to the update method to account for the grid not passing back null properties when doing the ajax call. I think this has more to do with how the TryUpdateModel method works
...
if (TryUpdateModel(dealAsset.Asset, new[] {"Name","AssetTypeID","SeniorityTypeID","RateBaseID" }))
{
// If no property passed back then set it to null
var senorityTypeID = ValueProvider.GetValue("SeniorityTypeID");
if (senorityTypeID == null)
{
dealAsset.Asset.SeniorityTypeID = null;
} else {
dealAsset.Asset.SeniorityTypeID = (short)senorityTypeID.ConvertTo(typeof(short));
}
var rateBaseID = ValueProvider.GetValue("RateBaseID");
if (rateBaseID == null)
{
dealAsset.Asset.RateBaseID = null;
} else {
dealAsset.Asset.RateBaseID = (byte)rateBaseID.ConvertTo(typeof(byte));
}
DataContext.SaveChanges();
}
'''

KendoUI Grid Ajax Binding Parameters For Select

I have a basic KendoUI Grid for my ASP.NET MVC app which uses ajax binding for the read. I'd like to enhance this so that a Form above the grid is used to help select data that should be displayed in the grid. This is a standard search form with basic fields like First Name, Last Name, Date of Birth, Customer Source, etc. with a search button. When the search button is pressed, I want to force the grid to go get the data that meets the criteria from the controller by passing in the Search Model with the fields I referenced above.
The search form is contained within the _CustomerSearch partial view.
I've implemented this sort of thing before with the Telerik MVC extensions by tapping into the OnDataBinding client event and updating the parameter values there and then manually making the Ajax call to get the data. It doesn't appear KendoUI will operate this same way.
View
#Html.Partial("_CustomerSearch", Model)
<hr>
#(Html.Kendo().Grid<ViewModels.CustomerModel>()
.Name("Grid")
.Columns(columns =>
{
columns.Bound(p => p.Id).Hidden(true);
columns.Bound(p => p.FirstName);
columns.Bound(p => p.LastName);
columns.Bound(p => p.DateOfBirth).Format("{0:MM/dd/yyyy}");
columns.Bound(p => p.IsActive);
})
.Scrollable()
.Filterable()
.Sortable()
.DataSource(dataSource => dataSource
.Ajax()
.Read(read => read.Action("_Search", "Customer"))
)
)
Controller
public ActionResult _Search([DataSourceRequest]DataSourceRequest request)
{
return Json(DataService.GetCustomers2().ToDataSourceResult(request));
}
I envision the controller looking something like this, but can't find any examples of anything being implemented this way, which is what I need help with.
public ActionResult _Search([DataSourceRequest]DataSourceRequest request, CustomerSearchModel customerSearchModel)
{
return Json(DataService.GetCustomers2(customerSearchModel)
.ToDataSourceResult(request));
}
Nicholas answer could work if your requirements can be solved with the built in filtering. But if your requirements can be solved with the built filtering why do you want to create a custom search form?
So I suppose you have a reason to do the search manually so here is how we've done it in our project (so maybe there is more easier way but still this worked for us):
The controller action is fine:
public ActionResult _Search([DataSourceRequest]DataSourceRequest request,
CustomerSearchModel customerSearchModel)
{
return Json(DataService.GetCustomers2(customerSearchModel)
.ToDataSourceResult(request));
}
Next step: you need a JavaScript function which collects the data from the search form (the property names of the JS object should match the property names of your CustomerSearchModel) :
function getAdditionalData() {
// Reserved property names
// used by DataSourceRequest: sort, page, pageSize, group, filter
return {
FirstName: $("#FirstName").val(),
LastName: $("#LastName").val(),
//...
};
}
Then you can configure this function to be called on each read:
.DataSource(dataSource => dataSource
.Ajax()
.Read(read => read.Action("_Search", "Customer")
.Data("getAdditionalData"))
)
Finally in your button click you just need to refresh the grid with:
$('#Grid').data('kendoGrid').dataSource.fetch();
You can set the filters on the grid by calling filter on the grid's data source.
So in your button's onclick handler function, put something like this:
var $Grid = $('#Grid').data('kendoGrid');
$Grid.dataSource.filter([
{ field: 'FirstName', operator: 'eq', value: $('#firstName').val() },
{ field: 'LastName', operator: 'eq', value: $('#lastName').val() }
]);
Here's a link to the Kendo docs: DataSource.filter
Refer Pass Additional Data to the Action Method
To pass additional parameters to the action use the Data method. Provide the name of a JavaScript function which will return a JavaScript object with the additional data:
A working Search example listed below:
Important: type="button" for the button; And AutoBind(false) for Grid; otherwise, it won’t work
VIEW
#model IEnumerable<KendoUIMvcSample.Models.Sample>
#{
ViewBag.Title = "Index";
}
<script type="text/javascript">
function getAdditionalData()
{
return {
FirstName: 'A',
LastName: 'B',
};
}
$(document).ready(function ()
{
$('#Submit1').click(function ()
{
alert('Button Clicked');
//Refresh the grid
$('#ssgrid222').data('kendoGrid').dataSource.fetch();
});
});
</script>
<h2>Index</h2>
#using (Html.BeginForm())
{
#(Html.Kendo().Grid<KendoUIMvcSample.Models.Sample>()
.Name("ssgrid222")
.Columns(columns => {
columns.Bound(p => p.SampleDescription).Filterable(false).Width(100);
columns.Bound(p => p.SampleCode).Filterable(false).Width(100);
columns.Bound(p => p.SampleItems).Filterable(false).Width(100);
})
.AutoBind(false)
.Pageable()
.Sortable()
.Scrollable()
.Filterable()
.HtmlAttributes(new { style = "height:430px;" })
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(20)
.Read(read => read.Action("Orders_Read", "Sample")
.Data("getAdditionalData"))
)
)
<input id="Submit1" type="button" value="SubmitValue" />
}
Controller
namespace KendoUIMvcSample.Controllers
{
public class SampleController : Controller
{
public ActionResult Index()
{
SampleModel AddSample = new SampleModel();
Sample s1 = new Sample();
return View(GetSamples());
}
public static IEnumerable<Sample> GetSamples()
{
List<Sample> sampleAdd = new List<Sample>();
Sample s12 = new Sample();
s12.SampleCode = "123se";
s12.SampleDescription = "GOOD";
s12.SampleItems = "newone";
Sample s2 = new Sample();
s2.SampleCode = "234se";
s2.SampleDescription = "Average";
s2.SampleItems = "oldone";
sampleAdd.Add(s12);
sampleAdd.Add(s2);
return sampleAdd;
}
public ActionResult Orders_Read([DataSourceRequest]DataSourceRequest request, CustomerSearchModel customerSearchModel)
{
string firstParam = customerSearchModel.FirstName;
return Json(GetOrders().ToDataSourceResult(request));
}
private static IEnumerable<Sample> GetOrders()
{
return GetSamples();
}
}
public class CustomerSearchModel
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
}
Model
namespace KendoUIMvcSample.Models
{
public class SampleModel
{
public List<Sample> samples;
}
public class Sample
{
public string SampleDescription { get; set; }
public string SampleCode { get; set; }
public string SampleItems { get; set; }
}
}

Telerik MVC Grid Master Detail Cascading Dropdowns

I am using a master-detail Telerik MVC Grid on two levels.
The first level contains a drop-down of Customers and some misc data.
The second level contains a drop-down of Cars that are linked to the customer on the first level and some misc data.
I am now using a foreign key column to show the dropdowns of cars and clients.
How can the second dropdown be filtered by the customer on the first level?
Code:
#(Html.Telerik().Grid<Models.ClientsModel>()
.Name("Grid")
.ToolBar(commands => commands.Insert().ButtonType(GridButtonType.ImageAndText))
.DataKeys(keys => keys.Add(c => c.ClientLineID))
.Columns(columns =>
{
columns.ForeignKey(o => o.ClientID, (System.Collections.IEnumerable)ViewBag.Client, "ClientID", "Name")
.Width(330)
.Title("Client");
columns.Command(commands =>
{
commands.Edit().ButtonType(GridButtonType.ImageAndText);
commands.Delete().ButtonType(GridButtonType.ImageAndText);
}).Width(250);
})
.DetailView(car => car.ClientTemplate(
Html.Telerik().Grid<Delta.Models.CarModel>()
.Name("Car_<#= ClientID #>")
.DataKeys(keys => keys.Add(c => c.LineID))
.ToolBar(commands => commands.Insert().ButtonType(GridButtonType.ImageAndText))
.DataBinding(dataBinding =>
{
dataBinding.Ajax()
.Select("_CarLineIndex", "Client", new { id = "<#= ClientID #>" })
.Insert("_CarLineCreate", "Client", new { id = "<#= ClientID #>" })
.Update("_CarLineUpdate", "Client")
.Delete("_CarLineDelete", "Client");
})
.Columns(columns =>
{
columns.ForeignKey(o => o.CarID, (System.Collections.IEnumerable)ViewBag.Cars,
"CarID", "No")
.Width(500)
.Title("Car");
columns.Command(commands =>
{
commands.Edit().ButtonType(GridButtonType.ImageAndText);
commands.Delete().ButtonType(GridButtonType.ImageAndText);
}).Width(200);
})
.Editable(editing => editing => editing.Mode(GridEditMode.InLine))
.Scrollable(c => c.Height("auto"))
.Resizable(resizing => resizing.Columns(true))
.Reorderable(reorder => reorder.Columns(true))
.KeyboardNavigation()
.Footer(false)
.ToHtmlString()
))
.DataBinding(dataBinding =>
{
dataBinding.Ajax()
.Select("_ClientIndex", "Client")
.Insert("_ClientCreate", "Client")
.Update("_ClientUpdate", "Client")
.Delete("_ClientDelete", "Client");
})
.Scrollable(c => c.Height("auto"))
.Editable(editing => editing.Mode(GridEditMode.InLine))
.Pageable(o => o.PageSize(50))
.Filterable()
.KeyboardNavigation()
.Groupable())
I am thinking that the code might involve some javascript on the OnDetailViewExpand event, but I can't figure out what.
The only solution I have now is to split the grid into separate views and build cascasing comboboxes there.
Unfortunately I cannot comment on posts yet to clarify some facts about your question. I'll make some assumptions in my answer so that we can work out the exact nature of the problem. You have two model classes one for each grid ClientsModel and CarModel. You are filtering the CarModel (second)grid with fields from the ClientsModel (first)grid.
You are not restricted to just one(<= ClientID =>) parameter in your select binding. You can use other fields from the ClientsModel class the same way as ClientID.
Sample Code:
dataBinding.Ajax().Select("_CarLineIndex", "Client", new { id = "<#= ClientID #>", city = "<#= City #>" })
Here is a working example with mock data that illustrates the method mentioned above:
Client Class
public class Client
{
public int ClientId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string City { get; set; }
}
Car Class
public class Car
{
public string Make { get; set; }
public string Model { get; set; }
public int Year { get; set; }
public string Color { get; set; }
}
HomeController
[GridAction]
public ActionResult _Index()
{
Client c1 = new Client() { ClientId = 1, City = "Boston", FirstName = "Ted", LastName = "Boder" };
Client c2 = new Client() { ClientId = 2, City = "New York", FirstName = "Chris", LastName = "Tobb" };
Client[] clients = {c1, c2};
return View(new GridModel(clients));
}
[GridAction]
public ActionResult _Cars(int ClientId, string City)
{
Car c1 = new Car() { Color = "Yellow", Make = "Ford", Model = "Mustang", Year = 2012 };
Car c2 = new Car() { Color = "Black", Make = "Toyota", Model = "Camry", Year = 2010 };
Car[] cars = { c1, c2 };
return View(new GridModel(cars));
}
View
#(Html.Telerik().Grid<Client>()
.Name("Clients")
.Columns(columns =>
{
columns.Bound(o => o.FirstName);
columns.Bound(o => o.LastName);
columns.Bound(o => o.City);
})
.DetailView(clientDetailView => clientDetailView.ClientTemplate(
Html.Telerik().Grid<Car>()
.Name("ClientDetails_<#= ClientId #>")
.Columns(columns =>
{
columns.Bound(c => c.Make);
columns.Bound(c => c.Model);
columns.Bound(c => c.Year);
columns.Bound(c => c.Color);
})
.DataBinding(db2 => db2.Ajax().Select("_Cars", "Home", new { ClientID = "<#= ClientId #>", City = "<#= City #>" }))
.Pageable()
.Sortable()
.ToHtmlString()
))
.DataBinding(db1 => db1.Ajax().Select("_Index", "Home"))
.Pageable()
.Sortable()
.Filterable()
)
As you can see from the example I'm also passing a City parameter as well as a ClientId when binding the grid.
Let me know if I missed something.
You are correct that you will need to do this with javascript, and it is a matter of being able to filter cars by customers. Telerik allows you to add additional parameters using the "e.data" argument for most of their controls. So for example if you wanted to filter a city list based on a select state the CSHTML would look like this:
<td valign="top">
#(Html.Telerik().DropDownListFor(m => m.State)
.Name("State")
.ClientEvents(events => events.OnChange("State_Change"))
.BindTo(new SelectList(Model.GetStates()))
.HtmlAttributes(new { style = string.Format("width:{0}px", 160) })
)
</td>
<td valign="top">
#(Html.Telerik().AutoCompleteFor(m => m.City)
.Name("City")
.Encode(false)
.ClientEvents(events => {
events.OnDataBinding("City_AutoComplete");
})
.DataBinding(a => a.Ajax().Select("CityList", "Location"))
.AutoFill(true)
.HighlightFirstMatch(true)
.HtmlAttributes(new { style = string.Format("height: 17px; width:{0}px", 250) })
)
</td>
The javascript would look like this:
function City_AutoComplete(e) {
//pass state as an additional parameter here to filter
//this would be your customer for cars list
e.data = $.extend({}, e.data, { state: $("#State").val() });
}
function State_Change(e) {
//reset when the parent list selection changes
$('#City').data('tAutoComplete').text('');
$('#City').data('tAutoComplete').value('');
}
Nothing to complex, create client event onEdit, you can found sample on telerik demo, than after once created client write down dropedown selection change event code that will filter data for you car dropdown. to do this I would suggest you to call ajax and insert HTml for dropdown. If you have still doubt than let me know I will explain it in detail.
If you you really find this answer best or appropriate please vote it.. it will help...

Telerik Grid databinding to call HttpPost method

I am working on ASP.NET MVC and I have a View on which form data is retrieved in the HttpPost action. It works fine when the HttpPost action is called. I use the form data to query a database and the result from the database is bound to a TELERIK Grid control. It displays data fine, but paging is not working.
The issue is that when I try to switch to another page, it calls the HTTPGET action method and not the HttpPost action method and hence no data is retrieved from the database.
Any help is appreciated.
Here is the code for the View and Controller:
//-------------View------------------------------------
#(Html.Telerik().Grid(Model)
.Name("Grid")
.Columns(columns =>
{
columns.Bound(o => o.DealerName);
columns.Bound(o => o.DealerNumber);
columns.Bound(o => o.ServiceDealerNumber);
columns.Bound(o => o.CMDealerNumber);
columns.Bound(o => o.PurchaseDealerNumber);
columns.Bound(o => o.Address);
columns.Bound(o => o.City);
columns.Bound(o => o.State);
columns.Bound(o => o.Zip);
})
.DataBinding(dataBinding =>
{
dataBinding.Server().Select("DealerProfile", "DealerManagement", new { testVal = "test" }).Enabled(true);
dataBinding.Ajax().Select("DealerProfile", "DealerManagement", new { testVal = "test" } ).Enabled(true);
})
.Scrollable(scrolling => scrolling.Enabled(true))
.Sortable(sorting => sorting.Enabled(true))
.Pageable(paging =>
paging.PageSize(20)
.Style(GridPagerStyles.NextPreviousAndNumeric)
.Position(GridPagerPosition.Bottom)
)
.Filterable(filtering => filtering.Enabled(true))
.Groupable(grouping => grouping.Enabled(true))
.Footer(true)
)
//---------------Controller Actions---------------------------------------
//
// GET: /DealerManagement/DealerProfile/
public ActionResult DealerProfile()
{
return View();
}
//
// POST: /DealerManagement/DealerProfile/
[HttpPost]
public ActionResult DealerProfile(FormCollection formValues)
{
string dealerNumber = Request.Form["DealerNumber"];
string dealerName = Request.Form["DealerName"];
DealerProfilesViewModel dealerProfilesViewModel = new DealerProfilesViewModel();
dealerProfilesViewModel.DealerProfiles = new List<DealerProfileViewModel>();
if (!dealerNumber.Trim().Equals(string.Empty))
{
DealerInfoCollection dealers = _iDealerProfileService.GetDealerInfoFromDealerNumber(dealerNumber);
foreach (var item in dealers)
{
DealerProfileViewModel dealerProfileViewModel = new DealerProfileViewModel();
dealerProfileViewModel.DealerName = item.Dealer_Name;
dealerProfileViewModel.DealerNumber = item.Dealer_No;
dealerProfileViewModel.ServiceDealerNumber = item.Service_Dealer_No;
dealerProfileViewModel.CMDealerNumber = item.CM_Dealer_No;
dealerProfileViewModel.PurchaseDealerNumber = item.PUR_Dealer_No;
dealerProfileViewModel.Address = item.Address;
dealerProfileViewModel.City = item.City;
dealerProfileViewModel.State = item.State;
dealerProfileViewModel.Zip = item.Zip;
dealerProfilesViewModel.DealerProfiles.Add(dealerProfileViewModel);
}
}
else if (!dealerName.Trim().Equals(string.Empty))
{
DealerInfoCollection dealers = _iDealerProfileService.GetDealerInfoFromDealerName(dealerName);
foreach (var item in dealers)
{
DealerProfileViewModel dealerProfileViewModel = new DealerProfileViewModel();
dealerProfileViewModel.DealerName = item.Dealer_Name;
dealerProfileViewModel.DealerNumber = item.Dealer_No;
dealerProfileViewModel.ServiceDealerNumber = item.Service_Dealer_No;
dealerProfileViewModel.CMDealerNumber = item.CM_Dealer_No;
dealerProfileViewModel.PurchaseDealerNumber = item.PUR_Dealer_No;
dealerProfileViewModel.Address = item.Address;
dealerProfileViewModel.City = item.City;
dealerProfileViewModel.State = item.State;
dealerProfileViewModel.Zip = item.Zip;
dealerProfilesViewModel.DealerProfiles.Add(dealerProfileViewModel);
}
}
if (!String.IsNullOrEmpty(dealerName) && !String.IsNullOrEmpty(dealerNumber))
{
dealerProfilesViewModel = null;
}
return View(dealerProfilesViewModel.DealerProfiles);
}
First your controller method needs the GridAction attribute. Second it must use the GridModel type as a model. This is required for ajax binding. You can check the ajax binding help article as well as the ajax binding online demo which show what the required steps are. Most probably you should define a separate action method just for the ajax binding.
Lastly it seems that the JavaScript of the grid does not kick in - the fact that it is making HTTP GET requests indicate that. Check that there is a ScriptRegistrar component declared AFTER the grid.

Telerik MVC Grid Edit Template DropDownList problem

I am getting a null value passed to my ajax .Update("_SaveAjaxEditing", "AptProfile") in my controller when using the dropdownlist client Edit Template.
property in my FormViewModel that my grid is bound to:
[UIHint("BuildingsGrid"), Required]
[DisplayName("Building ID")]
public int BuildingID
{
get;
set;
}).
Here is my view:
<%= Html.Telerik().Grid<PayRent.Models.AptProfileFormViewModel1>()
.Name("Profiles")
.DataKeys(dataKeys => dataKeys.Add(c => c.AptProfileID))
.ToolBar(commands => commands.Insert())
.DataBinding(binding =>
{
binding.Ajax()
.Select("GetProfiles", "AptProfile")
.Insert("_InsertAjaxEditing", "AptProfile")
.Update("_SaveAjaxEditing", "AptProfile")
.Delete("_DeleteAjaxEditing", "AptProfile");
})
.Columns(columns =>
{
columns.Bound(o => o.AptProfileID);
columns.Bound(o => o.BuildingID);
columns.Bound(o => o.AptID);
columns.Bound(o => o.AptRate);
columns.Bound(o => o.AptSize);
columns.Bound(o => o.MoveInDate);
columns.Command(s =>
{
s.Edit();
s.Delete();
});
})
.Editable(editing => editing.Mode(GridEditMode.InLine))
.ClientEvents(events => events.OnEdit("onEdit"))
.Pageable()
%>
</p>
<script type="text/javascript">
function onEdit(e) {
// $(e.form).find('#BuildingsGrid').data('tDropDownList').select(function (dataItem) {
// return dataItem.Text == e.dataItem['BuildingGrid'];
// });
}
</script>
My EditTemplate:
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
<%= Html.Telerik().DropDownList()
.Name("BuildingsGrid")
.BindTo(new SelectList((IEnumerable)ViewData["Buildings"], "BuildingID", "Name"))
%>)
Here is my Controller:
[AcceptVerbs(HttpVerbs.Post)]
//[CultureAwareAction]
[GridAction]
public ActionResult _SaveAjaxEditing(int id, int? BuildingGrid)
{
ApartmentProfileRepository repo = new ApartmentProfileRepository();
AptProfile profile = repo.Get(id);
TryUpdateModel(profile);
repo.Save();
return View(new GridModel(GetAllProfiles()));
}
If you want to keep everything Ajax-ified, you have do it without using the viewbag. My combobox is in a separate editor template. All you have to do is return the SelectList as a JsonResult. That said, I only recommended doing it that way if you expect the data in that combobox to change while the user is on the page, because it calls the server method every time the combo is opened.
In my example below, because the user can add a Category on the same page as they're selecting a Category, I need it to hit the server each time. But on other pages, I use server-side binding (via the ViewBag/ViewData) so that it only hits the server once.
My editor template:
#(Html.Telerik().ComboBox()
.Name("YourNameGoesHere")
.DataBinding(binding => binding.Ajax().Select("SelectCategoriesForComboBox","Shared")))
Then in the controller:
public EquipmentEntities db = new EquipmentEntities();
public List<SelectListItem> CategoryList
{
get
{
var m = db.Categories
.Select(e => new{ Id = e.Id, Name = e.Name })
.OrderBy(e => e.name);
List<SelectListItem> sl = new SelectListItem(m.ToList(), "Id", "Name").ToList();
//insert a blank item as the first entry
sl.Insert(0, (new SelectListItem { Text = "", Value = string.Empty }));
return sl;
}
}
[HttpPost]
public ActionResult SelectCategoryForComboBox()
{
return new JsonResult { Data = CategoryList };
}
Maybe I'm a little bit late, but hopefully it helps someone out.
First, you need to match up the name of your column in the view with the name of your edit template and controller action parameter. I don't think the int parameter needs to be nullable in the controller action.
Then in your controller action you need to set the ViewData["Buildings"] for the edit template; then select the current value in your profile object before returning the view.
e.g.
public ActionResult _SaveAjaxEditing(int id, int BuildingsGrid)
{
ApartmentProfileRepository repo = new ApartmentProfileRepository();
AptProfile profile = repo.Get(id);
// Save the building ID in the profile
profile.BuildingID = BuildingsGrid;
TryUpdateModel(profile);
repo.Save();
// Load the Building objects into the ViewData
ViewData["Buildings"] = GetBuildings();
return View(new GridModel(GetAllProfiles()));
}

Resources