Angularjs: 'controller as syntax' and $watch

前端 未结 10 1399
抹茶落季
抹茶落季 2020-11-28 18:52

How to subscribe on property change when using controller as syntax?

controller(\'TestCtrl\', function ($         


        
相关标签:
10条回答
  • 2020-11-28 19:34

    NOTE: This doesn't work when View and Controller are coupled in a route or through a directive definition object. What's shown below only works when there's a "SomeController as SomeCtrl" in the HTML. Just like Mark V. points out in the comment below, and just as he says it's better to do like Bogdan does it.

    I use: var vm = this; in the beginning of the controller to get the word "this" out of my way. Then vm.name = 'Max'; and in the watch I return vm.name. I use the "vm" just like @Bogdan uses "self". This var, be it "vm" or "self" is needed since the word "this" takes on a different context inside the function. (so returning this.name wouldn't work) And yes, you need to inject $scope in your beautiful "controller as" solution in order to reach $watch. See John Papa's Style Guide: 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);
        });
    }
    
    0 讨论(0)
  • 2020-11-28 19:38

    I usually do this:

    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)
       });
    });
    
    0 讨论(0)
  • 2020-11-28 19:38

    AngularJs 1.5 supports the default $ctrl for the ControllerAs structure.

    $scope.$watch("$ctrl.name", (value) => {
        console.log(value)
    });
    
    0 讨论(0)
  • 2020-11-28 19:41

    Similar to using the "test" from "TestCtrl as test", as described in another answer, you can assign "self" your scope:

    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)
            });
    })
    

    In this way, you are not tied to the name specified in the DOM ("TestCtrl as test") and you also avoid the need to .bind(this) to a function.

    ...for use with the original html specified:

    <div ng-controller="TestCtrl as test">
        <input type="text" ng-model="test.name" />
        <a ng-click="test.changeName()" href="#">Change Name</a>
    </div>
    
    0 讨论(0)
  • 2020-11-28 19:45

    You can use $onChanges angular component lifecycle.

    see documentation here: https://docs.angularjs.org/guide/component under Component-based application section

    0 讨论(0)
  • 2020-11-28 19:46

    Just bind the relevant context.

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

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

    UPDATE:

    Bogdan Gersak's answer is actually kind of equivalent, both answers try binding this with the right context. However, I found his answer cleaner.

    Having that said, first and foremost, you have to understand the underlying idea behind it.

    UPDATE 2:

    For those who use ES6, by using arrow function you get a function with the right context OOTB.

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

    Example

    0 讨论(0)
提交回复
热议问题