2

I'm learning Angular1 from Adam Freeman's ,,Pro AngularJS" book. I've got a problem with building a DeployD app he's describing in chapters 6-8 - it seems like my code doesn't want to read JSON

That's my HTML:

<!DOCTYPE html>
<html ng-app="sportsStore" lang="pl">
<head>
    <title>SportsStore</title>
    <script src="components/angular.js"></script>
    <script src="components/angular-resource.js"></script>
    <link href="components/bootstrap.css" rel="stylesheet" />
    <link href="components/bootstrap-theme.css" rel="stylesheet" />
    <script>
        angular.module("sportsStore", ["customFilters"]);
    </script>
    <script src="controllers/sportsStore.js"></script>
    <script src="filters/customFilters.js"></script>
    <script src="controllers/productListControllers.js"></script>
</head>
<body ng-controller="sportsStoreCtrl">
<div class="navbar navbar-inverse">
    <a class="navbar-brand" href="#">SKLEP SPORTOWY</a>
</div>
<div class="panel panel-default row" ng-controller="productListCtrl">
    <div class="alert alert-danger" ng-show="data.error">
        Błąd ({{data.error.status}}). Dane produktu nie zostały wczytane.
        <a href="/index.html" class="alert-link">Kliknij tutaj, aby spróbować ponownie</a>
    </div>
    <div class="panel panel-default row" ng-controller="productListCtrl"
         ng-hide="data.error">
    <div class="col-xs-3">
        <a ng-click="selectCategory()"
           class="btn btn-block btn-default btn-lg">Strona główna</a>
        <a ng-repeat="item in data.products | orderBy:'category' |
unique:'category'" ng-click="selectCategory(item)" class=" btn btn-block
btn-default btn-lg" ng-class="getCategoryClass(item)">
            {{item}}
        </a>
    </div>
    <div class="col-xs-8">
        <div class="well"
             ng-repeat="item in data.products | filter:categoryFilterFn |
range:selectedPage:pageSize">
            <h3>
                <strong>{{item.name}}</strong>
                <span class="pull-right label label-primary">
{{item.price | currency}}
</span>
            </h3>
            <span class="lead">{{item.description}}</span>
        </div>
        <div class="pull-right btn-group">
            <a ng-repeat="page in data.products | filter:categoryFilterFn |
                    pageCount:pageSize" ng-click="selectPage($index + 1)" class="btn
btn-default" ng-class="getPageClass($index + 1)">
                {{$index + 1}}
            </a>
        </div>
    </div>
</div>
</body>
</html>

and the sportStore.js controller

angular.module("sportsStore")
    .constant("dataUrl", "http://localhost:5500/products")
    .controller("sportsStoreCtrl", function ($scope, $http, dataUrl) {
        $scope.data = {};
        $http.get(dataUrl)
            .then(function (data) {
                $scope.data.products = data;
            },
            function (error) {
                $scope.data.error = error;
            });
    });

I'm using DeployD to build an API, and the problem is that when I try to run my app, the error shows up in console:

Error: [filter:notarray] Expected array but received: {"data":[{"name":"Kajak","description":"�?ódka przeznaczona dla jednej osoby","category":"Sporty Wodne","price":275,"id":"d9b9e4fcb9df3853"},{"name":"Kamizelka ratunkowa","description":"Chroni i dodaje uroku","category":"Sporty wodne","price":49.75,"id":"3c1cceedb44ddb84"},{"name":"Piłka","description":"Zatwierdzona przez FIFA rozmiar i waga","category":"Piłka Nożna","price":19.5,"id":"447a2079a8488932"},{"name":"Flagi narożne","description":"Nadadzą Twojemu boisku profesjonalny wygląd","category":"Piłka Nożna","price":34.95,"id":"2b2dd597f18bb8a7"},{"name":"Stadion","description":"Składany stadion na 35000 osób","category":"Piłka Nożna","price":79500,"id":"2cfe0f6767240bf9"},{"name":"Czapka","description":"Zwiększa efektywność mózgu o 75%","category":"Szachy","price":16,"id":"dfc137db43574b4a"},{"name":"Niestabilne krzesło","description":"Zmniejsza szansę przeciwnika","category":"Szachy","price":29,"id":"e2b644c5091d28ca"},{"name":"Ludzka szachownica","description":"Przyjemna gra dla całej rodziny","category":"Szachy","price":75,"id":"f945806bb011895d"},{"name":"Błyszczący król","description":"Pokryty złotem i wysadzany diamentami król","category":"Szachy","price":1200,"id":"fab242704bb38b64"}],"status":200,"config":{"method":"GET","transformRequest":[null],"transformResponse":[null],"jsonpCallbackParam":"callback","url":"http://localhost:5500/products","headers":{"Accept":"application/json, text/plain, /"}},"statusText":"OK"} http://errors.angularjs.org/1.6.0-rc.1/filter/notarray?p0=%7B%22data%22%3A%…son%2C%20text%2Fplain%2C%20*%2F*%22%7D%7D%2C%22statusText%22%3A%22OK%22%7D at angular.js:68 at angular.js:20392 at fn (eval at compile (angular.js:15095), :4:388) at regularInterceptedExpression (angular.js:16203) at Scope.$digest (angular.js:17732) at Scope.$apply (angular.js:18006) at done (angular.js:12150) at completeRequest (angular.js:12376) at XMLHttpRequest.requestLoaded (angular.js:12304)

I tried to skim through similar errors on SO but none of the solutions seemed to work for me. Did someone have a similar problem?

1
  • The response object in then() of $http is not the data itself...it has a property data that is what you need Commented Dec 24, 2016 at 17:29

4 Answers 4

1

ng repeat works with an arrays but as per the response getting from the API in then() method is not the data itself but it is having a property named as data which is the actual array that you have to pass in ng-repeat.

So, instead of using $scope.data.products = data use $scope.data.products = data.data

----------OR----------

.then(function (response) {
  $scope.data.products = response.data;
}
        
Sign up to request clarification or add additional context in comments.

Comments

1

The error message shows the filter refusing to process the response object instead of the data array. Expected array but received: {data:[..., headers: ...

The .then method of the $http service returns a response object, not data.

angular.module("sportsStore")
    .constant("dataUrl", "http://localhost:5500/products")
    .controller("sportsStoreCtrl", function ($scope, $http, dataUrl) {
        $scope.data = {};
        $http.get(dataUrl)
            //.then(function (data) {
            //    $scope.data.products = data;
            .then(function (response) {
                $scope.data.products = response.data;
            },
            function (error) {
                $scope.data.error = error;
            });
    });

Data is only one property of the response object:

$http(...).
  then(function onSuccess(response) {
    // Handle success
    var data = response.data;
    var status = response.status;
    var statusText = response.statusText;
    var headers = response.headers;
    var config = response.config;
    ...
  }, function onError(response) {
    // Handle error
    var data = response.data;
    var status = response.status;
    var statusText = response.statusText;
    var headers = response.headers;
    var config = response.config;
    ...
  });

Comments

0

ng repeat and filter works with array, you need to access the data

 angular.module("sportsStore")
    .constant("dataUrl", "http://localhost:5500/products")
    .controller("sportsStoreCtrl", function ($scope, $http, dataUrl) {
        $scope.data = {};
        $http.get(dataUrl)
            .then(function (data) {
                $scope.data.products = data.data;
            },
            function (error) {
                $scope.data.error = error;
            });
    });

Comments

0

Angular expects the data variable to be type of array.

$scope.data =  [];

Then try following code:

$http.get('dataUrl')
    .success(function(data) {
        $scope.data = data;
    }).error(function(data, status) {
        $log.error('Error ' + status + ' unable to get data from server.');
});

Also remember to add to your controller the $log to properly display bugs in console:

.controller('sportsStoreCtrl', ['$scope', '$http', '$log', function ($scope, $http, $log)

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.