Updating scope in ng-repeat in Angular

I have an Angular app with several nested controllers and views. I implemented infinite scrolling in it closely based on this tutorial for ngInfiniteScrolling: http://binarymuse.github.io/ngInfiniteScroll/demo_async.html

So I have a service that loads items into an array at $scope.content.items. Then there's an ng-repeat element that shows each result.

$scope.content = new Content()
$scope.content.loadMore( $scope.currentStream, 2 ) // this part is actually called in the HTML, but while debugging I've just done it in the controller

Now I want to implement search, and instead of making another search page, just have the items load in place of the current list of items. Basically to take the place of $scope.content.items.

So I built an identical controller, but now calling my search API. I use ng-change to see if someone has typed in the search box, then within the function that calls, do

$scope.search = function() {
    $scope.content = new Search()
    $scope.content.load( $scope.query )
}

I can see that this works in the console, that it replaces $scope.content.items, by doing this in the browser console:

var scope = angular.element($('[ng-controller=HomeController]')).scope()
scope.content.items

That shows me the array of objects I expect in each case (either before triggering ng-change="search()" or after). But the page itself does not update. It just shows the stuff from the Content() service.

Likewise, if I replace the above two lines from my controller with these below, it shows the content from the Search() service:

$scope.content = new Search()
$scope.content.load( 'thom' )

Long story short, I feel like the services and API work, but the page is not updating when I change the $scope.content.items array used by ng-repeat.


Here is the HTML

<div class="panel panel-item" ng-repeat="item in content.items" ng-hide="hideItem">
    <h2 ng-hide=" item.stream == 'read' " data-ng-bind="item.title"></h2>

    <a ng-click="openReaderModal( item )" class="cursor-pointer" ng-show=" item.stream == 'read' ">
        <h2 data-ng-bind="item.title"></h2>
    </a>

    // ...

    <div class="clearfix"></div>
</div>

Fixed it, somehow. Here is my routes from app.config() before:

$stateProvider
    // ...
    .state( 'app', {
        url: '/app',
        templateUrl: 'app/views/app.html',
        controller: 'HomeController'
    })
    .state( 'app.home', {
        url: '/main',
        templateUrl: 'app/views/home.html',
        controller: 'HomeController'
    })
    .state( 'app.profile', {
        url: '/profile',
        templateUrl: 'app/views/profile.html',
        controller: 'ProfileController'
    })
    .state( 'app.read', {
        url: '/read',
        templateUrl: 'app/views/stream-content.html',
        controller: 'HomeController'
    })
    .state( 'app.watch', {
        url: '/watch',
        templateUrl: 'app/views/stream-content.html',
        controller: 'HomeController'
    })
    .state( 'app.listen', {
        url: '/listen',
        templateUrl: 'app/views/stream-content.html',
        controller: 'HomeController'
    })

And here's after:

$stateProvider
    // ...
    .state( 'app', {
        url: '/app',
        templateUrl: 'app/views/app.html',
        controller: 'HomeController'
    })
    .state( 'app.home', {
        url: '/main',
        templateUrl: 'app/views/home.html'
    })
    .state( 'app.profile', {
        url: '/profile',
        templateUrl: 'app/views/profile.html',
        controller: 'ProfileController'
    })
    .state( 'app.read', {
        url: '/read',
        templateUrl: 'app/views/stream-content.html'
    })
    .state( 'app.watch', {
        url: '/watch',
        templateUrl: 'app/views/stream-content.html'
    })
    .state( 'app.listen', {
        url: '/listen',
        templateUrl: 'app/views/stream-content.html'
    })

And it works. If anyone can provide an explanation, I'll credit them the answer.

The routing in angular works like this.

When we provide a controller for the $stateProvider its actually considered as a new constructor (new keyword as in java) thus the data is re-initiated to defaults. The new constructor will be the child to itself, to access the parent controller one can use the $parent