2

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);
    }
}]);
4
  • 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 Commented Mar 7, 2015 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. Commented Mar 7, 2015 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? Commented Mar 7, 2015 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 Commented Mar 7, 2015 at 14:25

2 Answers 2

2

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

3 Comments

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?
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
Makes sense, thanks for the tip! Will do a cleanup and move into services once I have the basic functionality up and running!
1
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.

4 Comments

after you finish your code there is a few improvements, like move quring serivece to resolve object in routing configuration.
Precisely, a library like UI router would take the promise noise of the controller for example.
Even builded ng-router can clean up „promise noise”
@KrzysztofSafjanowski which is why I suggested a library "like" UI router, rather than UI router itself :-)

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.