2013-06-12 75 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);