Joe82
Joe82

Reputation: 1251

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.

Upvotes: 1

Views: 572

Answers (2)

Georgy
Georgy

Reputation: 2462

Why can't you modify checkbox propery itself? Changing input's model to opt.checkbox and commenting watch out make everything work. I think it's better this way.

But you can modify opt.checkbox = nv.cars[opt.element] to opt.checkbox = !!nv.cars[opt.element] to make it work too (the checkbox property in cars object is undefined, that breaks proper ordering).

Upvotes: 1

Yaron Schwimmer
Yaron Schwimmer

Reputation: 5357

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.

Upvotes: 2

Related Questions