0

I have three models startDate,endDate,durationMillis in scope. If any of the value is changed by use, I need to calculate the other model by $watch.

$scope.$watch('startDate', function()
{
    $scope.endDate = new Date($scope.startDate.getTime() + $scope.durationMillis);
});

$scope.$watch('endDate', function()
{
    $scope.durationMillis = $scope.endDate.getTime() + $scope.startDate.getTime();
});

$scope.$watch('durationMillis', function()
{
    $scope.startDate = new Date($scope.endDate.getTime() - $scope.durationMillis.getTime());
});

Here, my problem is when user changes start date/end date/duration, $watch of calculated attributes(not changed by user) has been called recursively.

2 Answers 2

1

The only solution I have found for this kind of problems is using an external flag and the following ugly code:

var triggeredBySystem = false;

$scope.$watch('startDate', function() {
    if( !triggeredBySystem ) {
        $scope.endDate = new Date($scope.startDate.getTime() + $scope.durationMillis);
        triggeredBySystem = true;
    }
    else {
        triggeredBySystem = false;
    }
});

$scope.$watch('endDate', function() {
    if( !triggeredBySystem ) {
        $scope.durationMillis = $scope.endDate.getTime() + $scope.startDate.getTime();
        triggeredBySystem = true;
    }
    else {
        triggeredBySystem = false;
    }
});

$scope.$watch('durationMillis', function() {
    if( !triggeredBySystem ) {
        $scope.startDate = new Date($scope.endDate.getTime() - $scope.durationMillis.getTime());
        triggeredBySystem = true;
    }
    else {
        triggeredBySystem = false;
    }
});

I would be interested in better solutions myself...

(I would refactor the common code above of course, but here I am just demonstrating the principle.)

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks. As of now worked great. But looking for a better solution.
0

Ok so I guess a Solution for the loop could be to unwatch other watches and then re init the watches (still feel dirty) :

blog for unbind : http://www.bennadel.com/blog/2480-unbinding-watch-listeners-in-angularjs.htm

function init(){
    $scope.unbindStart = $scope.$watch('startDate', function()
    {
        $scope.unbindStart();
        $scope.unbindEnd();
        $scope.unbindDuration();
        $scope.endDate = new Date($scope.startDate.getTime() + $scope.durationMillis);

        $timeout(setupWatch,10);
    });

    $scope.unbindEnd = $scope.$watch('endDate', function()
    {
        $scope.unbindStart();
        $scope.unbindEnd();
        $scope.unbindDuration();
        $scope.durationMillis = $scope.endDate.getTime() + $scope.startDate.getTime();

        $timeout(setupWatch,10);
    });

    $scope.unbindDuration = $scope.$watch('durationMillis', function()
    {
        $scope.unbindStart();
        $scope.unbindEnd();
        $scope.unbindDuration();
        $scope.startDate = new Date($scope.endDate.getTime() - $scope.durationMillis.getTime());

        $timeout(setupWatch,10);
    });
}

function setupWatch(){

    init();

}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.