0

I'm still learning AngularJS and I'm trying to (for example) switch the names on a regular interval. I've got most of the basic idea down but I'm running into problems with how Angular handles how information is shared I've tried this:

http://jsfiddle.net/nwz5krw4/1/ The core of the fiddle is this (where names is an array of names):

this.changeName = function($scope,names)
    {
        this.nameIndex++;
        if ($scope.$parent.nameIndex > (names.size - 1))
        {
            $scope.$parent.nameIndex = names[0];
        }
        else
        {
            $scope.$parent.myName = names[$scope.$parent.nameIndex];
        }

    };

Oddly, that will load in the browser and give me the first name, then simply refuse to change Reading the console reveals that t. Another path I've taken based on How do I use $rootScope in Angular to store variables? is to create this:

app.run(function($rootScope){

});

And place my array of names in there as $rootScope.names. Obviously $rootScope is to be avoided where possible, but right now I'm just going for functionality. However, this, too, did not work. Passing $scope to the method resulted in $scope.names or $rootScope.names being undefined. I'm not yet "thinking in Angular" and need some mental translation to make the leap.

Community
  • 1
  • 1
odinkirk
  • 3
  • 1
  • 4

2 Answers2

1

You don't need to pass $scope and names to the this.changeName method.

Just create a reference to this e.g. name it vm, self or that and then you can use your object variables inside of the method. That's required because this is different in the $interval callback.

Alternatively you could bind this to the callback and your won't need to store the reference.

Please find the working demo below and here at JSfiddle.

(function () {
    var app = angular.module('hello-world', []);

    app.controller('helloController', function ($scope, $interval) {
        // Create an array of names.
        var names = [
            "Jed",
            "Leo",
            "Josh",
            "Toby",
            "Sam",
            "CJ",
            "Donna",
            "Charlie",
            "Delores",
            "Abby",
            "Will"];

        // Set initial values for on-page elements
        var vm = this; // reference to view-model
        this.myName = names[0];
        this.nameIndex = 0;
        
        /**
         * Changes the name when called.
         */
        this.changeName = function () {
            vm.nameIndex = vm.nameIndex++ >= names.length - 1 ? 0: vm.nameIndex; 
            vm.myName = names[vm.nameIndex];
            console.log(vm.myName, vm.nameIndex);
        };

        $interval(this.changeName, 2000);
    });
})();
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="hello-world">
    <div ng-controller="helloController as hi">
        
<h1 style="text-align: center" ng-style="{'color':hi.myColor}">Hello, {{hi.myName}}</h1>

    </div>
</body>
AWolf
  • 8,770
  • 5
  • 33
  • 39
0

Alright, so first of all. A really good tip when doing controllerAs syntax, in your controller, assign this to a variable.

var hi = this;

This will avoid any weird internal this conflicts, and you wont have to mess with rootScope or $parent or any of that nonsense.

So I switched it to using that and it works fine. I also moved over to plunker because JSFiddle is pretty crappy and was giving me a bunch of strange angular errors. Anyways, here is a working fiddle

http://plnkr.co/edit/53Md9eAZmq0gRRs1hfkp?p=preview

You will see, all I did was change all the $scope.$parent to use the new variable that 'this' was assigned to.

ribsies
  • 1,218
  • 2
  • 10
  • 16
  • Yours was first and was an equally good answer but I gave the checkmark to AWolf due to the on-page example making it easier for those who follow. Thanks to both of you! – odinkirk Feb 18 '15 at 22:34