Monday, May 20, 2024
 Popular · Latest · Hot · Upcoming
46
rated 0 times [  49] [ 3]  / answers: 1 / hits: 6086  / 11 Years ago, wed, december 18, 2013, 12:00:00

I created a directive for input elements which creates a custom select2 dropdown.

After selecting an element, the original input field (which is used to filter data via the ngModel) is filled with the selected data from the dropdown, but the change event of the input isn't fired.

If I change the input value by hand, the filter is working.



Here is the code of my directive.



.directive('ajaxSelect2', ['$timeout', function($timeout) {
return {
restrict: 'A',
link: function (scope, element, attrs) {
switch(element.prop(tagName)) {
case 'INPUT':
$timeout(function() {
element.select2({
[ ... ] //the select2 part
});
});
break;
}

/* update the input value */
element.bind(change, function(e) {
scope.$apply(function() {
scope[attrs.ngModel] = e.val;
});
});

scope.$watch(element, function () {
console.log('x'); //not called
});
}
}
}])


I thought the element.bind(change) in the scope.apply() would trigger a view update, but it doesn't work.
Does anybody have an idea how to tell the ngModel it has new data?



EDIT: I figured out, the problem is the ngModel. Because I have to filter several values, my Model is filter.foobar. This is not working. If I change the model to foobar, it will work. I created a fiddle to illustrate: http://jsfiddle.net/StinsonMaster/6t3Nt/3/


More From » angularjs

 Answers
3

I have implemented a custom select2 dropdown directive. And register the change event handler to element which directive link to. The change event of the input element will be triggered when I selected a item from dropdown list.
Everything works as expected. You could try my implementation:



Directive



.directive('ajaxSelect2',['$timeout', function($timeout){
return {
restrict: 'A',
link: function(scope, element, attrs){
element.select2({
width: '200px',
createSearchChoice:function(term, data) { if ($(data).filter(function() { return this.text.localeCompare(term)===0; }).length===0) {return {id:term, text:term};} },
multiple: true,
data: [{id: 0, text: 'story'},{id: 1, text: 'bug'},{id: ccc, text: 'task'}]
});
element.bind(change,function(e){
scope.$apply(function(){
scope[attrs.ngModel] = e.val.toString();
});
});
}
};
}]);


HTML



<body ng-app=selectApp>
<div ng-controller=selectCtrl>
<span>Selcted value: {{input}}</span>
<div>
<input id=test2 ng-model=input ajax-select2/>
</div>
</div>
</body>


Here is the JSBin DEMO



[EDIT] For Property access problem



The ng-model of custom select2 element is filter.foo. You want to notify the angular world that the value of ng-model have been updated by select2 dropdown filter. But you can't access the second level property like this:



scope[attrs.ngModel] = e.val;  // equal to scope['filter.foo'] which is the first level property 'filter.foo'


You should access the property in this way:



var props = attrs.ngModel.split(.);
if(props.length>1){
scope[props[0]][props[1]] = e.val; //[] equals to dot '.'
}else{
scope[attrs.ngModel] = e.val;
}


Here is a jsFiddle demo



Hope this is helpful.


[#49426] Tuesday, December 17, 2013, 11 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
reed

Total Points: 725
Total Questions: 85
Total Answers: 89

Location: Singapore
Member since Sat, Jul 25, 2020
4 Years ago
;