Search code examples
javascriptangularjsngroute

AngularJS array not updating when using ng-view


I am learning how to use ngRoute to split my html forms into separate views. When I add data to the main array in the index.html the array updates correctly, but when I try the same approach in the html forms that are added in through the ng-view, the array does not render correctly. I can debug and see that the array is getting the new name added, but it will not render on the html.

Index.html

<h1> Names </h1>

<ul ng-repeat="name in names">
    <li>{{name.fname}}</li>
</ul>

<h1>Add name in index.html</h1>
<input type="text" ng-model="name" />
<button ng-click="addName(name)">add name</button>

<ul>
    <li><a href="#/first"> First</a></li>
    <li><a href="#/second"> Second</a></li>
</ul>

<div class="container">
    <div ng-view></div>
</div>

Apps.js

var myApp = angular.module('myApp', ['ngRoute']);

myApp.config(function ($routeProvider) {
$routeProvider
.when('/first', {
    templateUrl: 'pages/first.html',
    controller: 'mainController'
})

.when('/second', {
    templateUrl: 'pages/second.html',
    controller: 'mainController'
})

});

myApp.controller('mainController', ['$scope', '$log', function($scope, $log) {
$scope.names = [{fname:'john',lname:'doe'},{fname:'jane',lname:'doe'}];

 $scope.addName = function(name){
    $scope.names.push({fname:name,lname:'no last name'});     
}
}]);

first and second.html are identical

<h1>Add name in first.html</h1>
<input type="text" ng-model="name" />
<button ng-click="addName(name)">add name</button>

enter image description here


Solution

  • This is by design.

    The $scope is limited to the scope of the controller, which is everything that is rendered inside the ng-view. This means there are two collections named names, one on the app scope, and one on the controller scope. When you modify the names collection inside the controller, it only modifies this collection, not the one referenced in the root level of the app. (I am assuming that you bind mainController to the body tag, otherwise the addName() in index.html wouldn't work. This by itself is not a great choice, you should not put another controller instance into itself, unless you absolutely know what you are doing.)

    The proper way to handle this situation is to put the names collection and the addName() function into a service that you inject into your controllers.