-->

ng-repeat not updating the list when adding data

2019-02-27 12:13发布

问题:

my problem is that the ng-repeat is not updating automatically the data. When I press add pin in my code, the element is added correctly to the database. If I reload the page the data appear correctly, but not as angular should. For the record, the Update and delete are working correctly.

Thanks in advance

This is my app.js code:

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

app.controller("AppCtrl", function ($http) {
var app = this;

$http.get("/api/pin").success(function (data) {
    app.pins = data.objects;
})

app.addPin = function (scope) {
    $http.post("/api/pin", {"title":"new", "image":"http://placekitten.com/200/200/?image=" + app.pins.length})
        .success(function(data) {
            add.pins.push(data);
        })
}

app.deletePin = function (pin) {
    $http.delete("/api/pin/" + pin.id).success(function(response) {
            app.pins.splice(app.pins.indexOf(pin), 1)
        })
}

app.updatePin = function (pin) {
    $http.put("/api/pin/" + pin.id, pin);
}

})

This is my index.html file:

<html>
<head>
<title>Pin Clone</title>
<script src="angular/angular.js"></script>
<script src="angular/angular-resource.js"></script>
<script src="js/app.js"></script>
</head>
<body ng-app="app" ng-controller="AppCtrl as app">

<button ng-click="app.addPin()">Add Pin</button>
<div ng-repeat="pin in app.pins">
<img ng-src="{{ pin.image }}" alt=""/>
<div class="ui">
    <input type="text" ng-model="pin.title"/>
    <button ng-click="app.updatePin(pin)">Update</button>
    <button ng-click="app.deletePin(pin)">Delete</button>
</div>
</div>


</body>
</html>

回答1:

First of all, you should really use $scope (Doc) in your controller. You can read more about the differences in this post.

Thus your controller would look like this.

app.controller("AppCtrl", ["$scope", "$http",
                           function ($scope, $http) {

    $http.get("/api/pin").success(function (data) {
        $scope.pins = data.objects;
    });

    $scope.addPin = function () {
        ....
    };

    $scope.deletePin = function (pin) {
        ....
    };

    $scope.updatePin = function (pin) {
        ....
    };
}]);

HTML:

<body ng-app="app" ng-controller="AppCtrl">

    <button ng-click="addPin()">Add Pin</button>
    <div ng-repeat="pin in pins">
        <img ng-src="{{ pin.image }}" alt=""/>
        <div class="ui">
            <input type="text" ng-model="pin.title"/>
            <button ng-click="updatePin(pin)">Update</button>
            <button ng-click="deletePin(pin)">Delete</button>
        </div>
    </div>

</body>

Finally, here comes the core part. You should call $apply (Doc) when your models change. You can read more in this blog post.

$http
    .post("/api/pin", {
        title: "new",
        image:
            "http://placekitten.com/200/200/?image="
                + $scope.pins.length
    })
    .success(function(data) {
        $scope.$apply(function() {
            $scope.pins.push(data);
        });
    });

Thus, the full controller code:

app.controller("AppCtrl", ["$scope", "$http",
                           function ($scope, $http) {

    $http.get("/api/pin").success(function (data) {
        $scope.pins = data.objects;
    });

    $scope.addPin = function () {
        $http
            .post("/api/pin", {
                title: "new",
                image:
                    "http://placekitten.com/200/200/?image="
                        + $scope.pins.length
            })
            .success(function(data) {
                $scope.$apply(function() {
                    $scope.pins.push(data);
                });
            });
    };

    $scope.deletePin = function (pin) {
        $http
            .delete("/api/pin/" + pin.id)
            .success(function(response) {
                $scope.$apply(function() {
                    $scope.pins.splice(
                        $scope.pins.indexOf(pin), 1
                    );
                });
            });
    };

    $scope.updatePin = function (pin) {
        $http.put("/api/pin/" + pin.id, pin);
    };
}]);


回答2:

Cannot agree with Gavin. First, what you're doing is totally fine. Creating instance of controller is a much better practice than using $scope. Second, $apply() is not needed here.

The problem is ng-repeat created a new scope. While pin is updated, app.pins is not. You should do

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

app.controller("AppCtrl", function ($http) {
var app = this;

$http.get("/api/pin").success(function (data) {
    app.pins = data.objects;
})

app.addPin = function (scope) {
    $http.post("/api/pin", {"title":"new", "image":"http://placekitten.com/200/200/?image=" + app.pins.length})
        .success(function(data) {
            add.pins.push(data);
        })
}

app.deletePin = function (index) {
    $http.delete("/api/pin/" + app.pins[index].id).success(function(response) {
            app.pins.splice(index, 1)
        })
}

app.updatePin = function (index) {
    $http.put("/api/pin/" + app.pins[index].id, app.pins[index]);
}

})

and

<html>
<head>
<title>Pin Clone</title>
<script src="angular/angular.js"></script>
<script src="angular/angular-resource.js"></script>
<script src="js/app.js"></script>
</head>
<body ng-app="app" ng-controller="AppCtrl as app">

<button ng-click="app.addPin()">Add Pin</button>
<div ng-repeat="pin in app.pins track by $index">
<img ng-src="{{ pin.image }}" alt=""/>
<div class="ui">
    <input type="text" ng-model="pin.title"/>
    <button ng-click="app.updatePin($index)">Update</button>
    <button ng-click="app.deletePin($index)">Delete</button>
</div>
</div>


</body>
</html>

check here: How to update ng-model on event click using $event in Angularjs



回答3:

in posted code you've got typo error

app.addPin = function (scope) {
    $http.post("/api/pin", {"title":"new", "image":"http://placekitten.com/200/200/?image=" + app.pins.length})
        .success(function(data) {
           // add.pins.push(data); <--- app not add 
              app.pins.push(data)
        })
}