Kyle
Kyle

Reputation: 1183

AngularJS update view after delete operation

I have an AngularJS and Rails app that performs RESTful operations: create, read, destroy.

I have to refresh the page after performing a 'delete' operation, and am trying to figure out how to update the view asynchronously.

The 'create' operation updates the words in the view by using the .success http function; I've tried to do a similar approch with delete but am getting an error: Cannot read property 'success' of undefined

app.js

//= require angular-rails-templates
//= require_tree .


angular.module('d-angular', ['ui.router', 'templates'])

// Set routing/configuration
// ------------------------------
.config(['$stateProvider', '$urlRouterProvider',

    // Set state providers
    function($stateProvider, $urlRouterProvider) {$stateProvider

        // Home state
        .state('home', {
          url: '/home',
          templateUrl: 'home.html',
          controller: 'MainCtrl',
          resolve: {
              listPromise: ['lists', function(lists){
                return lists.getAll();
              }]
          }
        })

        $urlRouterProvider.otherwise('home');
    }
])


// lists factory
// Factories are used to organize and share code across the app.
// ------------------------------
.factory('lists', ['$http',

    function($http){
        // create new obect with array of lists
        var o = { lists: [] };

        // get all lists
        o.getAll = function() {
            return $http.get('/lists.json').success(function(data){
                angular.copy(data, o.lists);
            });
        };

        // get specific list
        o.get = function(id) {
          return $http.get('/lists/' + id + '.json').then(function(res){
            return res.data;
          });
        };

        // create list
        o.create = function(post) {
          return $http.post('/lists.json', post).success(function(data){
            o.lists.push(data);
          });
        };

        // delete list
        o.delete = function(id) {
            $http.delete('/lists/' + id + '.json');
        }

        // add word to list
        o.addWord = function(id, word) {
          return $http.post('/lists/' + id + '/words.json', word);
        };

        o.deleteWord = function(id, word) {
            $http.delete('/lists/' + id + '/words/' + word + '.json');
        }

        return o;

    }
])


// Main controller
// ------------------------------
.controller('MainCtrl', ['$scope', '$stateParams', 'lists', '$http',

    // Main scope (used in views)
    function($scope, $stateParams, lists, $http) {

        // array of lists
        $scope.lists = lists.lists;

        $scope.list = lists.lists[$stateParams.id];


        // Add list function
        // Creates a new list
        $scope.addList = function(){
            // prevent empty titles
            if(!$scope.title || $scope.title === '') { 
                return;
            }

            lists.create({
                title: $scope.title,
                date: new Date().toJSON().slice(0,10),
            });

            // reset title
            $scope.title = '';
        };

        $scope.deleteList = function() {
            lists.delete($scope.list.id).then(function(){
                $scope.lists.splice(index, 1)
            }); // UPDATE THE VIEW
        };

        // Add word function
        $scope.addWord = function(){

                // push new word to array
                lists.addWord($scope.list.id, {
                    title: $scope.word,
                    date: new Date().toJSON().slice(0,10),
                })
                .success(function(word) {
                    $scope.list.words.push(word);
                });
            });
        };

        $scope.deleteWord = function(word_id) {
            lists.deleteWord($scope.list.id, word_id);
        };


    }

]);

view

<div ng-controller="MainCtrl">

  <!-- add a list -->
  <form ng-submit="addList()">
    <input type="text" ng-model="title" placeholder="Enter list"></input>
    <button type="submit">Add</button>
  </form>
  <!-- end add -->

  <!-- list all lists -->
  <select ng-model="list" ng-options="list as list.title for list in lists">
      <option value="">Select List</option>
  </select>
  <!-- end list -->

  <!-- delete list -->
  <form ng-submit="deleteList()">
    <button type="submit">Delete</button>
  </form>
  <!-- end delete -->

  <hr>

  {{list.id}}

  <!-- add word -->
  <form ng-submit="addWord()">
    <input type="text" ng-model="word"></input>
    <button type="submit">Add</button>
  </form>
  <!-- end add -->

  <!-- list all words in list -->
   <div ng-repeat="word in list.words">
      {{word.title}}
      {{word.id}}

      <!-- delete word -->
      <form ng-submit="deleteWord(word.id)">
        <button type="submit">Delete</button>
      </form>
      <!-- end delete -->

  </div>
  <!-- end words -->

Upvotes: 2

Views: 2825

Answers (2)

lacostenycoder
lacostenycoder

Reputation: 11226

Clarifying my comment

Assuming you have already have a o.getAll function you can simply call that in your success callback

o.deleteWord = function(id, word) {
    return $http.delete('/lists/' + id + '/words/' + word + '.json')
    .success(function(response){ 
        return o.getAll(); 
    }):
}

I would put it in the o.deleteWord function. Also in your rails controller you'll want to respond_with Word.all after destroying your model. Without that, the page wont update because it will be listening for an updated words.json so something like

  def destroy
    Word.delete(params[:id])
    respond_with Word.all
  end

Upvotes: 0

Brent Washburne
Brent Washburne

Reputation: 13158

Is it because you're not returning the value from $http.delete()? Add a return statement to your factory function:

    o.deleteWord = function(id, word) {
        return $http.delete('/lists/' + id + '/words/' + word + '.json');
    }

and then in your controller, you can reference .success():

    $scope.deleteWord = function(word_id) {
        lists.deleteWord($scope.list.id, word_id)
             .success(...);
    };

Upvotes: 2

Related Questions