How to bind kendo mvc ui dropdownlist dynamically - asp.net-mvc

I am working on asp.net mvc with Kendo UI mvc. I have two kendo dropdown lists. one for list of clinics and another of list of patients in selected clinic. But there is no direct relationship between clinic and patient to use the cascading dropdownlist. for that i have used ajax calls in dropdownlist change event and get list of patients. and this is my first dropdownlist for list clinics
#(
Html.Kendo().DropDownList()
.Name("ddlClinics")
.Events(e=>e.Change("ChangeClinic"))
.BindTo(new SelectList((List<Account.Entities.Clinic>)ViewBag.lstClinic,
"ClinicID", "ClinicName")))
and this is my second dropdownlist for listpatients
#(
Html.Kendo().DropDownList()
.Name("ddlPatients")
.BindTo(new SelectList((List<Patient>)ViewBag.Patients,
"PatId", "PatName"))))
I want to dynamically bind the list of patients to second dropdownlist when the first dropdownlist changes,
function ChangeClinic()
{
$.ajax({
url: '/Messages/GetPatient',
type: 'Post',
data: { email: '#User.Identity.Name' },
cache: false,
success: function (result) {
var ddlPatients = $('#ddlPatients').data('kendoDropDownList');
var main = [];
$.each(result, function (k, v) {
main.push({ "PatId": v.PatId, "PatName": v.PatName });
});
ddlPatients.dataTextField = "PatName";
ddlPatients.dataValueField = "PatId";
ddlPatients.dataSource.data(main);
ddlPatients.reload();
}
});
}
i am able to bind the list to dropdownlist but all items are shows as 'undefined'. so please guide me.

From what I can tell, there is a relationship between clinics and patients so you should be able to use the CascadeFrom("DropDownList1") provided in the wrappers. We use a cascading dropdownlist in a similar fashion for the relationship between school districts and schools:
#(Html.Kendo().DropDownList()
.Name("District")
.HtmlAttributes(new { style = "width:300px;" })
.BindTo(ViewBag.districts)
.DataTextField("DistrictName")
.DataValueField("DistrictID")
.OptionLabel("Select District")
)
#(Html.Kendo().DropDownList()
.Name("School")
.HtmlAttributes(new { style = "width:300px;" })
.CascadeFrom("District")
.BindTo(ViewBag.schools)
.DataTextField("SchoolName")
.DataValueField("SchoolID")
.OptionLabel("Select School")
)

If you want fill second DropDown on basis of first DropDown value.
Telerik Provided,
.CascadeTo("DropDownList2")
Please see following link for detailed information.
Cascading of Dropdown in Telerik dropdownlist

Instead of creating such array which is useless to the dataSource use:
success: function (result) {
var ddlPatients = $('#ddlPatients').data('kendoDropDownList');
var main = [];
$.each(result, function (k, v) {
main.push({ "text": v.PatId, "value": v.PatName });
});
ddlPatients.dataSource.data(main);
}
});

If you are not using
.DataSource(source =>
{
source.Read(read =>
{
read.Action ("FunctionName", "ControllerName").Data("filterDropdown1");
}).ServerFiltering(true);
})
.CascadeFrom("Dropdown1")
properties in the definition of second dropdown and you are using the definition mentioned in question above. i.e:-
#(
Html.Kendo().DropDownList()
.Name("ddlPatients")
.BindTo(new SelectList((List<Patient>)ViewBag.Patients,"PatId", "PatName"))
)
then you can bind the data to the 2nd dropdown directly in the success function of ajax post.
function ChangeClinic()
{
$.ajax({
url: '/Messages/GetPatient',
type: 'Post',
data: { email: '#User.Identity.Name' },
cache: false,
success: function (result) {
$('#ddlPatients').data('kendoDropDownList').dataSource.data(result);
//ddlPatients.reload();
}
});
}
#Note:- 1) The result value should contain the list of new patients with properties "PatId" and "PatName" based on the parameter email passed to the function "Messages" in GetPatient controller, and there will be no need for ddlpatients.reload(), infact .reload() is not supported, it will break the execution, so don't use .reload().

Related

How to get the value of Dropdown on the specific field using ajax (mvc)

sorry for the bad title I cannot express the proper subject to my problem
since, I'm a newbie in MVC and ajax I have a problem
In view I prepared a dropdown where it list all the shoes name (Shoe Table), now the customer has to select it but the twist it must display the Shoesprice (Shoe Table) once it select a shoe name. the view code is given below
View:
#Html.DropDownListFor(x => x.shoename, new SelectList(Model.ShoesModel,"shoename","shoename"), "Select Shoes Name", new {id="myDrop",#class="form-control" })
I have the script when you select it the item, this particular syntax is working
Script:
$("#myDrop").change(function ()
{
var value = $(this).val();
console.log(value);
$.ajax({
type: 'POST',
url: '/Customers/GetShoesPrice',
dataType: 'json',
data: { shoesName: $(this).val() },
success: function (data) {
//how can I declare a value to get the and return the price
}
});
}
But, i don't know how to create an ajax syntax (get the price according to shoe name), and set to a controller
thank you for help
Since you want to return single value only, just use data in AJAX success result to show returned price value:
Controller
[HttpPost]
public JsonResult GetShoesPrice(string shoesName)
{
var customerViewPrice = (from c in _SBC.Shoeses // Change the condition here
where c.shoename.Contains(shoesName)
select c.ShoesUnitPrice).FirstOrDefault(); // or SingleOrDefault() for one and only returned value
return Json(customerViewPrice);
}
View (jQuery)
$("#myDrop").change(function () {
var value = $(this).val();
console.log(value);
$.ajax({
type: 'POST',
url: '/Customers/GetShoesPrice',
dataType: 'json',
data: { shoesName: value },
success: function (data) {
// set input element value which will be posted on form submit with DropDownListFor
$('#price').val(data);
}
});
}
Note that if you want to show list of ShoesUnitPrice from selected shoesName, you need to use $.each() loop to iterate returned array of price value.

How to dynamically change kendo UI treeview datasource

I have a kendo ui treeview and a dropdownbox on my asp.net mvc page. The dropdown box can have two values. Depending upon which one has been chosen, I want to change the datasource url, which is a method in a controller. The data type and structure of data from both the url will be the same. Essentially I want to change url: '#Url.Content("~/Document/GetMyDocument")' dynamically. The following is my treeview code:
<script>
$("#treeview").kendoTreeView({
checkboxes: {
checkChildren: true,
},
dataSource: {
transport: {
read: {
url: '#Url.Content("~/Document/GetMyDocument")',
type: "post",
dataType: "json"
}
},
schema: {
model: {
text: "Name",
spriteCssClass: "fa fa-folder",
children: "Files"
}
}
},
dataTextField: ["Name", "FileName"],
dataValueField: ["id"],
check: onCheck
});
You can specify the URL of the treeview dataSource as function
transport: {
read: {
url: function (e) { }
}
}
You can then listen for the change event of the DropDownList and call
$('#treeview').data('kendoTreeView').dataSource.read();
Inside the url function you can get the value of the DropDownList and resolve the url dynamically:
var ddl = $('#myDDl').data('kendoDropDownList');
var value = ddl.value();
return value == "someValue" ? "/foo/bar": "/bar/baz";

Sort Kendo Multiselects selected Items by DataTextField

We are using kendo multiselect with mvc wrappers. Everything on the setup works fine, but the selected items are sorted by the data value field. I simply want them to be sorted by the data text field, but nothing worked so far.
#(Html.Kendo().MultiSelectFor(m => m.SelectedPersonIds)
.HtmlAttributes(new { style = "width: 400px" })
.DataTextField("Name")
.DataValueField("PersonID")
.Filter("contains")
.Height(400)
.DataSource(ds =>
{
ds.Read(read =>
{
read.Action("GetPersons", "Person", new { area = "" });
});
})
.ItemTemplateId("detailTemplate")
.TagTemplateId("valueTemplate")
)
This is the working version. I tried adding
ds.Custom().Sort(s => s.Add("Name").Ascending());
and other approaches, but still no luck. The initial data, coming from the server, is sorted and therefore the list you select from is sorted perfectly (by Name).
How can i achieve that the selected items are also sorted by Name instead of by ID?
Thanks in advance.
Do not manually rearrange the DOM elements. Doing this will break the mapping between the displayed items and the internal data. If you were to manually rearrange the DOM elements, then deselecting an item will cause a different data item to be deselected in the underlying data. Binding back to the server will yield incorrect results.
Here is a correct way to order it, given that the value field is PersonID but you want it sorted by Name
function orderMultiSelect(multi) {
const dataItems = multi.dataItems();
dataItems.sort(
(a, b) => {
const textA = a.Name;
const textB = b.Name;
return (textA < textB) ? -1 : (textA > textB) ? 1 : 0;
}
);
const values = dataItems.map(di => di.PersonID);
multi.value(values);
}
function onMultiselectChange(e) {
orderMultiselect(e.sender);
}
You would then bind this handler function to the to the DataBound and Change events:
#(Html.Kendo().MultiSelectFor(m => m.SelectedPersonIds)
.HtmlAttributes(new { style = "width: 400px" })
.DataTextField("Name")
.DataValueField("PersonID")
.Filter("contains")
.Height(400)
.DataSource(
ds =>
{
ds.Read(
read =>
read.Action("GetPersons", "Person", new { area = "" })
);
}
).ItemTemplateId("detailTemplate")
.TagTemplateId("valueTemplate")
.Event(
e =>
e.DataBound("onMultiselectChange")
.Change("onMultiselectChange")
)
)
http://plnkr.co/edit/0gS9SDeccgOmfsGp?preview
I don't know is there is ASP.NET solution but i can give you JavaScript to solve it:
function onMultiselectChange(e) {
e.sender.tagList.find('> li').sort(function (a, b) {
return $(a).text() > $(b).text();
}).appendTo(e.sender.tagList);
}
});
You can apply it to your ASP.NET multiselect like this:
.Events(e =>
{
e.Change("onMultiselectChange")
})

Change dropdownlist to autocomplete in scheduler popup editor in Kendo MVC

For example, I bind the resource as follows.
.Resources(resource =>
{
resource.Add(m => m.UserName)
.Title("Staff")
.Name("Staff")
.DataTextField("Text")
.DataValueField("Value")
.DataSource(source => source
.Read(read => read.Action("GetStaffList", "Scheduler"))
);
})
When the editor popups, the staff input has type of dropdown list which contains all the Staff in database.
Question: How to change it to an autocomplete widget with server filtering by staff's name for example.
Thank you.
I would jump into JavaScript by hooking up a event on edit to the grid, then you can do it there doing something like this
function onEdit(e) {
//Autocompleter
$("#Staff").kendoAutoComplete({
dataSource: {
serverFiltering: true,
transport: {
read: { url: "/Staff/GetListForAutocompleter" },
parameterMap: function (data, action) {
var newParams = { filter: $("#Staff").val(), filter2: 'something' };
return newParams;
}
}
}
});
}

kendo ui Combobox binded to a Grid losts it's value and text after Grid's Cancel button pressed

I have two views in database. Bonuses and employees. One(employee)-to-many(bonuses).
I have kendo ui grid (kendo web), which displays ajax results from controller called Bonuses
And an autocompliting element - Employee Combobox binded with Employee filed of a grid.
Grid's datasource:
// bind json result from /Bonuses/GetPagedJsonBonuses
var bonusesDataSource = new kendo.data.DataSource({
transport: {
read: "#Url.Action("GetPagedJsonBonuses", "Bonuses")",
update: {
url: "#Url.Action("Edit", "Bonuses")",
type: "PUT"
},
create: {
url: "#Url.Action("Create", "Bonuses")",
type: "POST"
},
parameterMap: function(options, operation) {
if (operation === "update" || operation === "create") {
// updates the BonusDTO.EmployeeId with selected value
if (newValueEmployeeId !== undefined)
options.EmployeeId = newValueEmployeeId;
}
return options;
}
},
schema: {
data: "Data", // PagedResponse.Data
total: "TotalCount", // PagedResponse.TotalCount
model: {
id: "BonusId", // Data
fields: {
EmployeeId: { type: "number" },
EmployeeLastName: {
type: "string",
editable: true,
//validation: { required: {message: "Employee's last name is required"}}
},
Amount: {
type: "number",
editable: true,
nullable: false,
validation: {
required: { message: "Amount is required to be set" }
}
}
} // fields
} // model
}// schema
});
Grid element looks like this:
// creates bonuses grid control
$("#bonusesGrid").kendoGrid({
dataSource: bonusesDataSource,
toolbar: ["create"],
editable: "inline",
columns: [
"BonusId",
"EmployeeId",
{
field: "EmployeeLastName",
editor: employeeAutocompletingEditor,
template: "#=EmployeeLastName#"
},
"Amount",
{
command: ["edit"],
title: " "
}
],
save: function(e) {
if (newValueEmployeeId !== undefined && newValueEmployeeLastName !== undefined) {
e.model.EmployeeId = newValueEmployeeId; // it's a hack to bind model and autocomplete control
e.model.EmployeeLastName = newValueEmployeeLastName;
}
},
edit: function(e) {
setCurrentValueEmployeeIdAndLastName(e.model.EmployeeId, e.model.EmployeeLastName);
},
cancel: function(e) {
setCurrentValueEmployeeIdAndLastName(e.model.EmployeeId, e.model.EmployeeLastName);
}
});
Autocompleting combobox has it's own datasource using ajax:
// datasource for autocomlete combobox to lookup employees names from
var employeesDataSource = new kendo.data.DataSource({
transport: {
read: "#Url.Action("GetJsonEmployeesByLastName", "Bonuses")",
},
parameterMap: function(options, operation) {
if (operation === "update" || operation === "create") {
setNewValueEmployeeIdAndLastName(options.Id, options.LastName);
}
return options;
},
});
Autocompliting combobox look's like this:
function employeeAutocompletingEditor(container, options) {
$('<input required data-text-field="LastName" data-value-field="EmployeeId" data-bind="value:' + options.field + '"/>')
.appendTo(container)
.kendoComboBox({
// sets the local variables to update values of current row.
change: function() {
setNewValueEmployeeIdAndLastName(this.value(), this.text());
},
dataBinding: function (e) {
console.log("dataBinding: ", e, this.dataItem());
},
dataBound: function (e) {
console.log("dataBound: ", e, this.dataItem());
},
dataSource: employeesDataSource
});
}
I use Editor binding to pass values(EmployeeId) and Text (EmployeeLastName) from grid to combobox.
I also use a hack like temporal variables (newValueEmployeeId, currentValueEmployeeId) to
send selected Employee in combobox and pass it to grid for correct save. A found it's a most common practice to pass a value back to grid.
My problems is:
If I press Edit button on my grid first time The combobox displays current employee's name from grid row:
If I press Cancel button and again press Edit button, combobox doesn't display current value of grid (employee's name)
IF I type some name, change some other values, and Udate(save) value, next time combobox again displays employees name, but only once before Cancel was pressed.
I'm very new in Kendo UI and this problem drives me crazy...
I think that combobox losts it's binding or doesn't update smth. I tried to set values while onBound and onBinding events, but this doesn't help. Please help me with an advice and example.
PS all evenets and functions is my try to debug and find solution.
only one fix helped me:
var employeeList = new List<Employee>()
employeeList.add(new Emplpyee()) // add fake employee record.
return Json(employeeList)
I don't know why, but grid control start make cyclying empty ajax requests if I return empty list of employees or null. This doesn't work:
return Json(new List<Employee>());
return Json(null);
I think it's a problem in kendo combobox itself ,because it's not ready to receive and handle empty list or null as json result.
Also I heared something, that JQuery doesn't support empty or null results anymore...maybe that's the reason

Resources