I am migrating my application form MVC Extension to the Telerik UI for ASP.NET MVC. Changed the grid to:
#(Html.Kendo().Grid((IEnumerable<vw_Client_info>)ViewBag.Clients)
.Name("Clients")
.Columns(columns =>
{
columns.Bound(c => c.ClientID).Width(30).Title("Client ID").Hidden();
columns.Bound(c => c.FullName).Width(130);
})
.DataSource(dataSource => dataSource
.Ajax()
.Model(model => model.Id(p => p.ClientID))
.Read(read => read.Action("AllClientsSelection", "Visit")))
.Selectable()
.Events(events =>
{ events.Change("onRowSelected"); })
.RowAction(row => row.Selected = row.DataItem.ClientID.Equals(ViewData["id"]))
)
To get the cell value, I used before :
function onRowSelected(e) {
var detailGrid = $('#Visit').data('tGrid');
id = e.row.cells[0].innerHTML;
fullname = e.row.cells[1].innerHTML;
$('#ClientFullName').text(fullname);
detailGrid.rebind();
}
This works with Telerik MVC Extensions , but not with the new version, I get this error:
Unable to get property 'cells' of undefined or null reference.
I tried to use:
function onRowSelected(e) {
var detailGrid = $('#Visit').data('kendoGrid');
var id = e.row.ClientID;
var fullname = e.row.FullName;
$('#ClientFullName').text(fullname);
detailGrid.rebind();
}
I get this error:
Unable to get property 'ClientID' of undefined or null reference
I found the answer:
var grid = $("#Clients").data("kendoGrid");
var selectedItem = grid.dataItem(grid.select());
id = selectedItem.ClientID;
fullname = selectedItem.FullName;
This is due to the fact that the value of 'row' in:
var id = e.row.ClientID;
is null. So you might want to check if row is null before setting ClientID or cells[0] or cells[1] to the variables. So perhaps:
var id = null;
if(e.row != null)
id = e.row.ClientId
However, I think you might need to debug and find out if you're getting any 'row' count at all, though. Because if there is no 'row' then there is no 'row.ClientId' .
Related
ok, I have a situation where I need to have multiple DDLs of 'BayTypes' that use the same dictionary, which isn't a problem. One DDL for each of 'n' BayOptions. I'm passing a dictionary to my view as 'BayTypes' like this:
(Controller)
var bayTypes = _bayTypeRepository.GetBayTypes().ToList();
property.BayTypes = bayTypes.ToDictionary(g => g.Name, g => g.BayTypeGuid.ToString());
(View)
var overrideValue = item.BayTypeOverride ? item.BayTypeOverrideValue.BayTypeGuid.ToString() : string.Empty;
var result = (from x in Model.BayTypes
select new SelectListItem()
{
Text = x.Key,
Value = x.Value,
Selected = x.Value == overrideValue <-- ***this is working***
});
if (item.BayTypeOverride == true)
{
#Html.DropDownListFor(x => x.BayTypes, result, new { #Name = "BayOptionsToSubmit[" + aCounter + "].BayTypeOverrideValue" })
}
else
{
#Html.DropDownListFor(x => x.BayTypes, result, new { #Name = "BayOptionsToSubmit[" + aCounter + "].BayTypeOverrideValue", #style = "display:none;" })
}
The correct item IS getting selected in the 'result' object. If I step through, and watch 'result', I can see that 'Selected = true' for the right one... but it's not selecting in the DDLFor when it renders...
What am I missing?
Ultimately, what determines the "selected" item in a drop down is ModelState, not the SelectListItem.Selected property. ModelState is composed from the following sources: Request, ViewData, ViewBag, and finally Model.
Check the values of Request["BayTypes"], ViewData["BayTypes"], ViewBag.BayTypes, and Model.BayTypes. If any of those has a different value from what you're expecting to be selected, that's your problem, particularly if the value is not even in the ballpark.
For example, a common cause of this is developers storing their actual select list choices in something like ViewBag.Foo and then trying to apply that to a dropdown bound to Model.Foo. The select list itself at that point becomes the selected item in ModelState, rather than the one particular value you selected.
Solved it... Changed to a .DropDownList (no 'For') and passed in the 'name' as the 'result' var created earlier. Works.
var overrideValue = item.BayTypeOverride ? item.BayTypeOverrideValue.BayTypeGuid.ToString() : string.Empty;
var result = (from x in Model.BayTypes
select new SelectListItem()
{
Text = x.Key,
Value = x.Value,
Selected = x.Value == overrideValue
});
if (item.BayTypeOverride)
{
#Html.DropDownList("result", result, htmlAttributes: new { #Name = "BayOptionsToSubmit[" + aCounter + "].BayTypeOverrideValue" })
}
else
{
#Html.DropDownList("result", result, htmlAttributes: new { #Name = "BayOptionsToSubmit[" + aCounter + "].BayTypeOverrideValue", #style = "display:none;" })
}
Im trying to use incell editing and use of the http://demos.telerik.com/aspnet-mvc/grid/editing-custom but is can't find my partial view that the dropdownlist should be rendered from.
Partial view (Testview.cshtml)
#using Kendo.Mvc.UI
#(Html.Kendo().DropDownList()
.Name("ResourceType") // Name of the widget should be the same as the name of the property
.DataValueField("Id") // The value of the dropdown is taken from the EmployeeID property
.DataTextField("Name") // The text of the items is taken from the EmployeeName property
.BindTo((System.Collections.IEnumerable)ViewData["defaultResourceType"]) // A list of all employees which is populated in the controller
)
This is my grid:
#(Html.Kendo().Grid<RMS.Admin.ViewModel>()
.Name("ResourceGrid")
.Columns(columns =>
{
columns.Bound(c => c.ResourceId).Hidden();
columns.Bound(c => c.ResourceName);
columns.Bound(c => c.Descritption);
columns.Bound(c => c.ResourceType.Name).ClientTemplate("#=ResourceType.Name#");
columns.Bound(c => c.Approved);
columns.Bound(c => c.IsEnabled);
columns.Command(command =>
{
command.Edit();
command.Destroy();
}).Width(172).Title("Edit/Delete");
})
.ToolBar(toolbar => toolbar.Create())
.Editable(editable => editable.Mode(GridEditMode.InCell))
.Scrollable()
.Sortable()
.Pageable(pageable => pageable
.Refresh(true)
.PageSizes(true)
.ButtonCount(5))
.DataSource(dataSource => dataSource
.Ajax()
.Model(model =>
{
model.Id(s => s.ResourceId);
model.Field(s => s.ResourceType).DefaultValue(ViewData["defaultResourceType"] as RMS.Admin.ViewModel.ResourceTypeId);
})
.Create(update => update.Action("CreateResource", "Home"))
.Read(read => read.Action("ReadResource", "Home"))
.Update(update => update.Action("SaveSystem", "Home"))
.Destroy(destroy => destroy.Action("RemoveSystem", "Home"))
)
)
Here is a part of my model:
public string ResourceUserId { get; set; }
[UIHint("Testview")]
public ResourceTypeId ResourceType { get; set; }
This is in my controller where i bind the data:
private void GetResourceTypeId()
{
//string [] list = new string[]{"Image", "Document", "Other"};
IList<ViewModel.ResourceTypeId> list = new List<ViewModel.ResourceTypeId>();
var a = new ViewModel.ResourceTypeId
{
Name = "Image",
Id = 1
};
var b = new ViewModel.ResourceTypeId
{
Name = "Document",
Id = 2
};
var c = new ViewModel.ResourceTypeId
{
Name = "Other",
Id = 3
};
list.Add(a);
list.Add(b);
list.Add(c);
ViewData["defaultResourceType"] = list.First();
}
I get this error when trying to render the grid:
The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable. Please review the following URL and make sure that it is spelled correctly.
What am i missing?
First off your trying to bind just to one item with ViewData["defaultResourceType"] = list.First();. Instead you should bind to your whole list and then set the default option with .Value("1") so that it has "Images" by default.
#(Html.Kendo().DropDownList()
.Name("ResourceType")
.DataValueField("Id")
.DataTextField("Name")
.BindTo((System.Collections.IEnumerable)ViewData["ResourceTypeList"])
.Value(ViewData["DefaultResourceType"])
);
Also for a template for a column in MVC you may just want to set it with EditorTemplateName
columns.Bound(e => e.myColumn).EditorTemplateName("dropdownTemplate")
And then define the template that you want to use somewhere else on the page.
<script id="dropdownTemplate" type="text/x-kendo-template">
#(Html.Kendo().DropDownList()
.Name("myDropDown")
.....
.ToClientTemplate()
)
</script>
If you would like you can also declare it as a stand alone template in your /Views/Shared/ folder. You would not have to add the .ToClientTemplate() or the script tags. You would reference it by the file name. You could then use the template on multiple pages in the project.
I have a Kendo grid:
#(Html.Kendo().Grid<Grid>().Name("Grid")
.DataSource(ds => ds
.Ajax()
.Model(model => model.Id(m => m.ID))
.Read(read => read.Action("Grid_Read", "Sessions", new {sessionId = ViewBag.SessionID}))
.Update(update =>
update.Action("Grid_Update", "Sessions", new {
sessionId = ViewBag.SessionID, qcStateId = '????'}))
.PageSize(10)
.Batch(true)
)
.ToolBar(toolbar =>
{
toolbar.Template(
"| Set selected to: " + #Html.Partial("EditorTemplates/QCStatusHeader"));
}
)
QCStatusHeader:
#(Html.Kendo().DropDownList()
.Name("QCStatusHeader")
.DataValueField("Id")
.DataTextField("Name")
.BindTo((List<NomadBase.Web.ViewModels.Shared.QCStateViewModel>)ViewBag.PossibleQCStatesHeader)
)
How do I get the selected value from the QCStatusHeader dropdownlist into my update call to the controller?
Pretty simple solution, add the .Data option with a javascript method to return the currently selected value of the ddl.
.Update(update => update.Action("Grid_Update", "Sessions", new {sessionId = ViewBag.SessionID})
.Data("QCStatusHeaderValue"))
function QCStatusHeaderValue() {
var value = $('#QCStatusHeader').data("kendoDropDownList").value();
return { qcStateId: value };
}
I am using the following code. Can anybody tell me how will I use the page number instead of scroll bar?
My Index.cshtml page will be like
<div id="CustomerProfile">
<div id="GridCusotmerProfile">
#(Html.Kendo().Grid(Model)
.Name("grdCustomerProfile")
.Columns(coloumns =>
{
coloumns.Bound(p => p.CustomerID).Title("Customer ID");
coloumns.Bound(p => p.UserId).Title("User Id");
coloumns.Bound(p => p.ComapnyName).Title("Company Name");
coloumns.Bound(p => p.ContactPerson).Title("Contact Person");
coloumns.Bound(p => p.AccountNumber).Title("Account Number");
}
)
.Sortable()
.Scrollable(scrollable => scrollable.Virtual(true))
.HtmlAttributes(new { style = "height:430px;" })
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(10)
.Read(read => read.Action("Virtualization_Read", "CustomerProfile"))
)
)
</div>
My Controller will be like the following
public List<CustomerProfileModel> CustomerDataSource(int page, int pagesize, int skip, int take)
{
List<CustomerProfileModel> ModelData = new List<CustomerProfileModel>();
take = skip + take + (page * 10);
var CustomerData = (from cp in context.CustomerProfile select cp).OrderBy(x => x.ComapnyName).Take(take).Skip(skip).ToList();
foreach (var items in CustomerData)
{
CustomerProfileModel Model = new CustomerProfileModel();
Model.CustomerID = items.CustomerID;
Model.AccountNumber = items.AccountNumber;
Model.ComapnyName = items.ComapnyName;
Model.ContactPerson = items.ContactPerson;
Model.UserId = items.UserId;
ModelData.Add(Model);
}
return ModelData;
}
public ActionResult Virtualization_Read([DataSourceRequest] DataSourceRequest request, string page,string pagesize,string skip,string take)
{
return Json(CustomerDataSource(Convert.ToInt32(page),Convert.ToInt32(pagesize),Convert.ToInt32(skip),Convert.ToInt32(take)).ToDataSourceResult(request),JsonRequestBehavior.AllowGet);
}
public List<CustomerProfileModel> CustomerDataSource(int page, int pagesize, int skip, int take)
{
List<CustomerProfileModel> ModelData = new List<CustomerProfileModel>();
take = skip + take + (page * 10);
var CustomerData = (from cp in context.CustomerProfile select cp).OrderBy(x => x.ComapnyName).Take(take).Skip(skip).ToList();
foreach (var items in CustomerData)
{
CustomerProfileModel Model = new CustomerProfileModel();
Model.CustomerID = items.CustomerID;
Model.AccountNumber = items.AccountNumber;
Model.ComapnyName = items.ComapnyName;
Model.ContactPerson = items.ContactPerson;
Model.UserId = items.UserId;
ModelData.Add(Model);
}
return ModelData;
}
public ActionResult Virtualization_Read([DataSourceRequest] DataSourceRequest request, string page,string pagesize,string skip,string take)
{
return Json(CustomerDataSource(Convert.ToInt32(page),Convert.ToInt32(pagesize),Convert.ToInt32(skip),Convert.ToInt32(take)).ToDataSourceResult(request),JsonRequestBehavior.AllowGet);
}
Please let me know if I need something else to get data as lazy loading.
Your on the right tracks, but it is actually a lot easier than you think. Your trying to hand roll functionality that Kendo handles with the `ToDataSourceResult() extension method.
The DataSourceRequest contains all the information needed for database operations, such as ordering, aggregates and paging. So you can simplfy your code down to pretty much the following (NOT TESTED)
public ActionResult Virtualization_Read([DataSourceRequest] DataSourceRequest request)
{
var CustomerData = (from cp in context.CustomerProfile select cp); // don't call toList() this exectues the SQL and pulls data into memory, leave it as a Queryable object so we can pass it to kendo to add its expressions this will the be a Database operation
DataSourceResult result = CustomerData.ToDataSourceResult(request, x => new CustomerProfileModel(){
CustomerID = x.CustomerID;
AccountNumber = x.AccountNumber;
ComapnyName = x.ComapnyName;
ContactPerson = x.ContactPerson;
UserId = x.UserId;
});
return Json(result);
}
For further reading take a look at this link:
http://docs.kendoui.com/getting-started/using-kendo-with/aspnet-mvc/helpers/grid/ajax-binding
From the Kendo Site:
How do I implement paging, sorting, filtering and grouping?
If your model supports the IQueryable interface or is DataTable the grid will do paging, sorting, filtering, grouping and aggregates automatically. For server binding scenarios no additional steps are required - just pass the IQueryable to the Grid constructor. Check the server binding help topic for additional info.
For ajax binding scenarios the ToDataSourceResult extension method must be used to perform the data processing. Check the ajax binding help topic for additional information. If your model does not implement IQueryable custom binding should be implemented. This means that the developer is responsible for paging, sorting, filtering and grouping the data. More info can be found in the custom binding help topic.
Important:
All data operations will be performed at database server level if the underlying IQueryable provider supports translation of expression trees to SQL. Kendo Grid for ASP.NET MVC has been tested with the following frameworks:
Entity Framework
Linq to SQL
Telerik OpenAccess
NHibernate
.Columns(columns =>
{
columns.Bound(p => p.ID).Title("ID").Width(100).Visible(false);
columns.Bound(p => p.Apply).Title("Apply").Width(100);
columns.Bound(p => p.TaxName).Title("Tax Name").Width(100);
columns.Bound(p => p.TaxPercent).Title("Percent").Width(130);
columns.Bound(p => p.OrderApplied).Title("Oreder Applied").Width(130);
columns.Bound(p => p.Compund).Title("Compund").Width(130);
columns.Command(command => { command.Edit(); command.Destroy(); }).Width(172);
})
.ToolBar(toolbar => toolbar.Create())
.Editable(editable => editable.Mode(GridEditMode.InLine))
.Pageable()
.Sortable()
.Scrollable(scr=>scr.Height(430))
//.Scrollable(scrollable => scrollable.Virtual(true))
.HtmlAttributes(new { style = "height:430px;" })
.Filterable()
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(10)
.Events(events => events.Error("error_handler"))
.Model(model => model.Id(p => p.ID))
.ServerOperation(false)
.Create(update => update.Action("EditingInline_Create", "Taxes"))
.Read(read => read.Action("EditingInline_Read", "Taxes"))
.Update(update => update.Action("EditingInline_Update", "Taxes"))
.Destroy(update => update.Action("EditingInline_Destroy", "Taxes"))
)
)
I work with Telerik-MVC and I'm trying to rebind a grid when I change the value of a combobox. Everything seems working except I can't get selected value of my combobox.
Here is my code :
Grid :
#{Html.Telerik().Grid(Model)
.Name("Grid")
.Columns(columns =>
{
columns.Bound(o => o.Col1);
columns.Bound(o => o.Col2);
columns.Bound(o => o.Col3);
})
.DataBinding(dataBinding => dataBinding.Ajax()
.Select("_MyAction", "MyController")
)
.ClientEvents(events => events.OnDataBinding("Grid_onDataBinding"))
}
Combobox :
#(Html.Telerik().ComboBox()
.Name("ComboBox")
.HtmlAttributes(new { id = "ComboBoxCode" })
.BindTo(new SelectList(Model.GroupBy(x => x.Code)
.Select(o => o.First()).ToList(),
"Code", "Code"))
.ClientEvents(events => events
.OnChange("onComboBoxChange")
)
)
Script :
function onComboBoxChange(e) {
$("#Grid").data("tGrid").rebind();
}
function Grid_onDataBinding(e) {
var code = /* I need to get the combobox value here */;
e.data = { myCode: code };
}
Controller :
[GridAction]
public ActionResult _MyAction(string myCode)
{
Console.WriteLine("Code : " + code);
/*
Set new model here
*/
return View(new GridModel(newModel));
}
I tried things like :
var e = document.getElementById("ComboBoxCode");
var code = e.options[e.selectedIndex].text;
But it doesn't work. Can you tell me how to fix this problem and get the right value ?
The problem is that when you rebind the grid, you didn't really use the ComboBox selected value. Your onComboBoxChange function tells the grid to rebind, which it does by going to the _MyAction method. At no point did you pass in the ComboBox value. What you should do is before databinding, grab the selected value and pass it to your controller action. See http://www.telerik.com/help/aspnet-mvc/telerik-ui-components-grid-client-api-and-events.html#OnDataBinding for details. Something like this:
function Grid_onDataBinding(e) {
var combobox = $('#ComboBox').data('tComboBox');
e.data = { code: combobox.value };
}
(Note that I actually haven't done any work with the ComboBox, so this isn't tested, but this should at least get you on the right path. See ComboBox documentation.)