Sunday, 15 April 2012

How to create angular ui-select directive wrapper which binds property of the selected item to a model -



How to create angular ui-select directive wrapper which binds property of the selected item to a model -

i trying create angular directive wrapper on top of ui-select directive. goal give directive list items , model sync particular property of selected item(s). directive has 5 attributes:

ng-model - specify model, items - specify list of items, display-prop - name of property used within ui-select display purpose, value-prop - name of property used model assignment, multiple [optional] - if multiple selection allowed

in directive kid scope have object syncs ui-select ng-model , when changed updating main scope.

i manage create things working single selected item , multiple items when start empty selection. still have problem display initial selected items when multiple selection chosen. think problem somewhere scopes , $watch methods between directive , ui-select directive. looks updates in directive scope not impact ui-select ng-model in case of array. i've create plunker simple application containing directive , test case can see single selection works correctly when have array list not initialized.

angular.module('dgui', ['ui.select', 'ngsanitize']) .config(['uiselectconfig', function(uiselectconfig){ uiselectconfig.theme = 'select2'; }]) .controller('uiselectwrapperconttoller', ['$scope', function($scope){ $scope.useraddresses = [ { address: 'address 1', description: 'home address' }, { address: 'address 2', description: 'office address' }, { address: 'address 3', description: 'test address 3' }, { address: 'address 4', description: 'test address 4' } ]; $scope.currentuser = { name: 'user 1', address: 'address 1' }; $scope.currentuser = { name: 'user 1', address: 'address 2', availableaddresses:['address 3'] }; }]) .directive('dgselect', ['$parse', function ($parse) { homecoming { restrict: 'ae', require: ['ngmodel'], scope: true, templateurl: function(telement, tattrs) { homecoming '/global/dg-ui/dg-select' + ((angular.isdefined(tattrs.multiple) ? '-multi' : '') + '.tpl.html'); }, compile: function (telement, tattrs) { var displaypropsufix = tattrs.displayprop ? '.' + tattrs.displayprop : ''; var ismultiple = angular.isdefined(tattrs.multiple) ; //match element config if (tattrs.placeholder) { $('ui-select-match, *[ui-select-match]', telement).attr('placeholder', tattrs.placeholder); } if(ismultiple){ $('ui-select-match, *[ui-select-match]', telement).html('{{$item' + displaypropsufix + '}}'); }else{ $('ui-select-match, *[ui-select-match]', telement).html('{{$select.selected' + displaypropsufix + '}}'); } //choices element config $('ui-select-choices, *[ui-select-choices]', telement).attr('repeat', 'listitem in ' + tattrs.items + ' | filter:$select.search') $('ui-select-choices, *[ui-select-choices]', telement).html('<div ng-bind-html="listitem' + displaypropsufix + ' | highlight: $select.search"></div>'); homecoming function link(scope, element, attrs, ctrls) { scope.ngmodel = ctrls[0]; scope.ismultiple = angular.isdefined(attrs.multiple) scope.itemsgetter = $parse(attrs.items); if(angular.isdefined(attrs.valueprop) && attrs.valueprop !== ''){ scope.valuepropgetter = $parse(attrs.valueprop); } scope.getvaluemapper = function(itemobject){ homecoming scope.valuepropgetter ? scope.valuepropgetter(itemobject) : itemobject; } scope.updatevaluefrommodel = function(modelvalue){ if(scope.ismultiple){ var selectionarray = []; angular.foreach(modelvalue, function(modelitem, key){ var modelitemvalue = scope.getvaluemapper(modelitem); selectionarray.push(modelitemvalue); }); scope.selectionmodel = selectionarray; }else{ var items = scope.itemsgetter(scope); angular.foreach(items, function(item, key){ var itemvalue = scope.getvaluemapper(item); if(itemvalue == modelvalue){ scope.selectionmodel = item; homecoming false; } }); } } if(scope.ismultiple){ scope.$watchcollection(attrs.ngmodel, function(modelvalue, oldvalue) { scope.updatevaluefrommodel(modelvalue); }); }else{ scope.$watch(attrs.ngmodel, function(modelvalue){ scope.updatevaluefrommodel(modelvalue); }); } //watch items in case of async loading //scope.$watch(attrs.items, function(){ // scope.updatevaluefrommodel(scope.ngmodel.$modelvalue); //}); scope.onitemselect = function(item, model){ var movelvalue = scope.getvaluemapper(item); if(scope.ismultiple){ scope.ngmodel.$viewvalue.push(movelvalue); }else{ scope.ngmodel.$setviewvalue(movelvalue); } } scope.onitemremove = function(item, model){ var removedmodelvalue = scope.getvaluemapper(item); if(scope.ismultiple){ var removeindex = null; angular.foreach(scope.ngmodel.$viewvalue, function(itemvalue, index){ if(itemvalue == removedmodelvalue){ removeindex = index; homecoming false; } }); if(removeindex){ scope.ngmodel.$viewvalue.splice(removeindex, 1); } }else{ scope.ngmodel.$setviewvalue(movelvalue); } } } } }; }]) .run(['$templatecache', function ($templatecache) { $templatecache.put('/global/dg-ui/dg-select.tpl.html', '<ui-select class="ui-select" ng-model="selectionmodel" on-select="onitemselect($item, $model)" on-remove="onitemremove($item, $model)" ng-disabled="disabled"><ui-select-match></ui-select-match><ui-select-choices></div></ui-select-choices></ui-select>'); $templatecache.put('/global/dg-ui/dg-select-multi.tpl.html', '<ui-select class="ui-select" multiple ng-model="selectionmodel" on-select="onitemselect($item, $model)" on-remove="onitemremove($item, $model)" ng-disabled="disabled"><ui-select-match></ui-select-match><ui-select-choices></ui-select-choices></ui-select>'); }]);

probably doing wrong here. appreciate help :), thanks!

there such functionality in ui-select. specify property in repeater this:

repeat="item.indexprop item in myctrl.items"

and whole markup this:

<ui-select ng-model="myctrl.selecteditem" theme="select2"> <ui-select-match placeholder="select item...">{{$select.selected.captionprop}}</ui-select-match> <ui-select-choices repeat="item.indexprop item in myctrl.items | filter: $select.search" value=" {{$select.selected.indexprop}}"> <div ng-bind-html="item.captionprop | highlight: $select.search"></div> </ui-select-choices> </ui-select>

so if item looks like:

{indexprop: 1, captionprop: 'item name'}

ui-select display item's "captionprop" in dropdown , pass "indexprop" ng-model.

angularjs-directive angular-ui ui-select2

No comments:

Post a Comment