2013-06-12 35 views
2

$watch荷兰国际集团的对象更改和设置$scope.changed = true,但是有些情况下,我想将它设置为false我已经改变了数据之后编程:

$scope.$watch('data', function() { 
    $scope.changed = true; 
}, true); 

function loadData(data) { 
    $scope.data = data; 

    // I want to run $scope.$apply() here so the $watch is triggered 
    // before changed is set back to false 
    $scope.$apply(); 

    $scope.changed = false; 
} 

// in DOM: 
<div ng-click="loadData(newData)"> 

如果我使用非角度事件手动运行loadData,它可以很好地工作(当然$apply之后会再次显示范围),但是如果从类似上面的ngClick之类的东西运行它,则会出现“$ apply already in progress”错误。

使用$timeout在大多数情况下都能正常工作,但也有一些地方我真的希望它同步发生。

function loadData(data) { 
    $scope.data = data; 
    // what I want to avoid: 
    $timeout(function() { 
     $scope.changed = false; 
    }) 
} 

是否可以同步应用范围更改,还是我在做更改处理错误?

谢谢。

回答

3

如果你没有做很特别的事,你可以用angular.equals来检查两个对象是否相等。与angular.copy结合使用,以便您拥有原始数据的副本。

$scope.isDirty = function() { 
    return !angular.equals(initialData, $scope.data); 
} 

Plunker

这样做,这样你不必担心你的$watch功能的顺序和代码会更容易理解。

表现明智,但这可能会更重。您可以通过更改来优化它,以便在更改数据时仅更改isDirty。

+0

谢谢,效果很好,经过一段时间摆弄之后,开销应该不会太差。我修改了它,所以在'changed'被重置后的第一次数据更改后,它不需要运行比较。谢天谢地,我不需要知道它是否恢复到原来的状态。 [Plnkr](http://plnkr.co/edit/OI2zobbwsm0NKgqlXj6v?p=preview) –

0

ngclick将占据$apply处理程序,所以在功能就像你不能运行的过程,需要在$apply的事件处理函数,只需$timeout所有行动:

function loadData(data){ 
    $timeout(function(){ 
     $scope.data = data; 
     $scope.$apply(); 
     $scope.changed = false; 
    }); 
} 

试试这个,而不是测试。 ..

+0

我想如果可能的话做这一切同步,设置'$超时“是我目前的解决方法,但与异步操作一起工作往往会增加复杂性。 –

+0

@DeathCarrot我认为function(){#code#}和function(){$ timeout(function(){#code#})}几乎是相同的,除了在click事件的端点之前或之后运行。确保#代码#和点击事件端点的同步? –

+0

在某些情况下,loadData函数的等价物远离调用堆栈,原始调用可以从几个地方调用,其中一些可能深入别人的代码中。还有其他的超时时间取决于'changed'的有效值,它不会在'$ watch'和'$ timeout'之间。当然,你可以在两个'$ timeout'中包装使用'changed'的代码,但最终会变得乏味。 –

0

您可以使用第二个$scope变量来跟踪变化是否来自特定功能,并基于该变量启用$watch中的变量分配$scope.changed

添加一个变量作为loadData()函数中的标记。在这种情况下,我们把它叫做$scope.explicitChange

function loadData(data) { 
    $scope.data = data; 

    // I want to run $scope.$apply() here so the $watch is triggered 
    // before changed is set back to false 
    $scope.$apply(); 

    $scope.changed = false; 
    $scope.explicitChange = true; 
} 

检查$scope.explicitChange已被设定$watch

$scope.$watch('data', function(){ 
    if(!$scope.explicitChange){ 
     $scope.changed = true; 
    } 
    else{ 
     // Reset $scope.explicitChange 
     $scope.explicitChange = false; 
    } 
}, true);