0

AngularJS ng-repeat not changing when array changes

I have a controller:

  <section data-ng-controller="FilmController">
    <article data-ng-view></article>
  </section>

This is its controller:

.controller('FilmController',
      [
        '$scope',
        'dataService',
        '$routeParams',
        function ($scope, dataService, $routeParams) {
          var getFilms = function(searchterm, category, page){
            dataService.getFilms(searchterm, category, page).then(
              function(response){
                $scope.films = [];
                $scope.films = response.data;
                let pageLinks = [];
                for (let i = 0; i < response.data[10][0]; i += 10) {
                  pageLinks.push({
                    pageLink: "/wai/wai-assignment/#/films?searchterm=" + searchterm + "&category=" + category + "&page=" + i/10,
                    pageNum: i/10
                  })
                }
                $scope.pageLinks = pageLinks;
                console.log(pageLinks);
              },
              function(err){
                $scope.status = 'Unable to load data' + err;
              },
              function(notify){
                console.log(notify);
              }
            );
          }

          if ($routeParams && ($routeParams.searchterm || $routeParams.category)){
            getFilms($routeParams.searchterm, $routeParams.category, $routeParams.page);
          } else {
            getFilms('','',$routeParams.page);
          }
        }
      ]);

These are the routes:

app.config(
        [
            '$routeProvider',

            function ($routeProvider) {
                $routeProvider
                    .when('/films', {
                        templateUrl: 'js/partials/films.html',
                        controller: 'FilmController'
                    })
                    .otherwise({
                        redirectTo: '/'
                    });
            }
        ]
    );

Here is the template:

<section>
  <table>
    <tr data-ng-repeat="film in films">
      <td>{{film.title}}</td>
      <td>{{film.name}}</td>
      <td>{{film.description}}</td>
    </tr>
  </table>
  <a data-ng-repeat="pageLink in pageLinks" ng-href="{{pageLink.pageLink}}">
    {{pageLink.pageNum}}
  </a>
</section>

When i access films?searchterm=example&category=example&page=1

It shows films with the category and search criteria from a database. When i click a link to go to a different page, it just grabs data from an SQL statement with a different OFFSET, but the ng-repeat doesn't update with it.

I know why this happens, something to do with scopes, but i can't work out how to fix it. Can anyone help?

EDIT:

angular.module('filmDirectoryApp')
    .service('dataService',
        [
          '$q',
          '$http',
          function ($q, $http) {
            var urlBase = 'server/';
            var defer = $q.defer();
            this.getFilms = function (searchterm, category, page) {
              $http.get(urlBase + 'getfilms.php?searchterm=' + searchterm + '&category=' + category + '&page=' + page)
                .success(function (response) {
                  console.log(response);
                  defer.resolve({
                      data: response
                  });
                })
                .error(function (err) {
                    defer.reject(err);
                });
                return defer.promise;
            }
          }
        ]
      );
Community
  • 1
  • 1
Adam Cole
  • 173
  • 1
  • 3
  • 13
  • @dota2pro `ng-repeat='film in films'` is the `ng-repeat` in question and it is version 1.5.6 – Adam Cole May 09 '19 at 16:13
  • @dota2pro It is saying that it is changed but it isn't changing. I think the database request isn't working correctly. I'll see if i can get that fixed. – Adam Cole May 09 '19 at 16:25
  • @dota2pro No that section is just to load the page links. It's not related i don't think. – Adam Cole May 09 '19 at 16:32
  • So if i `console.log(response)` in the dataService, it returns the correct data. If i return the data that has supposedly been sent to the controller from that dataService then it logs the wrong data. – Adam Cole May 09 '19 at 16:45
  • Please check if you get correct $scope.films value thanks – dota2pro May 09 '19 at 16:59
  • We need to see the code for the `dataService`. Two possibilities: it uses a [deferred anti-pattern](https://stackoverflow.com/questions/30750207/is-this-a-deferred-antipattern) that is coded incorrectly, or it returns ES6 promises or some other type of promise that is not integrated with the AngularJS framework. – georgeawg May 09 '19 at 17:02
  • @georgeawg I forgot to add the dataService earlier. I added it as an edit. – Adam Cole May 09 '19 at 17:21

1 Answers1

0

The code uses a deferred anti-pattern that is written incorrectly. The $q.defer only resolves once. Subsequent calls to defer.resolve are ignored. This is the way promises work.

In addition the .success and .error methods are deprecated and have been removed from the AngularJS framework.

The solution is to avoid the deferred anti-pattern and use the .then and .catch methods.

angular.module('filmDirectoryApp')
.service('dataService',
    [
      '$http',
      function ($http) {
        var urlBase = 'server/';
        this.getFilms = function (searchterm, category, page) {
          var params = {
              "searchterm": searchterm,
              "category"  : category,
              "page"      : page
          };
          var config = { "params": params };    
          return $http.get(urlBase + 'getfilms.php', config)
            .then(function (response) {
              var data = response.data;
              console.log(data);
              return data;
            })
            .catch(function (err) {
              console.log(err)
              throw err;
            });
        }
      }
    ]
);

The $http service deprecated custom callback methods - .success() and .error() - have been removed. You can use the standard .then()/.catch() promise methods instead, but note that the method signatures and return values are different.

The .then method returns a new promise which is resolved or rejected via the return value of the successCallback, errorCallback (unless that value is a promise, in which case it is resolved with the value which is resolved in that promise using promise chaining).

For more information, see

georgeawg
  • 48,608
  • 13
  • 72
  • 95
  • Thanks alot for this. The code you showed is identical to my previous code. How would i write a .then.catch variant of it? – Adam Cole May 09 '19 at 17:40