4

I'm trying to make my first AngularJS application and I've run into a problem.

I have an input:

<input ng-model="userNameLogin" type="text" placeholder="username" class="form-control">

A button:

<button ng-click="setActiveUser()" type="submit" class="btn btn-success">Sign in</button>

and an expression:

{{ activeUser }}

I want the text to change to whatever was typed in the input once the button is clicked. For that I have the following controller:

app.controller('View1Ctrl', ['$scope', function($scope) {
    $scope.userNameLogin = "";
    $scope.activeUser = "Test";

    $scope.setActiveUser = function() {
        $scope.activeUser = $scope.userNameLogin;
        console.log($scope.activeUser);
    };
}]);

The initial value "Test" is shown just fine and according to the console the value of "activeUser" is being changed correctly as well. But the text in the view stays the same.

I have seen similar questions where a $scope.$apply() was the answer, but if I add that after the console.log I get

"Error: [$rootScope:inprog] $apply already in progress".

What am I missing here?

EDIT:

I have noticed that If I put the input, button and expression in the same HTML file it all works fine. However my Input and button are in a navbar in index.html while the expression is in view1.html

This is the body of index.html:

    <body ng-app="myApp.view1">
<nav class="navbar navbar-inverse navbar-fixed-top" ng-controller="View1Ctrl as view">
    <div class="container">
        <div class="navbar-header">
            <a class="navbar-brand" href="#/view1">Kwetter</a>
        </div>
        <div class="navbar-collapse collapse" >
            <ul class="nav navbar-nav">
                <li><a href="#/view1">Home</a></li>
                <li><a href="#/view2">Profile</a></li>
            </ul>
            <form class="navbar-form navbar-right">
                <div class="form-group">
                    <input ng-model="userNameLogin" type="text" placeholder="username" class="form-control">
                </div>
                <div class="form-group">
                    <input type="password" placeholder="password" class="form-control">
                </div>
                <button ng-click="setActiveUser()" type="submit" class="btn btn-success">Sign in</button>
            </form>
        </div>
    </div>
</nav>
<div id="pagewrapper" class="container">

    <div ng-view></div>

    <div>Angular seed app: v<span app-version></span></div>
</div>    

and this is my view1.html

    <div ng-controller="View1Ctrl as view">
<!-- row 1: welcome -->
<div class="row">
    <div class="col-md-12 pull-left">
        <image ng-src="{{ view.users[0].avatar }}"/>
        <!-- If I put the button and input here it will work -->
        <input ng-model="userNameLogin" type="text" placeholder="username" class="form-control">
        <button ng-click="setActiveUser()" type="submit" class="btn btn-success">Sign in</button>
        {{ activeUser }}
    </div> 
</div>
<!-- row 2: main content -->
<!-- left the rest of the content out because it would just clutter the page -->

I tried placing the ng-controller in <div id="pagewrapper" class="container"> instead of the first div of view1.html, but that made no difference.

6
  • 2
    may be you have placed {{ activeUser }} outside of controller div Commented Mar 17, 2015 at 13:02
  • Thanks for the suggestion, pankajparker. I checked and this is not the case. Commented Mar 17, 2015 at 13:09
  • Ben Felda, by "the text stays the same" I mean that it says "Test", even after the button is clicked. Commented Mar 17, 2015 at 13:10
  • Is the console showing you what you'd expect? Commented Mar 17, 2015 at 13:12
  • 1
    I just ran this your code as is and it worked fine, I'll tend to agree with the frist comment and say that {{ activeUser }} isn't within the element where you defined ng-controller="View1Ctrl" Commented Mar 17, 2015 at 13:17

6 Answers 6

3

I think u have misplaced the button or textbox or expression, note : these should be inside the ng-controller. please try this, it will work

<html>

  <head>
    <script data-require="angular.js@*" data-semver="1.4.0-beta.6" src="https://code.angularjs.org/1.4.0-beta.6/angular.js"></script>
    <link rel="stylesheet" href="style.css" />
    <script src="script.js"></script>
  </head>

  <body ng-app="app">
    <div ng-controller="View1Ctrl">
      <input ng-model="userNameLogin" type="text" placeholder="username" class="form-control">
      <button ng-click="setActiveUser()" type="submit" class="btn btn-success">Sign in</button>
      {{activeUser}}
    </div>
    <h1>Hello Plunker!</h1>
  </body>

</html>

script.js code

var app = angular.module("app",[]);


app.controller('View1Ctrl', ['$scope', function($scope) {
    $scope.userNameLogin = "";
    $scope.activeUser = "Test";

    $scope.setActiveUser = function() {
        $scope.activeUser = $scope.userNameLogin;
        console.log($scope.activeUser);
    };
}]);

refer http://plnkr.co/edit/ixbByBQ9nGm4XEqEFi4t?p=preview

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

Comments

0

You have the properties directly on $scope and that is breaking the binding. Instead try:

app.controller('View1Ctrl', ['$scope', function($scope) {
    $scope.userInfo = {
        userNameLogin: "",
        activeUser:"Test"
    }
    $scope.setActiveUser = function() {
        $scope.uesrInfo.activeUser = $scope.userInfo.userNameLogin;
        console.log($scope.activeUser);
    };
}]);

and in your view: {{userInfo.activeUser}}

From Egghead.io https://egghead.io/lessons/angularjs-the-dot

Comments

0

Within your code I can't see anything causing the problem. I made a fiddle, that shows that your code works:

http://jsfiddle.net/xxvsn8xs/

You need to declare the ng-appand the ng-controller of course, like in the fiddle, to let the app work at all.

Also, an view update might not occur, if setting the activeUser actually occurs outside of the angular scope, which might be within an external library or whatever. It is true, that these could be achieved by calling $scope.$apply() directly, but it is nor recommended, as the digest might already be in progress. This is the case in your code, as why you get the according error message.

Instead use angulars $timeout service with a callback and 0 delay, that applies the value to $scope.activeUser. $timeout will check, if a digest cycle is in progress and if not, will start one.

$scope.setActiveUser = function() {
  $timeout(function () {
    $scope.activeUser = $scope.userNameLogin;
    console.log($scope.activeUser);
  });
};

Don't forget to define $timeout in your controllers dependencies:

 app.controller('View1Ctrl', ['$scope', '$timeout', function($scope, $timeout) {

Comments

0

Angular watches the variable you bind to $scope, but if you replace that variable Angular is not able to detect it. That's why $apply would be a suggestion.

Another suggestion is to bind the variable to a 'model' variable:

app.controller('View1Ctrl', ['$scope', function($scope) {
    $scope.userNameLogin = "";
    $scope.myData = { activeUser: "Test" };

    $scope.setActiveUser = function() {
        // Angular will pick up the change in the myData object, and will update all variables attached to it
        $scope.myData.activeUser = $scope.userNameLogin; 
        console.log($scope.myData.activeUser);
    };
}]);

view:

{{ myData.activeUser }}

Comments

0

Do you execute your application in Apache ? I'd the same issue when I was using file:// And I fixed my issue by using a localhost.

Comments

0

I put my navbar (containing the input and button) in a partial and made a new directive for it. Instead of placing the navbar in the index.html I put it in the individual partials and now it works fine. I suspect the problem had something to do with different scopes.

navbar html:

        <a class="navbar-brand" href="#/view1">
            Kwetter
            <image id="navbar-image" src="src/kwetter_logo.png"/>                    
        </a>
    </div>
    <div class="navbar-collapse collapse" >
        <ul class="nav navbar-nav">
            <li><a href="#/view1">Home</a></li>
            <li><a href="#/view2">Profile</a></li>
        </ul>
        <form class="navbar-form navbar-right">
            <div class="form-group">
                <input ng-model="userNameLogin" type="text" placeholder="username" class="form-control">
            </div>
            <div class="form-group">
                <input type="password" placeholder="password" class="form-control">
            </div>
            <button ng-click="setActiveUser()" type="submit" class="btn btn-success">Sign in</button>
        </form>
    </div>
</div>

the directive:

    app.directive('navbar', function() {
return {
    restrict: 'E',
    templateUrl: 'partials/navbar.html',
    controller: 'View1Ctrl as view'
}

});

Then I just added <navbar></navbar> to every view where I want a navbar. Thanks everyone, your help pushed me in the right direction.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.