I have three column in kendoui grid as "Delivery Location", "PickUp location" and "Available Shipping Options". When either of the location column changed("Delivery location" or "Pickup location"), the "Available shipping options" column should be changed accordingly.
I can achieve this using Cascade-from for two column(i.e. if one column changed, other would list the result based on the first column data) but don't know how to achieve same for two or more column.
How can i achieve cascading for two or more column?
Code:
JS Function:
function filterShippingOptions() {
return { pickUpLocationId: $("#PickUpLocationId").data("kendoDropDownList").value(), deliveryLocationId: $("#deliveryLocationId").data("kendoDropDownList").value() };
}
AvailableShippingOptions Editor:
#(Html.Kendo().DropDownListFor(m => m)
.DataValueField("ShippingOptionId")
.DataTextField("ShippingOptionName")
.OptionLabel("Select...")
.AutoBind(false)
.DataSource(dataSource =>
{
dataSource.Read(read =>
{
read.Action("GetAvailableShippingOptions", "ProductionZone").Type(HttpVerbs.Post)
.Data("filterShippingOptions");
}).ServerFiltering(true);
})
//.CascadeFrom("RMSupplierLocationViewModel")
.CascadeFrom("DeliveryLocationViewModel")
)
#Html.ValidationMessageFor(m => m)
There are two options to achieve what you are looking for:
Option 1: You can Use Cascading + Server Filtering
Option 2: You can Use Cascading + Client Side Filtering
First of all you will need to define events on both of your drop downs of Locations ("Delivery location" or "Pickup location") as below:
#(Html.Kendo().DropDownListFor(m => m)
.Name("PickUpLocationId")
.DataValueField("ShippingOptionId")
....
....
.Events(evnt=>evnt.Cascade("onCascade")) //Need to add this Event on Parent Drop Downs
)
Repeat the same for another Location DropDown. Your Cascade Event should be as below:
Server side filtering
#(Html.Kendo().DropDownListFor(m => m)
.Name("ShipingOption")
.DataValueField("ShippingOptionId")
.DataTextField("ShippingOptionName")
.OptionLabel("Select...")
.AutoBind(false)
.DataSource(dataSource =>
{
dataSource.Read(read =>
{
read.Action("GetAvailableShippingOptions", "ProductionZone").Type(HttpVerbs.Post)
.Data("filterShippingOptions");
}).ServerFiltering(true);
})
)
JS Function
function onCascade(e){
("#ShipingOption").data("kendoDropDownList").dataSource.read();
}
function filterShippingOptions() {
return { pickUpLocationId: $("#PickUpLocationId").data("kendoDropDownList").value(), deliveryLocationId: $("#deliveryLocationId").data("kendoDropDownList").value() };
}
Client side filtering
For Second option you will need to retrieve all the records for the Shipping option, disable server filtering to false and apply the filtering in the onCascade JS Function.
I have achieved this as follows:
View code:
<script>
function filterShippingOptions() {
return { locationId: $("#LocationViewModel").data("kendoDropDownList").value(), deliveryLocationId: $("#Location2ViewModel").data("kendoDropDownList").value() };
}
function onCascade(e) {
$("#ShippingOptionViewModel").data("kendoDropDownList").dataSource.read();
}
</script>
Editor code:
#model Comanex.Models.ShippingOptionsViewModel
#(Html.Kendo().DropDownListFor(m => m)
.DataValueField("ShippingOptionId")
.DataTextField("ShippingOptionName")
.OptionLabel("Select")
.AutoBind(false)
.DataSource(dataSource =>
{
dataSource.Read(read =>
{
read.Action("GetAvailableShippingOptions", "Shipping").Type(HttpVerbs.Post)
.Data("filterShippingOptions");
}).ServerFiltering(true);
})
)
#Html.ValidationMessageFor(m => m)
Controller Method:
public JsonResult GetAvailableShippingOptions(string PickUpLocationId, string DeliveryLocationId)
{
//Getting value from database
return Json(ShippingOptionRepository.GetAvailableShippingOptions(PickUpLocationId, DeliveryLocationId), JsonRequestBehavior.AllowGet);
}
Both the Parent controls(Dropdownlists in my case) should have following:
.Events(evnt => evnt.Cascade("onCascade")) //Need to add this Event on Parent Drop Downs
Related
My MVC ViewModel contains the initial list of records to be displayed within my Kendo TreeList. However, the TreeList is NOT rendering the initial list...and I don't understand why.
REQUIREMENTS:
If initial records exist...display them
The READ ACTION CANNOT be executed on the initial render (other controls manage that later)
For other Kendo controls, you set:
AutoBind(false)
BindTo(Model.MyCollectiom)
...and the READ ACTION does not execute. But the TreeList is failing at the moment.
MY RAZOR LOOKS LIKE:
At initial render records DO EXIST (see image below)
#(Html.Kendo().TreeList<DeviceHierarchyDataItem>()
.Name("treeTarget")
.Columns(columns =>
{
columns.Add().Field(e => e.DisplayName)
.TemplateId("tmplDisplayName")
.Title(" ");
})
.BindTo(Model.TargetDevices)
.AutoBind(false)
.DataSource(dataSource => dataSource
.Read(read => read.Action("find", "devicehierarchy", new { Area = "" })
.Data("window.etp.pageController.getFilter"))
.ServerOperation(false)
.Model(m =>
{
m.Id(f => f.Id);
m.ParentId(f => f.ChildOf);
m.Expanded(true);
m.Field(f => f.DisplayName);
}))
.Sortable())
Strangely enough the TreeList MVC control doesn't support binding to local data...
At least not in july 2018...
The recommendation is to use the jquery control instead.
And then convert the data from the Model to a json string:
$(document).ready(function () {
var dataSource = new kendo.data.TreeListDataSource({
data: #Html.Raw(Json.Encode(#Model.TargetDevices)),
schema: {
model: {
id: "Id",
parentid: "ChildOf",
expanded: true
}
}
});
I hope it helps!
I am trying to replicate exactly what is on this Kendo demo page with the Categories column. Simply a drop down list inside the grid. I copied all their source code exactly, but when I click the column with a drop down, the grid simply flashes. I can edit the FullName value fine. I tried to get an animation of the effect with a screen recorder, but for some reason it is not showing everything I see. In this image I am clicking the "Rol" drop down column multiple times.
What the gif does not show is that when I click the column, it briefly changes to a drop down control for a split second. I was able to capture this by adding a "debugger" line to the onDataBound event for the dropdown and taking a screenshot:
What is going on? Why doesn't it just pop open?
Here is some of the relevant code:
The EditorTemplates/RolList.cshtml file. Note that NONE of these events fire except the onDataBound event. That is probably a clue.
#model MyCompany.Web.CaseLink.Mvc.Admin.Models.RolDropDown
#(Html.Kendo().DropDownListFor(m => m)
.BindTo((System.Collections.IEnumerable)ViewData["roles"])
.DataValueField("RolId")
.DataTextField("RolDescription")
.Events(events => events
.Select("onSelect")
.Change("ddlChange")
.Open("onOpen")
.DataBound("onDatabound")
)
)
<script type="text/javascript">
function onSelect(e) {
console.log("ddl select" + e);
}
function ddlChange(e) {
console.log("ddl change" + e);
}
function onOpen(e) {
console.log("ddl open" + e);
}
function onDatabound(e) {
debugger;
console.log("ddl databound" + e);
}
</script>
Here is the partial view containing the MVC Grid itself. Note that the gridChange event was added just for debugging, and it does not fire when clicking in the drop down column.
#(Html.Kendo().Grid<CaseMemberGridRow>()
.Name("grid")
.Columns(columns =>
{
columns.Bound(c => c.FullName)
.Title("Name")
;
columns.Bound(p => p.Rol).ClientTemplate("#=Rol.RolDescription#").Width(180);
columns.Bound(c => c.Email)
.Title("Email")
;
columns.Bound(c => c.Telephone)
.Title("Phone")
;
columns.Command(command => command.Destroy()).Width(150);
})
.ToolBar(toolBar =>
{
toolBar.Create();
toolBar.Save();
})
.HtmlAttributes(new { style = "height: 550px;" })
.Scrollable()
.Sortable()
.Editable(editable => editable.Mode(GridEditMode.InCell))
.DataSource(dataSource => dataSource
.Ajax()
.Batch(true)
.ServerOperation(false)
.Events(events => events.Error("error_handler").Change("gridChange"))
.Model(m =>
{
m.Field(p => p.FullName).Editable(true);
m.Field(p => p.Rol).Editable(true);
m.Field(p => p.Rol).DefaultValue(
ViewData["defaultRol"] as MyCompany.Web.CaseLink.Mvc.Admin.Models.RolDropDown);
})
.Create(create => create.Action("AddCaseMemberNoCustomerRecord_Create", "AddMember"))
.Update(update => update.Action("AddCaseMemberNoCustomerRecord_Update", "AddMember"))
)
)
Controller is nothing special, as I said, I am doing exactly when Telerik did in their demo. A sample:
var roles = _rolService.GetAllRolesDTO()
.OrderBy(o => o.Description)
.Select(r => new RolDropDown
{
RolDescription = r.Description,
RolId = r.RolId
});
ViewData["roles"] = roles;
ViewData["defaultRol"] = roles.First();
If there is something to look for in the debugger on the "onDataBound" event, let me know. As you can see here, the datasource is definitely populated.
EDIT: I am aware that you can attempt to do the same thing using the ForeignKey type of column. When I try that, I can get a drop down to work once. After selecting a value, the column starts acting like before where you cannot change the value.
columns.ForeignKey(p => p.RolId, (System.Collections.IEnumerable)ViewData["roles"], "RolId", "Description")
.Title("Role")
.Width(150);
I using the following:
#(Html.Kendo().DropDownListFor(m => m.AbcID)
.OptionLabel("Select Abc")
.DataTextField("AbcName")
.DataValueField("AbcID")
.AutoBind(true)
.HtmlAttributes(new { style = "width: 300px" })
.Filter(FilterType.Contains)
.DataSource(source =>
{
source.Read(read =>
{
read.Action("AutoCompleteAbcList", "Common").Data("GetSelectedXyz");
});
})
So basically what's happening is that the dropdownlist is being populated by the Json returned by the AutoCompleteAbcList ActionMethod.
What I'd like to know is that I have another ActionMethod ddlPQRList that returns a Json and I'd like to populate my dropdownlist using both the Jsons.
I have tried the following:
#(Html.Kendo().DropDownListFor(m => m.AbcID)
.OptionLabel("Select Abc")
.DataTextField("AbcName")
.DataValueField("AbcID")
.AutoBind(true)
.HtmlAttributes(new { style = "width: 300px" })
.Filter(FilterType.Contains)
.DataSource(source =>
{
source.Read(read =>
{
read.Action("AutoCompleteAbcList", "Common").Data("GetSelectedXyz");
read.Action("ddlPQRList", "Common").Data("GetSelectedXyz");
});
})
but do not get the desired output. I get the list from the 2nd ActionMethod only.
Any help is appreciated. Thanks.
No, this is not possible the way you are trying to do it. A widget can only have one dataSource.
The second read Action is overwriting the first. It is the same thing as setting a variable value twice...only the second one counts.
If you want the dataSource of the DropDownList to be the concatenation of list, then you need to create a single controller action that returns that list, i.e.:
read.Action("AutoCompleteAbcListANDddlPQRList", "Common").Data("GetSelectedXyz");
where the implementation of AutoCompleteAbcListANDddlPQRList() returns a single list of BOTH AutoCompleteAbcList and ddlPQRList lists.
I need to use multiselect list in kendo grid (inline editing) so that user can select multiple values from the list per row.
Following are my requirements:
At the time of display, kendo grid should show comma separated list of all the selected values.
At the time of Add, kendo grid should show multiselect list and allow to select multiple values.
At the time of Edit, kendo grid should show multiselect list with already selected values. User should be able to modify the select and add/remove items from the list.
When user clicks on update/save button, selected values from multiselect list should be available in code behind (in update ajax action) along with id of row.
Following what I do as of now:
I am taking an approach similar to using a drop down list in kendo inline grid.
I have created an Editor Template for displaying multiselect at the time of add/edit.
Following is the code:
#model List<Namespace.CompanyConnector>
#using Kendo.Mvc.UI
#(Html.Kendo().MultiSelectFor(c=>c)
.Name("company_connector_id")
.DataTextField("connector_name")
.DataValueField("company_connector_id")
.Placeholder("Select connector...")
.AutoBind(false)
.Value((List<int>)ViewData["SelectedValues"])
.DataSource(source =>
{
source.Read(read =>
{
read.Action("GetCompanyConnectors", "BrandConnector");
})
.ServerFiltering(true);
})
)
#Html.ValidationMessageFor(m => m)
Explanation: I bind a list of model class to the multiselect and set data source in the read action. For selecting the selected values at the time of edit, I have created a function that returns the ids of selected values and put that in View Data in the read action.
I've used this Editor template in my Index page as following code:
#{Html.Kendo().Grid<Cee.DomainObjects.DomainObjects.BrandConnector>()
.Name("BrandConnectorGrid")
.Filterable()
.Events(e => e.Edit("onEdit"))
.DataSource(dataSource => dataSource
.Ajax()
.Events(e => e.Error("error_handler").RequestEnd("onRequestEnd"))
.ServerOperation(false)
.Model(model =>
{
model.Id(p => p.brand_id);
model.Field(e => e.CompanyConnectorList).DefaultValue(new
List<Cee.DomainObjects.DomainObjects.CompanyConnector>());
})
.Read(read => read.Action("_AjaxBinding", "BrandConnector",new{companyID = 0 }).Type(HttpVerbs.Post))
.Update(update => update.Action("_UpdateBinding", "BrandConnector").Type(HttpVerbs.Post)))
.Columns(columns =>
{
columns.Bound(c => c.brand_connector_id).Width(0).Hidden(true);
columns.Bound(c => c.company_id).Width(0).Hidden(true);
columns.Bound(c => c.brand_id).Width(0).Hidden(true);
columns.Bound(u => u.brand_name).Title("Brand").Width("18%").HtmlAttributes(new { #class = "brkWord", #readonly = "readonly" });
columns.ForeignKey(u => u.connector_name, Model.CompanyConnectorList, "company_connector_id", "connector_name").Title("Connector").Width
("16%").HtmlAttributes(new { #class = "brkWord" }).EditorTemplateName("company_connector_id");
columns.Command(p => p.Edit().Text("Edit").HtmlAttributes(new { #title = "Edit" })).Width("16%").Title("Edit");
})
.Editable(editable => editable.Mode(GridEditMode.InLine).CreateAt(GridInsertRowPosition.Top))
.Pageable(pageable => pageable.Refresh(true).PageSizes(GlobalCode.recordPerPageList).ButtonCount(GlobalCode.PageSize).Input(true).Numeric(true))
.HtmlAttributes(new { #class = "dynamicWidth" })
.Sortable(sorting => sorting.Enabled(true))
.Render();
}
Explanation: I've used ForeignKey. Bound it to the string column "connector_name". Connector_name is a comma separated list of IDs that I send from controller. Editor template is used here.
Issue: It works fine at the time of View/Display in Index but Edit does not show selected value. Also we do not get updated value in code behind on update click.
Is this correct way of implementing multiselect list or do I need to bind a collection property as a column in grid?
If I bind a collection property as a column then how would I be able to show comma separated string at the time of display?
Try below code:
function onEdit(e) {
var multiselect = $("#YourMutliselectDropdown").data("kendoMultiSelect");
var IDArray = [];
$(e.model.propertyName).each(function (index) {
var ID = e.model.propertyName[index].id;
IDArray.push(ID);
});
multiselect.value(IDArray);
}
I assume that propertyName is List of your collection and it contains id as property.
try it:
c.Bound(p => p.CompanyConnectorList).ClientTemplate("#= connectorsToString(data)#").EditorTemplateName("company_connector_id");
and js:
function connectorsToString(data) {
var list = data.company_connector_id;
var result = "";
for (var i = 0; i < list.length; i++) {
result += list[i].Name + ';';
}
return result;
}
I am working on asp.net mvc. I am trying to display list of messages in a Kendo mvc ui grid.
I have written the code like,
Html.Kendo().Grid((List<messages>)ViewBag.Messages))
.Name("grdIndox")
.Sortable(m => m.Enabled(true).SortMode(GridSortMode.MultipleColumn))
.HtmlAttributes(new { style = "" })
.Columns(
col =>
{
col.Bound(o => o.RecNo).HtmlAttributes(new { style = "display:none" }).Title("").HeaderHtmlAttributes(new { style = "display:none" });
col.Bound(o => o.NoteDate).Title("Date").Format("{0:MMM d, yyyy}");
col.Bound(o => o.PatName).Title("Patient");
col.Bound(o => o.NoteType).Title("Type");
col.Bound(o => o.Subject);
}
)
.Pageable()
.Selectable(sel => sel.Mode(GridSelectionMode.Single).Type(GridSelectionType.Row))
.DataSource(
ds => ds.Ajax().ServerOperation(false).Model(m => m.Id(modelid => modelid.RecNo))
.PageSize(10)
//.Read(read => read.Action("Messages_Read", "Msg"))
)
.Events(ev => ev.Change("onSelectingGirdRow"))
)
and i have the field in the table like IsRead-boolean type. so if the message is unread message then i need to format that record with bold font. I have used clientTemplates but with that i am able to format only particular cells i want format entire row. Please guide me.
as Sanja suggested you can use the dataBound event but it will be better to cycle through the tr elements (the rows). Also I assume that you will need the related dataItem to check if the property that indicates if the message is read.
e.g.
dataBound: function ()
{
var grid = this;
grid.tbody.find('>tr').each(function(){
var dataItem = grid.dataItem(this);
if(!dataItem.IsMessageRead)
{
$(this).addClass('someBoldClass');
}
})
}
You can use dataBound event to change your rows.
dataBound: function ()
{
$('td').each(function(){
if(some condition...)
{
$(this).addClass('someBoldClass')}
}
})
}
There is another way to do that.It's called RowAction.
.RowAction(row =>
{
if (condition)
{
row.HtmlAttributes["class"] = "someBoldClass";
}
})
Please note that the RowAction is available only for rows that are rendered on server side. So in your case, you can use RowAction as an alternative to DataBound.