Sign up ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free.

I have a simple to-do app I'm working on, which is using Angular and then PHP/MySQL for the backend.

I now have a simple app that works, where I can add new todos, and add the "percentage completed" per day to the Database, using a simple $http post.

However now what I'm looking to do is, populate the $scope.historicalDailyPercentages array, with data from the database.

At the start of the script, I init the object like so:

$scope.historicalDailyPercentages = []; //TODO, this should be initialised with data from the database.

I understand I'll need to have some sort of $http get loop in there, to check for the data and fill the object, but I'm a little unclear on how to get started there.

The entire goalzy.js script is below for reference. Thanks in advance!

angular.module('goalzy', [])

.config(['$httpProvider', function($httpProvider) {
    $httpProvider.defaults.headers.post['Content-Type'] = 'application/json; charset=utf-8';
}])

.controller('TodoController', ['$scope', '$http', function($scope, $http) {

    $scope.todos = [];
    $scope.historicalDailyPercentages = []; //TODO, this should be initialised with data from the database.

    $scope.addTodo = function() {
        if ($scope.todoText != "") {
            if ($scope.todos.length < 3) {
                $scope.todos.push({
                    text: $scope.todoText,
                    done: false
                });
                $scope.todoText = '';
                //Save to DB
            } else {
                alert("You can only have 3 todos per day!");
                $scope.todoText = '';
            }
        } else {
            alert("you must write something");
        }
    };

    $scope.remaining = function() {
        var count = 0;
        angular.forEach($scope.todos, function(todo) {
            count += todo.done ? 0 : 1;
        });
        return count;
    };

    $scope.percentComplete = function() {
        var countCompleted = 0;
        angular.forEach($scope.todos, function(todo) {
            countCompleted += todo.done ? 1 : 0; //Simply calculates how many tasks have been completed
            console.log(countCompleted);
        });
        var totalCount = $scope.todos.length;
        var percentComplete = countCompleted / totalCount * 100;
        return percentComplete;
    }

    $scope.finaliseDay = function(percentComplete) {
        alert("You're finalising this day with a percentage of: " + percentComplete);
        var today = new Date();
        var alreadyPresent = $scope.historicalDailyPercentages.some(function(item) {
            return item.date.getFullYear() === today.getFullYear() &&
                item.date.getMonth() === today.getMonth() &&
                item.date.getDate() === today.getDate();
        });

        //Confirm that nothing has alreayd been posted for today
        if (!alreadyPresent) {

            // Simple POST request example (passing data)
            $http.post('/postDailyPercentage.php', {
                user_id: 1,
                percent: percentComplete,
                date: today
            }).
            success(function(data, status, headers, config) {
                // this callback will be called asynchronously
                // when the response is available
                if (data) {

                    $scope.historicalDailyPercentages.push({
                        user_id: 1,
                        percent: percentComplete,
                        date: today
                    });

                } else {
                    alert("Something went wrong" + data);
                }

            }).
            error(function(data, status, headers, config) {
                // called asynchronously if an error occurs
                // or server returns response with an error status.
                console.log("Post failure");
            });
        } else {
            alert("You're all set for today - see you tomorrow!");
        }

        //console.log($scope.historicalDailyPercentages);
    }
}]);
share|improve this question
    
As you are using $http.post to update database you must to use $http.get to retrive some data from database. According to have postDailyPercentage.php you have to create similiar file and support calculation – Krzysztof Safjanowski Mar 7 at 14:18
    
"As you are using $http.post to update database you must to use $http.get to retrive some data" Not true, POST requests can return data too; OP could easily read the response from her $http.post call rather than using another request. – A Red Herring Mar 7 at 14:22
    
„Not true, POST requests can return data too.” doen't mean that it should be used to retrive data – @DanPantry – what is not true? – Krzysztof Safjanowski Mar 7 at 14:24
    
@KrzysztofSafjanowski well if you are getting data right after using a $http.post why not circumvent another request and just combine it into one EDIT: I misunderstood, sorry – A Red Herring Mar 7 at 14:25

2 Answers 2

up vote 1 down vote accepted

To populate that object with an $http.get you can do it as follows:

function getHistoricalDataSuccess(data) {
  $scope.historicalDailyPercentages = data;
}

function getHistoricalDataError(error) {
  //handle the error
}

$http.get('path/to/api')
.success(getHistoricalDataSuccess)
.error(getHistoricalDataError);
share|improve this answer
    
Exactly what I was trying to get at, thanks! Quick question though, from a clean code perspective, where is the best place to have the functions - just after I initialise the array or? – user2656127 Mar 7 at 14:24
    
I usualy put them at the beginning of the controller. As long as they are declared before you reference them it should be fine. A quick tip, i see you have alot of logic in your controller. You should read about Angular Services. Try to keep in mind that a controller is to glue data to the scope, and services is the place where you want your logic. As explained in the answer by Dan Pantry – RVandersteen Mar 7 at 14:34
    
Makes sense, thanks for the tip! Will do a cleanup and move into services once I have the basic functionality up and running! – user2656127 Mar 7 at 14:36
var TodoController = function($scope, HistoricalDailyPercentageService) {
  HistoricalDailyPercentageService.get().then(function(percentages) {
    $scope.historicalDailyPercentages = percentages;
  }, function(error) {
    alert(error);
  });
};

var HistoricalDailyPercentageService = function($http) {
  this.get = function() {
    return $http.get('yourUrl')
      .then(function(xhr) {
        var data = xhr.data;
        // Transform the data as you see fit
        return data;
      }, function(xhr) {
        // xhr contains the error message - modify this as you see fit.
        return xhr.code;
      });
  };
};

angular.module('goalzy')
  .controller('TodoController', ['$scope', 'HistoricalDailyPercentages', TodoController])
  .service('HistoricalDailyPercentageService', ['$http', HistoricalDailyPercentageService]);

I would recommend doing it this way; this will make it easier to test by taking the logic of getting the data out of your already busy controller. @RVandersteen's example will only work inside of your controller, which is fine, but it really does make your controller very busy; controllers should really only assign things to a scope, everything else should be handled in a directive (for example, binding events to methods) or a service/factory/provider (for business logic).

After you have finished up your code, could you post on CodeReview? There's a few improvements I could suggest but they are merely review-based things and not appropriate for the scope of this question.

It's worth noting by the way that because I am using then in the controller I must use then in the service, too. If I use success in the service then my changes will not be reflected when I call then in the controller.

share|improve this answer
    
after you finish your code there is a few improvements, like move quring serivece to resolve object in routing configuration. – Krzysztof Safjanowski Mar 7 at 14:26
    
Precisely, a library like UI router would take the promise noise of the controller for example. – A Red Herring Mar 7 at 14:27
    
Even builded ng-router can clean up „promise noise” – Krzysztof Safjanowski Mar 7 at 14:29
    
Thanks for the comment, will try both! – user2656127 Mar 7 at 14:29
    
@KrzysztofSafjanowski which is why I suggested a library "like" UI router, rather than UI router itself :-) – A Red Herring Mar 7 at 14:30

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.