This is a migrated thread and some comments may be shown as answers.

MultiSelect: view and model not in sync

6 Answers 402 Views
MultiSelect
This is a migrated thread and some comments may be shown as answers.
Lawrence
Top achievements
Rank 1
Lawrence asked on 03 Jun 2016, 06:53 PM

I am using a Kendo MultiSelect (within a column of a tr-ng-grid) and I am trying to add a functionality where an item is deselected when another is selected.

Ex. I have the options 1, 2, 3,  and UNKNOWN; only 2 and 3 are selected. The rule is when UNKNOWN is selected, the rest are deselected and when 1, 2, or 3 is selected, UNKNOWN is deselected.

The problem that I am facing is that the model and the view is not always in sync, which poses a problem.

 

Here is the code.

index.html (short version)

1.<dir-multi-select selected-items="gridItem.items" />

directive.js

01.(function() {
02.    'use strict';
03.    angular.module('moduleA').directive('dirMultiSelect', function() {
04.        return {
05.            restrict : 'E',
06.            scope : {
07.                selectedItems : '='
08.            },
09.            controller : 'MultiSelectController',
10.            templateUrl : 'multiselect.html',
11.            replace : true
12.        }
13.    })
14.})();

multiselect.html

01.<div ng-init="init()">
02.    <select kendo-multi-select
03.        id="'multiSelect'"
04.        ng-if="dataSource"
05.        k-data-source="dataSource"
06.        k-data-text-field="'name'"
07.        k-data-value-field="'id'"
08.        k-ng-model="selectedItems"
09.        k-rebind="selectedItems"
10.        k-value-primitive=true
11.        k-auto-close=false
12.        k-data-placeholder="'Select items...'"
13.        k-on-select="onSelect(kendoEvent)">
14.    </select>
15.</div>

multiselect.controller.js

01.(function() {
02.    angular.module('moduleA').controller(
03.            'MultiSelectController',
04.            [
05.                    '$scope',
06.                    function($scope) {
07.                        $scope.init = function() {
08.                                $scope.dataSource = //http call
09.                        }
10. 
11.                        $scope.onSelect = function(kendoEvent) {
12.                            var selectedItem = kendoEvent.sender.dataItem(kendoEvent.item.index());
13.                            if (selectedItem ) {
14.                                autoDeselectItems(kendoEvent, selectedItem);
15.                            }
16.                        }
17. 
18.                        function autoDeselectItems(kendoEvent, selectedItem) {
19.                            if (isItemIdUnknown(selectedItem.id)) {
20.                                kendoEvent.preventDefault();
21.                                if (!doesSelectedItemContainUnknown()) {
22.                                    setSelectedItemsToUnknown();
23.                                }
24.                            }
25.                            else {
26.                                if (doesSelectedItemsContainUnknown()) {
27.                                    kendoEvent.preventDefault();
28.                                    setSelectedItems(selectedItem);
29.                                }
30.                                else {
31.                                    if (doesSelectedItemsContain(selectedItem.id)
32.                                            && $scope.selectedItems.length == 1) {
33.                                        setSelectedItemsToUnknown();
34.                                    }
35. 
36.                                }
37.                            }
38.                        }
39. 
40.                        function isItemIdUnknown(id) {
41.                            return id == "0";
42.                        }
43. 
44.                        function doesSelectedItemsContainUnknown() {
45.                            for (var i = 0; i < $scope.selectedItems.length; i++) {
46.                                if (isItemIdUnknown($scope.selectedItems[i].id)) {
47.                                    return true;
48.                                }
49.                            }
50.                            return false;
51.                        }
52. 
53.                        function doesSelectedItemsContain(id) {
54.                            for (var i = 0; i < $scope.selectedItems.length; i++) {
55.                                if ($scope.selectedItems[i].id == id) {
56.                                    return true;
57.                                }
58.                            }
59.                            return false;
60.                        }
61. 
62.                        function removeUnknownFromSelectedItems() {
63.                            for (var i = 0; i < $scope.selectedItems.length; i++) {
64.                                if ($scope.selectedItems[i].id == 0) { // "UNKNOWN"
65.                                    $scope.selectedItems.splice(i, 1);
66.                                    break;
67.                                }
68.                            }
69.                        }
70. 
71.                        function setSelectedItemsToUnknown() {
72.                            $scope.selectedItems = [ {
73.                                id : "0",
74.                                name : "UNKNOWN"
75.                            } ];
76.                        }
77. 
78.                        function setSelectedItems(ids) {
79.                            if (ids) {
80.                                $scope.selectedItems = [];
81.                                if (ids.length) {
82.                                    for (var i = 0; i < ids.length; i++) {
83.                                        $scope.selectedItems.push({
84.                                            id : ids[i].id,
85.                                            name : ids[i].name
86.                                        });
87.                                    }
88.                                }
89.                                else {
90.                                    $scope.selectedItems.push({
91.                                        id : ids.id,
92.                                        name : ids.name
93.                                    });
94.                                }
95.                            }
96.                        }
97.                    } ]);
98.})();

a

6 Answers, 1 is accepted

Sort by
0
Alex Hajigeorgieva
Telerik team
answered on 07 Jun 2016, 04:08 PM

Hello Lawrence,

I have updated one of our Kendo UI MultiSelect demos to work with a configuration similar to the one provided. For some Kendo UI widgets with multiple options, the k-options attribute is necessary as outlined below:

http://docs.telerik.com/kendo-ui/AngularJS/introduction#widget-update-upon-option-changes

A sample demo for your convenience:
http://dojo.telerik.com/ANeHE

Additionally, the AngularJS directive ng-if is not supported and should be used at own risk. If possible, use ng-show instead:
http://www.telerik.com/forums/kendo-and-angular---ng-if#SrNHC_3VR0auZ9LR8d9kMg

Please avoid creating posts in different threads that are related to the same issue. This way we can track all relevant details in one place and focus our efforts to reach a resolution faster.

Let me know if you need further assistance with the Kendo UI MultiSelect.

Regards,
Alex
Telerik
 
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
 
0
Lawrence
Top achievements
Rank 1
answered on 07 Jun 2016, 06:43 PM
The reason I am using ng-if instead of ng-show because I don't want it to be rendered until the DataSource is valid.
0
Lawrence
Top achievements
Rank 1
answered on 07 Jun 2016, 06:51 PM

In your sample demo, you have two widgets: the first is not using k-options and the second is. The first one is not working, but the second one is. In the second one, you don't modify the selectedIds within the select event, which is what I am trying to do, while keeping the model in sync with the view.

0
Alex Hajigeorgieva
Telerik team
answered on 09 Jun 2016, 11:09 AM

Hello Lawrence,


Please accept my apology for sending a wrong Dojo demo - I have updated it now and also added onSelect function with a Kendo Event.

http://dojo.telerik.com/ejEmO

A Kendo UI widget will not be created if any of the defined attribute options evaluate to undefined: 
http://docs.telerik.com/kendo-ui/AngularJS/introduction#widget-options-in-html

To delay a Kendo UI widget until the data source becomes available, make use of the k-ng-delay attribute instead of using the non-supported ng-if
http://docs.telerik.com/kendo-ui/AngularJS/introduction#delay-widget-initialization

Let me know if you need any more help with the Kendo UI MultiSelect integration with AngularJS.

Kind Regards,
Alex
Telerik
 
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
 
0
Lawrence
Top achievements
Rank 1
answered on 13 Jun 2016, 07:21 PM

Still not there. You didn't modify the scope in your select event.

0
Alex Hajigeorgieva
Telerik team
answered on 16 Jun 2016, 11:22 AM
Hi Lawrence,

I was under the impression that the issue was with binding the Kendo UI Multiselect and that the model is not always in sync, so I provided a generic example. I would not recommend changing the ids of the DataSource to achieve the desired custom item selection logic inside the Kendo UI MultiSelect. 

I created a simple conditional statement that handles the selected items in the model of the Kendo UI MultiSelect using the following steps:

1)  Attach an event listener to the select event using k-on-select:
http://docs.telerik.com/kendo-ui/api/javascript/ui/multiselect#events-select

2) If "Unknown" is selected, then all others are deselected by assigning the value of "Unknown" to the model
$scope.selectedIds = [0];

3) If any other option is selected, then find the "Unknown" option and remove it from the model. Finally, add the current selection.

A similar result can be implemented by following the same steps with a change event handler:
http://docs.telerik.com/kendo-ui/api/javascript/ui/multiselect#events-change

If change is used, adding the current selection in step 3 will not be necessary.

Please find the demo at: http://dojo.telerik.com/AruRe

Kind Regards,
Alex
Telerik
Get started with Kendo UI in days. Online training courses help you quickly implement components into your apps.
Tags
MultiSelect
Asked by
Lawrence
Top achievements
Rank 1
Answers by
Alex Hajigeorgieva
Telerik team
Lawrence
Top achievements
Rank 1
Share this question
or