2

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 -->

2 Answers 2

2

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(...);
    };
Sign up to request clarification or add additional context in comments.

1 Comment

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

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

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.