0
votes

Introduction

I' m writing checkbox tree directive using angular. Part of the behaviour is when I check checkbox in the middle of the tree, I need to unset all ancestor checkboxes and set all descendant checkboxes (see screenshot, transparent checkboxes are unchecked in fact).

https://www.dropbox.com/s/yx1bzqsamunmjpx/Screenshot%20from%202014-08-25%2018%3A39%3A44.png?dl=0

I'm using:

itemScope.$watch('checked', function setCheckboxes(newValue, oldValue) { ... });

For descendants everything works fine. I forEach child checkboxes and set them a new value, which in turn fires events for their descendants and so forth.

Problem is with ancestors. If I set parent checked value to false, it triggers event which sets all children to false which is not desired.

Question starts here:

I need to find a way to update (ancestor checkbox) model without firing event I subscribed with $watch. I know one way to wrap new value assignment in setTimeout(fn, 1), but I think it's not cool. What's the correct way of doing this?

Thanks!

1
Wrapping with setTimeout just defer the event firing, it doesn't solve the problem. - runTarm
You are incorrect. Check this out: jsfiddle.net/megapotz/da9o801a/3 it fires event on the second hit, because first time with setTimeout angular looses execution flow, so only next button press it finds out value has changed. - megapotz
The behavior that you've described above is exactly what I mean by "defer the event firing". And yes, the next button press will cause the problem that has been deferred. In a real world application, there are a lot of things that would trigger a digest cycle. - runTarm

1 Answers

1
votes

You could use the ngChange directive on the checkbox to kick off the correct behavior, rather than $scope.watch. From the docs:

The ngChange expression is only evaluated when a change in the input value causes a new value to be committed to the model.

It will not be evaluated:

  • if the value returned from the $parsers transformation pipeline has not changed
  • if the input has continued to be invalid since the model will stay null
  • if the model is changed programmatically and not by a change to the input value