0

I have a simple page with an input field and a button to change the name. The name changes on ng-click of the button, but what I want to happen is below the hello {{name}} text to have a log of the previous names selected and the time they were selected. eg

Hello Tom

  • sam - 1414530148463
  • Mick - 1414530159015

I have tried the below in this fiddle http://jsfiddle.net/4ybmyf1a/2/ but get the message, 'cannot read property push of undefined' (I have commented out in myCtrl so that the fiddle would run)

    <div ng-controller="MyCtrl">
        <input type="text" ng-model="updatedname" />
        <input type="button" value="Change name" ng-click="changeName(updatedname)"/>
        <br/>
          Hello, {{name}}!

    <ul>
        <li ng-repeat="names in namelog">{{nameLog.value}} - {{nameLog.time}}</li>
    </ul>    
    </div>


    var myApp = angular.module('myApp',[]);
    myApp.factory('UserService', function() {
                var userService = {};
                userService.name = "John";
                userService.ChangeName = function (value) {
                    userService.name = value;
                };
                userService.NameLog  = function (value) {
                    userService.nameLog.push ({
                        "value":value,
                        "time" :Date.now()
                    });
                };
        return userService;
    });

    function MyCtrl($scope, UserService) {
        $scope.name = UserService.name;
        $scope.updatedname="";
        $scope.changeName=function(data){
            $scope.updateServiceName(data);
        }
        $scope.updateServiceName = function(name){
            UserService.ChangeName(name);
            //UserService.NameLog(name);
            $scope.name = UserService.name;
            //$scope.nameLog = UserService.NameLog;
        }
    }

I have looked at also adding in userService.nameLog = [] to stop the undefined issue however this does not push the items like I want it.

        userService.NameLog  = function (value) {
            userService.nameLog = [];
            userService.nameLog.push ({
                "value":value,
                "time" :Date.now()
            });
        };

How am I able to acheive this?

3 Answers 3

2

Couple different things.

Your factory function LogName was referencing itself when pushing the log entry. This is the sort of thing you want to declare outside of the service object (_nameLog) and use a closure to return it back (getNameLog)

myApp.factory('UserService', function() {
        var _nameLog = [];
        var userService = {};
        userService.name = "John";
        userService.ChangeName = function (value) {
            userService.name = value;
        };
        userService.logName  = function (value) {
            _nameLog.push ({
                "value":value,
                "time" :Date.now()
            });
        };
        userService.getNameLog = function(){ return _nameLog; }
        return userService;
});

You were also using the ng-repeat incorrectly:

<li ng-repeat="name in nameLog">{{name.value}} - {{name.time}}</li>

Here is a working version: http://jsfiddle.net/sfqo2fn3/

Sign up to request clarification or add additional context in comments.

Comments

2

This is your first problem:

<li ng-repeat="names in namelog">{{nameLog.value}} - {{nameLog.time}}</li>

the variable you should be accessing in this ng-repeat is names, so this is the correct form (I also renamed the variable to make more sense):

<li ng-repeat="logEntry in namelog">{{logEntry.value}} - {{logEntry.time}}</li>

And second problem is your controller, here is a correct version:

function MyCtrl($scope, UserService) {
    $scope.name = UserService.name;
    // Add the name log to the scope here, not when you
    // invoke the updateServiceName function
    $scope.namelog = UserService.nameLog;

    $scope.changeName = function(data){
        $scope.updateServiceName(data);
    }

    $scope.updateServiceName = function(name){
        UserService.ChangeName(name);
        UserService.NameLog(name);
        $scope.name = UserService.name;
    }
}

In your version, you have commented out the following code:

//$scope.nameLog = UserService.NameLog;

That is wrong for two reasons. First the case of the nameLog variable is different in the controller and in the template (nameLog vs namelog). Second your are assigning it reference to the NameLog function not the nameLog property (again, notice the case).

When I made these modifications in your Fiddle it started working correctly.

And by the way, I think that the logic for adding log entry when you change username should be in the service itself not in the controller function.

Comments

1

I updated the jsfiddle with a working version after changing few things. Please refer it.

http://jsfiddle.net/4ybmyf1a/4/

These are the changes

 <li ng-repeat="names in nameLog">{{names.value}} - {{names.time}}</li>


myApp.factory('UserService', function() {
            var userService = {};
            var nameLog = [];
            userService.name = "John";

            userService.ChangeName = function (value) {
                userService.name = value;
            };

            userService.addNameToLog  = function (value) {
                nameLog.push ({
                    "value":value,
                    "time" :Date.now()
                });
                return nameLog;
            };

    userService.getNameLog = function() {
        return nameLog;
    }

    return userService;
});

Controller

function MyCtrl($scope, UserService) {
    $scope.name = UserService.name;
    $scope.updatedname="";

    $scope.changeName = function(data){
        $scope.updateServiceName(data);
    }

    $scope.updateServiceName = function(name){
        UserService.ChangeName(name);
        UserService.addNameToLog(name);
        $scope.name = UserService.name;
        $scope.nameLog = UserService.getNameLog();
        console.log(JSON.stringify($scope.nameLog));
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.