2014-09-01 135 views
4

我需要在多個控制器中使用datacontext。
datacontext可以以不同的方式更改(通過ajax調用,由用戶/視圖,服務器)。
當datacontext中的數據發生更改時,應通知所有使用datacontext的控制器。Angularjs:在控制器之間共享可觀察數據

的DataContext:

var userDataContext = { firstName: "John", lastName: "Doe" }; 

我在每一個例子模擬後端變化與setTimeout的

setTimeout(function() { 
    console.log("change firstname"); 
    userContext.firstName= "Bart"; 
}, 3000); 

這裏是淘汰賽,它工作正常的小提琴例子。
http://jsfiddle.net/8ct0L1zu/4/


我也試圖與做到這一點,但它部分地工作。

  • 當我將完整的對象傳遞給控制器​​(通過引用)時,更改在控制器之間起作用。
    在javascript/backend中更改datacontext時,它不會更改我的視圖。

  • 我也更喜歡在控制器範圍內只有名字和姓氏,而不是完整的對象。
    但在這種情況下,沒有任何工作。
    原因:在我們的應用程序中,會有大量的數據上下文與數組大對象。

http://jsfiddle.net/19xv3skn/1/


要真正讓它工作,我以前角與淘汰賽。數據綁定和數據上下文挖掘的角度。這工作正常,但我不太喜歡這個解決方案。
http://jsfiddle.net/7chp5xLa/2/


有一個最佳實踐或更好的方式與角度觀察到的一個的DataContext工作?

回答

2

我認爲這個問題可能是您考慮在AngularJS應用程序中管理數據的方式。您正在編輯AngularJS生命週期之外的userContext數據。不要管理AngularJS「看到」什麼,而是在將數據提供給AngularJS後編輯數據。相反,請考慮在Angular內部更改userContext狀態,在那裏您需要它

在您的示例中,您有兩個控制器在$ scope上具有相同的數據,也許您應該參考管理數據的公共父控制器爲$範圍,而不是:

jsfiddle

app.controller('ParentCtrl', function ($scope, userContext, $timeout) { 
    $scope.firstName = userContext.firstName; 
    $scope.lastName = userContext.lastName; 
    $scope.user = userContext; 
    $timeout(function() { 
     console.log("change firstname"); 
     userContext.firstName= "Bart"; 
    }, 3000); 
}); 

,事情就當你想要做不同的事情,並與每個控制器的UserContext更有趣。在這種情況下,您可能需要根據您的需要在控制器之間進行一些同步。關於在控制器之間共享狀態和在控制器之間進行通信的問題有很多答案。

+0

這個想法是「在datacontext和view之間沒有鏈接」。 當我使用ParentCtrl時,我的數據被鏈接到特定的視圖。 我的數據不需要關於ui的任何知識,它的剛好可以被任何控制器/視圖使用的數據。 – 2014-09-02 08:10:35

+0

這是真的userContext是在他的生命週期之外。 Angular使用稱爲髒檢查的技術觀察變量。 所以你只能使用控制器內部的變量。 Knockout使用Observable模式。這對我來說效果更好。 http://blog.nebithi.com/knockoutjs-vs-angularjs/ 對我來說不會有完美的解決方案:s – 2014-09-02 08:46:16

+0

的確,它完全取決於您的需求,無論Knockout還是AngularJs都是最合適的。 – 2014-09-02 09:14:37

0

也許我沒有得到你所需要的正確,但是我建議你得到一看$broadcast

可以播放控制器之間的事件,因此,如果在controllerA數據的變化,然後controllerB可以聽和執行邏輯(反之亦然)當事件被解僱時。

這裏有一個解釋:http://mariuszprzydatek.com/2013/12/28/sharing-data-between-controllers-in-angularjs-pubsub-event-bus-example/

一個骯髒的方式可以是使用$ rootScope來處理所有的應用程序相同的數據,所以當它改變它的工作流程無處不在改變。

希望它有幫助

2

你有幾個選項。

1-使用服務和廣播事件。

// service 
app.service("DataService", function($rootScope) { 
    var _name = ''; 
    var result = { 
     setName : function(name) { 
      _name = name; 
      $rootScope.$broadcast("nameChanged", _name); 
     }, 
     getName : function() { 
      return _name; 
     } 
    } 
    return result; 
}); 

// controller(s) 
app.controller("ObservingController", function($scope) { 
    $scope.$on("nameChanged", function(name) { 
     console.log("Something changed with name."); 
    }); 
}); 

// other controllers 
app.controller("ModifyingController", function($scope, DataService) { 
    // triggers the broadcast 
    DataService.setName("bob"); 
}); 

2)留意變化與表達

// controller - use the same DataService as above 
app.controller("WatchingController", function($scope, DataService) { 
    // bind the service to the scope for the expression 
    $scope.DataService = DataService; 
    $scope.$watch("DataService.getName()", function(newVal, oldVal) { 
     console.log("Name changed " + newVal); 
    }); 
}); 

這是給你,你喜歡什麼。我的服務也寫得很差,僅僅是一個例子。 $ rootScope僅用於向所有子範圍廣播。我不建議在那裏存儲數據。在數據上下文的情況下,如果將其包裝在服務中並公開,則可以將服務(或由服務公開的變量)綁定到示例中,並且您的手錶應觸發。

// service 
app.service("DataContextService", function() { 
    var context = { 
     firstName : "", 
     lastName : "" 
    }; 
    return { 
     context : context 
    }; 
}); 

// controller 
app.controller("Watcher", function($scope, DataContextService) { 
    $scope.context = DataContextService.context; 
    $scope.$watch("context.firstName", function(newVal, oldVal) { 
     console.log("Change.."); 
    }); 
}); 

app.controller("Modifier", function($scope, DataContextService) { 
    // causes the watch to trigger 
    DataContextService.context.firstName = "Bob"; 
}); 
+0

這和我的解決方案一樣安靜。 除了我正在使用Knockout並在您的示例中,您正在編程它自己。 Knockout有一個完全可觀察的模式,它非常強大(計算好,性能好等),因此我更喜歡使用Knockout來處理DataContextService。 – 2014-09-02 08:35:25

相關問題