title: AngularJS - how to handle circular watch?
body: <p>Suppose I am working with a directive that is given a date in form of a unix timestamp via two-way binding, but also offers a calendar widget to change the selection.</p>
  
  <p>The calendar widget works with a date object, and I am unable to change the input data format and I do not want to rework the calendar to support unix timestamp. Also this is just an example and the question is about general way of working with circular watchers.</p>
  
  <p>The scope would look like this:</p>
  
  <pre><code>scope.selectedUnixTimestamp; // this comes from the outside
  scope.selectedDate;
  
  scope.$watch('selectedUnixTimestamp', function(newV, oldV) {
      $scope.selectedDate = new Date(newV*1000);
  });
  scope.$watch('selectedDate', function(newV, oldV) {
      $scope.selectedUnixTimestamp = Math.floor(newV.getTime()/1000 + 0.000001);
  });
  </code></pre>
  
  <p>My question is: <strong>what do I do in order to avoid extra calls to $watch callbacks?</strong> Obviously if I choose a new date, the flow will be following:</p>
  
  <ol>
  <li>Watcher #2 is called - it modifies selectedUnixTimestamp</li>
  <li>Watcher #1 is called - it modifies selectedDate</li>
  <li>Watcher #2 is called again (new object reference) - it modifies selectedUnixTimestamp </li>
  </ol>
  
  <p>But I don't want any of those calls besides the first one. How do can I achieve it?</p>
  
  <hr>
  
  <p>Obviously one way would be to do something like:</p>
  
  <pre><code>scope.selectedUnixTimestamp; 
  scope.selectedDate;
  
  var surpressWatch1 = false;
  var surpressWatch2 = false;
  
  scope.$watch('selectedUnixTimestamp', function(newV, oldV) {
      if(surpressWatch1) { surpressWatch1 = false; return; }
      $scope.selectedDate = new Date(newV*1000);
      surpressWatch2 = true;
  });
  scope.$watch('selectedDate', function(newV, oldV) {
      if(surpressWatch2) { surpressWatch2 = false; return; }
      $scope.selectedUnixTimestamp = Math.floor(newV.getTime()/1000 + 0.000001);
      surpressWatch1 = true;
  });
  </code></pre>
  
  <p>But it quickly becomes a hell to maintain a code like that.</p>
  
  <hr>
  
  <p>Another way would be to do something like:</p>
  
  <pre><code>scope.selectedUnixTimestamp; 
  scope.selectedDate;
  
  scope.$watch('selectedUnixTimestamp', function(newV, oldV) {
      if(newV*1000 === scope.selectedDate.getTime()) { return; }
      $scope.selectedDate = new Date(newV*1000);
  });
  scope.$watch('selectedDate', function(newV, oldV) {
      if(scope.selectedUnixTimestamp*1000 === newV.getTime()) { return; }
      $scope.selectedUnixTimestamp = Math.floor(newV.getTime()/1000 + 0.000001);
  });
  </code></pre>
  
  <p>But it might be very costful if the data transformation is more complicated than <code>* 1000</code></p>
  
  <hr>
  
  <p>Another way would be to watch on primitive value instead of a date object:</p>
  
  <pre><code>scope.$watch('selectedDate.getTime()', function(newV, oldV) {
  </code></pre>
  
  <p>But this only works with this particular example and does not solve the general issue  </p>