How to work with JSON and promises data received through $ http.get?

I don't think angular $ http.get works correctly, so maybe you can help me change the settings. I am working on a wizard in which each step is a separate html file, and the sequence of steps is in the JSON file. What I want to do is read in the JSON file, and then:

  • Create a list of steps as a guide.
  • Display step contents with ng-include.
  • Create buttons that point to the previous and next steps.

From what I read in Service vs. Provider vs. Factory , AngularJS: factory $ http. get the json file and similar topics, i can create a service or factory to read in json. This creates a promise object, which is then passed along a line that needs to be filled whenever data arrives. This works when inserting data into a model that is tied to a view. If I need data to calculate things like the buttons for the next step, all I have is a promise object - I can’t create links to the previous and next steps and set their status yet. Is there a way to make angular wait until the data arrives before continuing with the code? Is this the right way to think about this?

Here is the plunker and some code snippets:

JSON:

[{
    "name"  : "Step 1",
    "id"    : "step-1",
    "src"   : "step-1.html",
    "state" : "active"
    },

    {
    "name"  : "Step 2",
    "id"    : "step-2",
    "src"   : "step-2.html",
    "state" : "unavailable"
    },

    {
    "name"  : "Step 3",
    "id"      : "step-3",
    "src"   : "step-3.html",
    "state" : "unavailable"
}]

Factory:

workflow.factory('getWorkflow', function($http, $q) {
   return {
     getFlow: function() {
       var deferred = $q.defer();
       $http.get('steps.json').success(function(data) {
          deferred.resolve(data);
       }).error(function(){
          deferred.reject();
       });
       return deferred.promise;
     }
   }
});

Control fragments:

var workflow = angular.module("workflow", ['getWorkflow']);

workflow.controller("showStep", function($scope) {
    $scope.workFlow = {};         // Create the workFlow object
    $scope.workFlow.steps = [];   // Create an empty array to hold the steps
    $scope.workFlow.steps = getWorkflow.getFlow(); 

... set the first step as the active step and point to the HTML file ...

    $scope.workFlow.buildNavButtons = function() {
    scope.workFlow.buttonArray = [];    // Create/reset the array of buttons to nothing

    // The button for the PREVIOUS step.
    if ($scope.workFlow.activeStepIndex > 0) {  // Only add button if not the first step
        var prevButton = {};
        prevButton["destination"] = $scope.workFlow.activeStepIndex - 1;
        prevButton["buttonText"] = "<< " + $scope.workFlow.steps[$scope.workFlow.activeStepIndex - 1].name;
        prevButton["buttonClass"] = "workflow-previous";

        $scope.workFlow.buttonArray.push(prevButton);
    }
...

HTML

<!-- PREVIOUS AND NEXT STEP BUTTONS -->
<div id="workflow_navigation">
    <ul>
        <li data-ng-repeat="button in workFlow.buttonArray">
            <button class = "{{ button.buttonClass }}" 
            ng-click="workFlow.updateStep(button.destination)">
                {{ button.buttonText }}
            </button>
        </li>
    </ul>
</div>
+4
source share
1 answer

You have it almost right, just a few problems. First you need to enter factory on your controller not as a module dependency.

var workflow = angular.module("workflow", []);

workflow.controller("showStep", function($scope, getWorkflow) {

And secondly, you need to wait for the promise to be fulfilled before acting on it:

  getWorkflow.getFlow().then(
    function(data) {
      $scope.workFlow.steps = data
      console.log($scope.workFlow.steps);

      // "activeStep" controls which step appears on screen.  
      // This initialize it and loads default content.
      $scope.workFlow.activeStep = $scope.workFlow.steps[0];
      $scope.workFlow.activeStepIndex = 0;
      console.log($scope.workFlow.activeStep);
      $scope.workFlow.content = $scope.workFlow.activeStep.src; // The display of the step content itself - changing this changes the display.

    }); // Use the factory below

This should fix the underlying issues with the promise and allow you to continue. You can check and work plunkr here.

+2
source

Source: https://habr.com/ru/post/1527544/


All Articles