Ways to guarantee that the factory promise is fulfilled prior to the execution of the

So far, I have always found valuable help by studying existing answers on stackoverflow, but now I've hit a roadblock.

I'm currently working on an app that utilizes a directive to generate calendar month boxes.

<app2directive class="column_50" year="2016" month="November"></app2directive>

The directive code isolates the scope and uses a templateUrl file to display the calendar month.

App.directive('app2directive',function( YEARS, MONTHS, DAYS){

return {
    restrict:"ACE",
    scope:{},
    replace:true,
    templateUrl:"templates/cal_directive3.html",
    controller: function ( $scope, $attrs, $injector, $log, YEARS, MONTHS, DAYS) {            var factoryName = "datumFactory" ;
        var factoryTonnen = "jsonsrc" ;
        var factoryInstance = $injector.get( factoryName ) ;
        var tonnenInstance = $injector.get( factoryTonnen ) ;

        var wtf = $scope.jsondata.get().then( function( promise){
            console.log( "jsondata", promise ) ;
            //$scope.tonnen = promise ;
        }, function( error){
            console.log( "error", error ) ;
        }) ;


});

Currently, I am using an $injector to inject a factory that performs a $http request to retrieve data from a JSON file containing information like holidays or other static details specific to the chosen year and month(s).

App.factory( 'jsonsrc', function( $http, $q ){ 
return {
    get: function(){
        var deferred = $q.defer() ;
        $http.get( 'termine_2016.json' )
            .success(function(data, status, headers, config) {
                deferred.resolve( data ) ;
            }).error(function(data, status, headers, config) {
                console.log( "[jsonsrc] request did not work!" );
                deferred.reject( data ) ;
            }) ;
        return deferred.promise ;
    }
}

});

This results in the $http call being made 12 times for a full year page load.

My goal is to refactor the code so that I can ideally load the JSON data into the main controller and have the directive inherit from the parent scope.

Since the call returns a promise, the directive needs to wait for it to resolve before proceeding, but I am currently unsure how to approach this. Any guidance would be greatly appreciated!

Answer №1

Initially, $http already returns a promise that you can work with:

return $http.get(...)

On another note, remember that you can chain promises together. If you need to preprocess data before returning it, you can do so like this:

return $http.get(..).then(function(response){
    var data = response.data;
    [..process..]
    **return data;**
}, function(rejection){
    // handle rejections
});

In a typical scenario, you bind data to your directive using ng-model and call services in the controller. To manage asynchronous data loading, you can use scope.$watch or attrs.$observe on the model to update your directive.

This approach allows for flexibility in how data is loaded, making directives reusable regardless of the data source or changes in the application.

Don't forget the importance of the bolded text mentioned earlier, as it ensures that your processed data is available for subsequent 'then' calls.

Lastly, when using the link function provided by the directive API, consider including:

link  : function(scope, element, attrs){
    attrs.$observe('myVariable', function(){
         // update internal state of directive here
    });
}

'myVariable' refers to an attribute named my-variable in the directive's invocation.

If "myData" is loaded in the view controller as shown below:

jsonrc.get().then(function(response){
    $scope.myData = response.data;
});

To take it a step further, consider creating a service for your holiday service to load data only once at application startup:

App.service('MyService',['$http', function($http){
    var promise = $http.get([URL]);
    return function(){  // define your service
        var self = this;
        promise.then(function(response){
            self.data = response.data;
        });
    }
}]);

Now, in your main controller, you can utilize: scope.data = MyService.data; Alternatively, you can integrate it into your directive or use getters as needed. This level of abstraction can be advantageous, though not always necessary.

If anything was left out, please let me know.

Answer №2

This method might be beneficial.

  • To start, include the async call in a parent controller (the directive's parent controller).
  • Next, isolate your directive's scope and add a model to it.

scope: {
  data: '=',
}

  • In your controller, declare a variable like this: $scope.directiveData = {}
  • Set the value of that variable with the result of the async call.
  • Don't forget to pass it to your directive using:
    <mydirective data="directiveData"></mydirective>
  • Access this variable in your template using the name data, or scope.data in the link function.

You may need mocked data for directiveData, or add an ng-if to prevent crashing (when trying to display data for the first time and directiveData is an empty object).

Answer №3

Optimize your factory by caching the httpPromise and creating it only once.

App.factory( 'jsonsrc', function( $http ){
     var httpPromise;
     function load () {
         httpPromise = $http.get( 'termine_2016.json' )
             .then(function onFullfilled(response) {
                  //return data for chaining
                  return response.data;
             }).catch( function onRejected(response) {
                  console.log( "[jsonsrc] request didnot work!" );
                  //throw to reject promise
                  throw response.status;
             });
          return httpPromise;
      };
      function get () {
          if (httpPromise) return httpPromise;
          //Otherwise
          return load();
      };
      return { load: load,
               get:  get
             };
});

The usage of $q.defer has been replaced with .then and .catch methods as the .success and .error methods are now deprecated according to the AngularJS $http Service API Reference -- deprecation notice.

Your directive can be simplified as follows:

App.directive('app2directive',function(){
    return {
        restrict:"ACE",
        scope:{},
        replace:true,
        templateUrl:"templates/cal_directive3.html",
        controller: function ($scope, $attrs, jsonsrc, $log, YEARS, MONTHS, DAYS) { 
            jsonsrc.get().then (function (data) {
                $scope.tonnen = data ;
            }).catch( function(error){
                console.log( "error", error ) ;
            });
        })
    }
});

By implementing this approach, the XHR GET request in the jsonsrc factory is executed only once while each instance of app2directive can retrieve the data independently for its own isolate scope.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Creating a structured file hierarchy by extracting files from Amazon S3 and transferring them for storage in Firebase

I am looking to retrieve key/value pairs from Amazon S3 and then store some of the obtained information in Firebase to build a file system in AngularJS. This question focuses only on storing in Firebase. It is essential to be able to create an unlimited ...

What is the best way to retrieve a complete DynamoDB scan response using aws-sdk-js-v3 without object types included in the marshaled response?

After struggling with the AWS JS SDK V3 documentation and examples, I decided to share my findings to help others. The official SDK docs were frustrating and misleading, especially when it came to showing marshaled output properly. While the DDB Doc client ...

What is the most effective method for checking the structure of a JSON string object in a JAVA program

Is there a way to quickly determine if a given string object is a properly formatted JSON object, regardless of its actual data? For example: "abc":"123", "cba":"233" } This scenario should result in a format exception. { "abc":"123" "cba":"233" } Woul ...

What are the advantages of using React JS for a Single Page Application compared to server-side rendering?

Currently, I am faced with a conundrum when it comes to selecting the best approach for a highly scalable project. On one hand, server-side rendering using Node.js with Express (utilizing EJS) to render full HTML pages is an option. On the other hand, ther ...

What is causing my checkboxes to deactivate other selections?

My checkboxes are causing a dilemma where changing the value of one checkbox sets all others to false. To address this issue, I am considering implementing a solution in my validate.php file that would only update the intended checkbox value. If this appro ...

What is the best way to split key and value into separate array objects using JavaScript?

Here's a snippet of code I am working with: let obj = {EdadBeneficiario1: '32', EdadBeneficiario2: '5'} var years = []; let i; for (i= obj;i<=obj;i++) { years.push({ edad_beneficiario : i }) } When I run this code, the output i ...

Using angularjs, populate a dropdown menu by enclosing the options in curly braces

Utilizing the curly braces syntax interpolation in AngularJS allows us to connect data from the model to the view. This technique is typically used for displaying text. Is there a way to populate a dropdown list using the {{}} syntax? ...

Formatting a ui-grid grid column in RC 3.0 to display currency

The options for the grid displayed below are meeting expectations in terms of data presentation. However, when attempting to format the value of row.entity[col.field] in my cellTemplate, I am not getting any data returned. Here is the code snippet: $scop ...

Retrieving information from the backend with AngularJS

Is there a more efficient way to retrieve data from the backend when using AngularJS (or similar) in my web application? The current method I see involves rendering static HTML with JavaScript scripts, such as AngularJS, and then making AJAX requests to f ...

Troubleshooting Node.js Application: Investigating Port Errors

After cloning a node.js application, I went through the setup process by running npm install and npm install -g nodemon. In order to run the application locally on port 3000, I added the following line in my app.js file: app.listen(3000, () => console. ...

I encountered no response when attempting to trigger an alert using jQuery within the CodeIgniter framework

Jquery/Javascript seem to be causing issues in codeigniter. Here is what I have done so far: In my config.php file, I made the following additions: $config['javascript_location'] = 'libraries/javascript/jquery.js'; $config['javas ...

At what point is a $.cache considered oversized?

After coming across a fascinating tutorial, I learned that certain memory leaks in jQuery can be identified by monitoring the size of the $.cache variable. It was emphasized to always keep an eye on its size, as it could indicate potential issues if it bec ...

Why do we even need to use $validators and $setValidity in our code?

There seems to be some confusion surrounding the use of $validators and $setValidity. I've noticed that both these functions seem to achieve the same outcome, so do we really need to use both? Please correct me if I'm mistaken. Even without the $ ...

Encountering crashes when trying to map JSON data onto React components

I have created a menu items application that displays products from a JSON file. When an item is clicked, it shows some modifiers for that item. Everything works well until certain categories or items are clicked, causing the application to crash. To test ...

Numerical values are not considered by the JavaScript table filter

I'm having trouble with dynamically filtering the content. It works fine for the first two columns, but not for the third one. Maybe I need some additional JavaScript? Here is the link to my snippet: `https://www.w3schools.com/code/tryit.asp?filen ...

What is causing these dynamic carousels to malfunction in Chrome?

After using Agile Carousel successfully for a while, I am now experiencing issues with it not working properly in Safari and Chrome, although it functions fine on Firefox and Safari for iPad. On this specific page, the carousel stops at the second image, ...

When trying to log the parsed JSON, it unexpectedly returns undefined even though it appears to be in good

Everything was working fine until a couple of days ago. Let's consider this as my PHP script: echo json_encode(array('stat'=>'ok')); I am sending an AJAX request to this script: $.post(base_url+'line/finalize/', {t ...

Using Angular 4 to delete selected rows based on user input in typescript

I am facing a challenge with a table that contains rows and checkboxes. There is one main checkbox in the header along with multiple checkboxes for each row. I am now searching for a function that can delete rows from the table when a delete button is clic ...

Efficiently bundling Angular templates using Grunt and Browserify

I am currently utilizing angular1 in conjunction with browserify and grunt to construct my application. At present, browserify only bundles the controllers and retrieves the templates using ng-include through a separate ajax call. Due to the excessive amo ...

Storing JSON data in a WordPress database

I have developed a unique plugin that effectively retrieves and displays data from an external API. Code: function retrieve_posts_from_api() { $request = wp_remote_get( 'http://xxx' ); if( is_wp_error( $request ) ) { return fal ...