Hi
I've been working with the MultiSelect widget for a while now but this has led to a few questions....
Is there anyway to add or remove selections programmatically? I've implemented the following code in the select event but having tried lots of different methods, as suggested in the forums, I cannot get this to work (e.g. clearing the datasource filter and setting value seems to be the most popular). My multiselect is remote bound. My onSelect event is shown below.
Is there a better way of getting the dataItem rather than how I'm doing it in the first line?
Thanks
Keith
private checkSelection(e: kendo.ui.MultiSelectSelectEvent) {
var
dataItem = e.item.data().$$kendoScope.dataItem;
var
hidSelected = dataItem.hid;
e.preventDefault();
//check to see if adding this will change anything currently selected
_.find(<Array<any>>
this
.msSelector.dataItems(), (s) => {
if
(s.hid != hidSelected) {
//check to see if item's ancestor has been selected
if
(_.startsWith(hidSelected, s.hid)) {
this
.dialogService.showYesNo(
'Confirm selection'
,
'Adding <span class="text-bold">'
+ dataItem.name +
'</span> will remove <span class="text-bold">'
+ s.name +
'</span>. Do you want to continue?'
).promise.then((r) => {
if
(r) {
//remove parent
}
else
{
//remove new selection
}
return
;
});
}
}
});
}
6 Answers, 1 is accepted
You can check out the following how-to article from our documentation that shows selecting/deselecting all items programmatically and adjust it to select/deselect specific items only:
http://docs.telerik.com/kendo-ui/controls/editors/multiselect/how-to/select-deselect-all-items
Let us know if you need further assistance.
Regards,
Dimiter Topalov
Telerik
Hi Dimiter
Thanks for your response but I'd already looked at that How-To but it seems to work in a different way - all items are local and so already exist in the DataSource. I'm trying to do this using a service.
When I add an item into the selection, the server is called but the filter is blank and so since my service returns the top 100 items (and the selected item is not contained in this list) it doesn't get included in the data source. Having said all of that, I already have an instance of the item I would like to add, so having it going back to the server is not that important.
Since I have an instance of the item to add, manually adding into the data source and pushing its ID into the selection doesn't always seem to work. Here's some sample code which isn't exactly the same as I'm trying to do but is a good start...
<!DOCTYPE html>
<html>
<head>
<base href=
"http://demos.telerik.com/kendo-ui/multiselect/angular"
>
<style>html { font-size: 14px; font-family: Arial, Helvetica, sans-serif; }</style>
<title></title>
<link rel=
"stylesheet"
href=
"http://kendo.cdn.telerik.com/2016.2.607/styles/kendo.common.min.css"
>
<link rel=
"stylesheet"
href=
"//kendo.cdn.telerik.com/2016.2.607/styles/kendo.metro.min.css"
/>
<link rel=
"stylesheet"
href=
"//kendo.cdn.telerik.com/2016.2.607/styles/kendo.default.mobile.min.css"
/>
<script src=
"http://code.jquery.com/jquery-1.9.1.min.js"
></script>
<script src=
"http://kendo.cdn.telerik.com/2016.2.607/js/angular.min.js"
></script>
<script src=
"http://kendo.cdn.telerik.com/2016.2.607/js/kendo.all.min.js"
></script>
<link rel=
"stylesheet"
href=
"http://kendo.cdn.telerik.com/2016.2.607/styles/kendo.rtl.min.css"
>
<link rel=
"stylesheet"
href=
"http://kendo.cdn.telerik.com/2016.2.607/styles/kendo.default.min.css"
>
<link rel=
"stylesheet"
href=
"http://kendo.cdn.telerik.com/2016.2.607/styles/kendo.mobile.all.min.css"
>
<script src=
"http://kendo.cdn.telerik.com/2016.2.607/js/jszip.min.js"
></script>
</head>
<body>
<div id=
"example"
ng-app=
"KendoDemos"
>
<div class=
"demo-section k-content"
ng-controller=
"MyCtrl as ctrl"
>
<h4>Refresh page after each test</h4>
<ul>
<li>Click Add - Works but selector only includes
new
item. How
do
you clear the filter?</li>
<li>Click
in
selector (optionally select an item) and click Add - Works</li>
<li>Click
in
selector, type Tom and select one. Click Add - Doesn't work</li>
</ul>
<h4>Select product</h4>
<kendo-multi-select k-scope-field=
"ctrl.ms"
k-options=
"ctrl.selectOptions"
k-ng-model=
"ctrl.selectedIds"
></kendo-multi-select>
<p ng-show=
"ctrl.selectedIds.length"
style=
"padding-top: 1em;"
>Selected: {{ ctrl.selectedIds }}</p>
<button ng-click=
"ctrl.add()"
>Add</button>
</div>
</div>
<script>
angular.module(
"KendoDemos"
, [
"kendo.directives"
])
.controller(
"MyCtrl"
,
function
($scope){
this
.selectOptions = {
placeholder:
"Select products..."
,
itemTemplate:
'<span class="order-id">#= OrderID #</span> #= ShipName #, #= ShipCountry #'
,
dataTextField:
"ShipName"
,
dataValueField:
"OrderID"
,
valuePrimitive:
true
,
autoBind:
false
,
dataSource: {
type:
"odata"
,
pageSize: 10,
serverPaging:
true
,
serverFiltering:
true
,
transport: {
read:
"//demos.telerik.com/kendo-ui/service/Northwind.svc/Orders"
},
schema: {
model: {
fields: {
OrderID: { type:
"number"
},
Freight: { type:
"number"
},
ShipName: { type:
"string"
},
OrderDate: { type:
"date"
},
ShipCountry: { type:
"string"
}
}
}
}
}
};
this
.selectedIds = [];
this
.add =
function
(e) {
var
itemToAdd = {
OrderID: 10926,
Freight: 123,
ShipName:
'Test'
,
OrderDate:
'2016-07-01'
,
ShipCountry:
'Country'
,
}
this
.ms.dataSource.add(itemToAdd);
this
.selectedIds.push(itemToAdd.OrderID);
}
})
</script>
</body>
</html>
Thanks
Keith
The described issue is caused by the following known limitation of server filtering in the context of the Kendo UI dropdown widgets:
http://docs.telerik.com/kendo-ui/controls/editors/combobox/serverfiltering#known-limitations
To be able to add items that are not in the current page of data to the MultiSelect's value, you should utilize the Virtualization functionality of the widget, as described in the following documentation article:
http://docs.telerik.com/kendo-ui/controls/editors/combobox/virtualization#virtualization
You can also check out our MultiSelect Virtualization demo for a sample implementation of the required configuration and valueMapper:
http://demos.telerik.com/kendo-ui/multiselect/virtualization
I hope this helps, but if I am missing something, please describe the scenario, and the desired functionality in further details, so we can provide further, and more to-the-point suggestions.
Regards,
Dimiter Topalov
Telerik
I have a related problem with this.
I have a successfully virtualized MultiSelect working.
As a user types in to the field searching for a specific record, they find there isn't one. Through a separate button on the page, they execute a function to add to the list of options. This triggers an Ajax call that updates the lookup table adding a new record, and it returns the key for that record. Upon success, it updates the value of the MultiSelect to add the newly created record to the list of selected records.
The problem I'm running into is that the server's mapper function is returning (for example) 1267 for the index into the dataset where the newly created record is found. Since the dataset is sorted alphabetically, this is not going to be the last record. When the control reads the return from the mapper, it says, "Hey, I've already retrieved the record at position 1267, and it displays it without going back to the server to update the list of options. The problem is that this is what WAS at 1267 (and is now at 1268) is being selected - sometimes.
I had the following records in my database. ..., test, theory, ... I typed test into the MultiSelect, and saw that (of course) test1 wasn't in there. So, I clicked on the button I added, entered my new value (test1) and saved. The MultiSelect successfully selected test1. I then clicked on the button again, and I entered another new value (test2) and saved. The MultiSelect showed test1 and theory. If I clicked on the MultiSelect to view the items, I indeed saw test1 followed by theory. However, if I typed "test" in for searching and the virtualization kicked in and started talking to the server, I saw test1 and test2. Now, if I cleared my search text, I saw ..., test, test1, test2, theory, ...
I think what I'm looking for is a way to manually clear or reset the data already retrieved for pages of selections the MultiSelect has seen. When I successfully add a new lookup value, I want to call a method that tells the MultiSelect, "Hey, your cached data isn't quite accurate anymore. You're going to need to go to the server to get current selections.
Is there a way to do this?
Unfortunately, any manual data operations, such as add, filter, remove, page, read, etc. can lead to undesired behavior, and is not supported in scenarios with virtualization (this applies to all Dropdown widgets that share common virtualization functionality):
http://docs.telerik.com/kendo-ui/controls/editors/combobox/virtualization#known-limitations
You can try creating a new DataSource after adding the item to the remote service via the described AJAX call, and use the setDataSource() method to set it to the MultiSelect, but I cannot guarantee this would yield the desired effect in the specific scenario.
In general, non-supported scenarios and/or feature customization fall outside the scope of our support service, but if you send us an isolated runnable project, similar to the ones in our online demos, we can take a look, and try to provide a relevant suggestion, if one is available, and the desired functionality can be achieved with our API.
Regards,
Dimiter Topalov
Telerik by Progress