varios sintaxis otro llamar funcion entre directivas controladores controlador comunicacion javascript angularjs angularjs-scope ng-controller

javascript - otro - Angularjs: ''controlador como sintaxis'' y $ watch



ng-model (10)

AngularJs 1.5 admite el $ ctrl predeterminado para la estructura ControllerAs.

$scope.$watch("$ctrl.name", (value) => { console.log(value) });

¿Cómo suscribirse al cambio de propiedad cuando se usa el controller as sintaxis?

controller(''TestCtrl'', function ($scope) { this.name = ''Max''; this.changeName = function () { this.name = new Date(); } // not working $scope.$watch("name",function(value){ console.log(value) }); });

<div ng-controller="TestCtrl as test"> <input type="text" ng-model="test.name" /> <a ng-click="test.changeName()" href="#">Change Name</a> </div>


Aquí es cómo hacer esto sin $ scope (¡y $ watch!) Los 5 errores principales: abuso de reloj

Si está utilizando la sintaxis de "controlador como", es mejor y más limpio evitar el uso de $ scope.

Aquí está mi código en JSFiddle . (Estoy utilizando un servicio para mantener el nombre; de ​​lo contrario, los métodos set y get de ES0 Object.de.finanProperty causan llamadas infinitas.

var app = angular.module(''my-module'', []); app.factory(''testService'', function() { var name = ''Max''; var getName = function() { return name; } var setName = function(val) { name = val; } return {getName:getName, setName:setName}; }); app.controller(''TestCtrl'', function (testService) { var vm = this; vm.changeName = function () { vm.name = new Date(); } Object.defineProperty(this, "name", { enumerable: true, configurable: false, get: function() { return testService.getName(); }, set: function (val) { testService.setName(val); console.log(vm.name); } }); });


Escribir un reloj $ en la sintaxis de ES6 no fue tan fácil como esperaba. Esto es lo que puedes hacer:

// Assuming // controllerAs: "ctrl" // or // ng-controller="MyCtrl as ctrl" export class MyCtrl { constructor ($scope) { ''ngInject''; this.foo = 10; // Option 1 $scope.$watch(''ctrl.foo'', this.watchChanges()); // Option 2 $scope.$watch(() => this.foo, this.watchChanges()); } watchChanges() { return (newValue, oldValue) => { console.log(''new'', newValue); } } }


Puede usar el ciclo de vida del componente angular $ onChanges .

Consulte la documentación aquí: docs.angularjs.org/guide/component en la sección de aplicación basada en componentes


Puedes usar:

$scope.$watch("test.name",function(value){ console.log(value) });

Esto está funcionando JSFiddle con tu ejemplo.


Similar a usar la "prueba" de "TestCtrl como prueba", como se describe en otra respuesta, puede asignar "self" su alcance:

controller(''TestCtrl'', function($scope){ var self = this; $scope.self = self; self.name = ''max''; self.changeName = function(){ self.name = new Date(); } $scope.$watch("self.name",function(value){ console.log(value) }); })

De esta forma, no estás vinculado al nombre especificado en el DOM ("TestCtrl como prueba") y también evitas la necesidad de enlazar (esto) a una función.

... para usar con el html original especificado:

<div ng-controller="TestCtrl as test"> <input type="text" ng-model="test.name" /> <a ng-click="test.changeName()" href="#">Change Name</a> </div>


Solo une el contexto relevante.

$scope.$watch(angular.bind(this, function () { return this.name; }), function (newVal) { console.log(''Name changed to '' + newVal); });

Ejemplo: http://jsbin.com/yinadoce/1/edit

ACTUALIZAR:

La respuesta de Bogdan Gersak es realmente equivalente, ambas respuestas intentan unir this con el contexto correcto. Sin embargo, encontré su respuesta más limpia.

Habiendo dicho eso, antes que nada, debes entender la idea subyacente detrás de esto .

ACTUALIZACIÓN 2:

Para aquellos que usan ES6, al usar la arrow function obtienes una función con el contexto correcto OOTB.

$scope.$watch(() => this.name, function (newVal) { console.log(''Name changed to '' + newVal); });

Example


Usualmente hago esto:

controller(''TestCtrl'', function ($scope) { var self = this; this.name = ''Max''; this.changeName = function () { this.name = new Date(); } $scope.$watch(function () { return self.name; },function(value){ console.log(value) }); });


puedes pasar una función como primer argumento de $ watch ():

app.controller(''TestCtrl'', function ($scope) { this.name = ''Max''; // hmmm, a function $scope.$watch(function () {}, function (value){ console.log(value) }); });

Lo que significa que podemos devolver nuestra referencia this.name:

app.controller(''TestCtrl'', function ($scope) { this.name = ''Max''; // boom $scope.$watch(angular.bind(this, function () { return this.name; // `this` IS the `this` above!! }), function (value) { console.log(value); }); });

Lea una publicación interesante sobre el tema del controlador https://toddmotto.com/digging-into-angulars-controller-as-syntax/


NOTA : Esto no funciona cuando View y Controller están acoplados en una ruta o a través de un objeto de definición de directiva. Lo que se muestra a continuación solo funciona cuando hay un "SomeController SomeCtrl" en el HTML. Al igual que Mark V. señala en el comentario a continuación, y justo cuando dice que es mejor hacer como Bogdan lo hace.

Yo uso: var vm = this; al comienzo del controlador para sacar la palabra "esto" de mi camino. Entonces vm.name = ''Max''; y en el reloj return vm.name . Utilizo el "vm" al igual que @Bogdan usa "self". Esta var, ya sea "vm" o "self" es necesaria ya que la palabra "this" toma un contexto diferente dentro de la función. (por lo que devolver this.name no funcionaría) Y sí, necesita inyectar $ scope en su hermosa solución de "controlador como" para alcanzar $ watch. Consulte la Guía de estilo de John Papa: https://github.com/johnpapa/angularjs-styleguide#controllers

function SomeController($scope, $log) { var vm = this; vm.name = ''Max''; $scope.$watch(''vm.name'', function(current, original) { $log.info(''vm.name was %s'', original); $log.info(''vm.name is now %s'', current); }); }