1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
/**
* Enhanced Select2 Dropmenus
*
* @AJAX Mode - When in this mode, your value will be an object (or array of objects) of the data used by Select2
* This change is so that you do not have to do an additional query yourself on top of Select2's own query
* @params [options] {object} The configuration options passed to $.fn.select2(). Refer to the documentation
*/
angular.module('ui.directives').directive('uiSelect2', ['ui.config', '$timeout', function (uiConfig, $timeout) {
var options = {};
if (uiConfig.select2) {
angular.extend(options, uiConfig.select2);
}
return {
require: '?ngModel',
compile: function (tElm, tAttrs) {
var watch,
repeatOption,
repeatAttr,
isSelect = tElm.is('select'),
isMultiple = (tAttrs.multiple !== undefined);
// Enable watching of the options dataset if in use
if (tElm.is('select')) {
repeatOption = tElm.find('option[ng-repeat], option[data-ng-repeat]');
if (repeatOption.length) {
repeatAttr = repeatOption.attr('ng-repeat') || repeatOption.attr('data-ng-repeat');
watch = jQuery.trim(repeatAttr.split('|')[0]).split(' ').pop();
}
}
return function (scope, elm, attrs, controller) {
// instance-specific options
var opts = angular.extend({}, options, scope.$eval(attrs.uiSelect2));
if (isSelect) {
// Use <select multiple> instead
delete opts.multiple;
delete opts.initSelection;
} else if (isMultiple) {
opts.multiple = true;
}
if (controller) {
// Watch the model for programmatic changes
controller.$render = function () {
if (isSelect) {
elm.select2('val', controller.$modelValue);
} else {
if (isMultiple) {
if (!controller.$modelValue) {
elm.select2('data', []);
} else if (angular.isArray(controller.$modelValue)) {
elm.select2('data', controller.$modelValue);
} else {
elm.select2('val', controller.$modelValue);
}
} else {
if (angular.isObject(controller.$modelValue)) {
elm.select2('data', controller.$modelValue);
} else {
elm.select2('val', controller.$modelValue);
}
}
}
};
// Watch the options dataset for changes
if (watch) {
scope.$watch(watch, function (newVal, oldVal, scope) {
if (!newVal) return;
// Delayed so that the options have time to be rendered
$timeout(function () {
elm.select2('val', controller.$viewValue);
// Refresh angular to remove the superfluous option
elm.trigger('change');
});
});
}
if (!isSelect) {
// Set the view and model value and update the angular template manually for the ajax/multiple select2.
elm.bind("change", function () {
scope.$apply(function () {
controller.$setViewValue(elm.select2('data'));
});
});
if (opts.initSelection) {
var initSelection = opts.initSelection;
opts.initSelection = function (element, callback) {
initSelection(element, function (value) {
controller.$setViewValue(value);
callback(value);
});
};
}
}
}
attrs.$observe('disabled', function (value) {
elm.select2(value && 'disable' || 'enable');
});
if (attrs.ngMultiple) {
scope.$watch(attrs.ngMultiple, function(newVal) {
elm.select2(opts);
});
}
// Set initial value since Angular doesn't
elm.val(scope.$eval(attrs.ngModel));
// Initialize the plugin late so that the injected DOM does not disrupt the template compiler
$timeout(function () {
elm.select2(opts);
// Not sure if I should just check for !isSelect OR if I should check for 'tags' key
if (!opts.initSelection && !isSelect)
controller.$setViewValue(elm.select2('data'));
});
};
}
};
}]);
|