0

I have an AngularJS Web APP that interacts with a NodeJS API. I need to make some http request to the API (CRUD operations) with a task object.

Right now i'm tryng to make a PUT request to a local Url:

http://localhost:4000/tasks/:id/finish

I have a button in a view that triggers a function (in this case, vm.finish) on the controller, which makes a request to a Service (TaskService.finish(id)).

View

    <md-card ng-repeat="task in vm.unfinishedTasks">
        <md-card-header ui-sref="main.edit({id: task.id})" class="md-title">
            {{ task.title }}
        </md-card-header>
        <md-card-title>
            {{ task.description }}
        </md-card-title>
        <md-card-actions layout="row" layout-align="center">
            <md-button ng-click="vm.delete(task.id)"><md-icon>close</md-icon></md-button>
            <md-button><md-icon>{{task.priorityClass}}</md-icon></md-button>
            <md-button ng-click="vm.finish(task.id)"><md-icon>done</md-icon></md-button>
        </md-card-actions>
    </md-card>

Controller

function TasksListCtrl(TaskService, toastr, $http, $state, $promise) {

        var vm = this;
        ...

        vm.finish = function (id) {
                console.log("Calling the service to finish the task...");
                TaskService.finish(id)
                    .$promise.then(
                        function (response) {
                            toastr.success('Task finished.');
                            $state.reload();
                        },
                        function (err) {
                            toastr.error('There was a problem when trying to finish the task. Please refresh the page before trying again.')
                        }
                    )
        }

Service

function TaskService($resource) {

        //The API runs locally for now. 
        var apiUrl = 'http://localhost:4000/tasks';
        var resource = $resource(apiUrl);;
        return {
            unfinishedTasks: $resource(apiUrl, {}, {
                query: {
                    method: 'GET',
                    params: {
                        finished: false
                    },
                    isArray: true
                }
            }),
            finishedTasks: $resource(apiUrl, {}, {
                query: {
                    method: 'GET',
                    params: {
                        finished: true
                    },
                    isArray: true
                }
            }),
            save: function (taskDto) {
                return resource.save(taskDto);
            },
            finish: function (id) {
                console.log('Finishing the task...')
                return $resource(apiUrl + '/:id/finish', {
                    id: '@id'
                }, {
                    'finish': {
                        method: 'PUT',
                        params: {
                            id: "@id"
                        }
                    }
                });
            },
            delete: function (id) {
                return particularResource.delete();
            }
        }

The console.log messages are shown as expected, but the PUT request is not being made at all. In this case, how do I code the PUT request properly? and what is right way to call the function of the Service?

Here's the console error when i try to call the finish function from the service:

Calling the service to finish the task...
Finishing the task...
angular.js:14525 TypeError: Cannot read property 'then' of undefined
    at TasksListCtrl.vm.finish (TasksListCtrl.js:42)
    at fn (eval at compile (angular.js:15358), <anonymous>:4:274)
    at callback (angular.js:26994)
    at Scope.$eval (angular.js:18161)
    at Scope.$apply (angular.js:18261)
    at HTMLButtonElement.<anonymous> (angular.js:26999)
    at defaultHandlerWrapper (angular.js:3734)
    at HTMLButtonElement.eventHandler (angular.js:3722)
2
  • spare yourself prolonged agony and ditch $resource in favor of $http Commented Apr 4, 2017 at 12:28
  • I made a research before and when interacting with a restful API, $resource was recommended. In your opinion, why do you suggest $http in this case? Commented Apr 4, 2017 at 12:53

3 Answers 3

0

Try use $http

$http.put(url, newTaskObject).then(successFn, errorFn);
Sign up to request clarification or add additional context in comments.

2 Comments

My focus, for now, is use $resource. I can change my mind if you have some good arguments.. heheh. With your solution, the flow control (success or error) will be coded in the Service? I'm doing it in the controller right now.
When you use $http you have more control over the data you get. $http is built in angular, and you don't must included other libraries. And you can write flow control in service.
0

So, I decided to use $http instead of $resource. The solution worked perfectly. My code is now like this.

Controller

vm.delete = function (id) {
         TaskService.delete(id)
             .then(
                 function (response) {
                     toastr.success('Task succesfully deleted.');
                     $state.reload();
                    },
                 function (err) {
                     toastr.error('There was a problem in the deletion. Please refresh the page before trying again.')
                 }
             )
     }

Service

function TaskService($http) {

    //The API runs locally for now. 
    var apiUrl = 'http://localhost:4000/tasks';
    return {
        unfinishedTasks: function () {
            return $http.get(apiUrl, {
                params: {
                    "finished": false
                }
            });

        },
        finishedTasks: function () {
            return $http.get(apiUrl, {
                params: {
                    "finished": true
                }
            });
        },
        save: function (taskDto) {
            return $http.post(apiUrl,taskDto);
        },
        finish: function (id) {
            return $http.put(apiUrl + '/' + id + '/finish', null);
        },
        delete: function (id) {
            return $http.delete(apiUrl + '/' + id);
        }
    }
}

Just one detail: the flow control is implemented in the controller layer, not in the service layer.

Thanks for the suggestions.

Comments

0

We have to call 2 methods with the name 'finish'. First is the service method 'finish' and the other is ng-resource method 'finish'. Call the method finish as below:

TaskService.finish(id).finish(id)
.$promise.then(
    function (response) {
        toastr.success('Task finished.');
        $state.reload();
    },
    function (err) {
        toastr.error('There was a problem when trying to finish the task. Please refresh the page before trying again.')
    });

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.