Joe82 Joe82 - 7 days ago 5
AngularJS Question

AngularJs - <ul> <li> element to top when its checkbox is checked

This question is based in this previous one

I have a

ng-repeat
like this:

<li ng-repeat="opt in namesCtrl.uniqueCars">
<input type="checkbox" ng-model="namesCtrl.filter['cars'][opt.element]" | orderBy:['checkbox','-count']"><p2>{{opt.element}} ({{opt.count}})</p2>
</li>


Where the elements are taken from
this.uniqueCars


this.uniqueCars=[
{'element':'Ford','count':3,'checkbox':false},
{'element':'Honda','count':2,'checkbox':false},
{'element':'Ferrari','count':1,'checkbox':false},
{'element':'Delorean','count':6,'checkbox':false}
];


And the checked items in the view go to
this.filter
(that I use for another purpose)

this.filter = {
"cars": {}
}


So what I want to achieve is to order the checkbox list in the view, so when one of the items is checked, it would go to the top, something like this

enter image description here

enter image description here

In order to do that, I have a
$watch
that goes like this

$scope.$watch("namesCtrl.filter", function(nv,ov){
angular.forEach(self.uniqueCars, function(opt){
opt.checkbox = nv.cars[opt.element]
})
}, true)


But the behavior is pretty inconsistent when ordering by the checkbox value (when first clicking it does the job, OK, but when unclicking it doesn't work, and when clicking again it sorts it in the opposite way).

So I would like to do this by modifying the
$watch
. (I do it this way as IRL
this.filter
could be modified by other elements, so I need to watch the changes there).

PS: the
this.uniqueCars.checkbox
the field is inserted by me just in order to make the sorting possible, so it would be safe to modify it.

You can check the working Plunker here.

Answer

You almost got it right.
There was a small problem with your $watch function: In the case where a car is not yet a member of namesCtrl.filter, its checkbox value is removed from namesCtrl.uniqueCars because it's undefined.
If you handle this case like this:

$scope.$watch("namesCtrl.filter", function(nv,ov){
  angular.forEach(self.uniqueCars, function(opt){
    var value = nv.cars[opt.element] ? nv.cars[opt.element].checkbox : false;
    opt.checkbox = value;
  });
}, true);

Then your ordering is fine. Except you also need to order by checkbox in reverse order:

<li ng-repeat="opt in namesCtrl.uniqueCars | orderBy:['-checkbox','-count']">

See working plunker.