sirve - what is rootscope in angularjs
Cómo acceder/actualizar $ rootScope desde fuera de Angular (3)
Mi aplicación inicializa un gráfico de objetos en $ rootScope, así ...
var myApp = angular.module(''myApp'', []);
myApp.run(function ($rootScope) {
$rootScope.myObject = { value: 1 };
});
... y luego consume datos de ese gráfico de objeto (solo enlace de 1 vía), así ...
<p>The value is: {{myObject.value}}</p>
Esto funciona bien, pero si posteriormente (después de que la representación de la página se haya completado) intente actualizar $ rootScope y reemplace el objeto original por uno nuevo, se ignorará. Inicialmente asumí que esto se debía a que AngularJS guarda una referencia al objeto original, aunque lo haya reemplazado.
Sin embargo, si envuelvo el HTML que consume en un controlador, puedo actualizar varias veces su alcance de la manera prevista y las modificaciones se reflejan correctamente en la página.
myApp.controller(''MyController'', function ($scope, $timeout) {
$scope.myObject = { value: 3 };
$timeout(function() {
$scope.myObject = { value: 4 };
$timeout(function () {
$scope.myObject = { value: 5 };
}, 1000);
}, 1000);
});
¿Hay alguna manera de lograr esto a través de $ rootScope, o solo se puede hacer dentro de un controlador? Además, ¿hay un patrón más recomendado para implementar tales operaciones? Específicamente, necesito una forma de reemplazar los gráficos de objetos completos que consume AngularJS desde fuera del código AngularJS.
Gracias de antemano por sus sugerencias, Tim
Editar: como se sugiere en los comentarios, he intentado ejecutar el cambio dentro de $ apply, pero no ayuda:
setTimeout(function() {
var injector = angular.injector(["ng", "myApp"]);
var rootScope = injector.get("$rootScope");
rootScope.$apply(function () {
rootScope.myObject = { value: 6 };
});
console.log("rootScope updated");
}, 5000);
Después de actualizar $ rootScope, llame a $ rootScope. $ Apply () para actualizar los enlaces.
Piense en modificar los ámbitos como una operación atómica y $ apply () confirma esos cambios.
Si desea actualizar el objeto del ámbito raíz, inyecte $rootScope
en su controlador:
myApp.controller(''MyController'', function ($scope, $timeout, $rootScope) {
$rootScope.myObject = { value: 3 };
$timeout(function() {
$rootScope.myObject = { value: 4 };
$timeout(function () {
$rootScope.myObject = { value: 5 };
}, 1000);
}, 1000);
});
A excepción de casos muy, muy raros o con fines de depuración, hacer esto es solo una práctica MALA (¡o una indicación del diseño de una aplicación MALA)!
Para los casos muy, muy raros (o depuración), puede hacerlo así:
- Acceda a un elemento que sepa que es parte de la aplicación y envuélvalo como un elemento jqLite / jQuery.
- Obtenga el Ámbito del elemento y luego
$rootScope
accediendo a.scope().$root
. (También hay otras formas). - Haz lo que sea que hagas, pero envuélvelo en
$rootScope.$apply()
, así Angular sabrá que algo está pasando y hará su magia.
P.ej:
function badPractice() {
var $body = angular.element(document.body); // 1
var $rootScope = $body.scope().$root; // 2
$rootScope.$apply(function () { // 3
$rootScope.someText = ''This is BAD practice, dude ! :('';
});
}
Ver, también, esta breve demostración .
EDITAR
Angular 1.3.x introdujo una opción para deshabilitar la depuración de información para que se adjunte a los elementos DOM (incluido el scope
): $compileProvider.debugInfoEnabled()
Es aconsejable deshabilitar la depuración de información en la producción (por el rendimiento), lo que significa que el método anterior no funcionaría más.
Si solo desea depurar una instancia en vivo (producción), puede llamar a angular.reloadWithDebugInfo() , que volverá a cargar la página con la información de depuración habilitada.
Alternativamente, puede ir con Plan B (accediendo a $rootScope
través del inyector de un elemento):
function badPracticePlanB() {
var $body = angular.element(document.body); // 1
var $rootScope = $body.injector().get(''$rootScope''); // 2b
$rootScope.$apply(function () { // 3
$rootScope.someText = ''This is BAD practice, dude ! :('';
});
}