Utilizing repeated directives within a single controller in Angular

Currently, I am in the process of developing a webpage that utilizes Highcharts to display some data. To ensure reusability, I have encapsulated the desired chart within a directive.

'use strict';
angular.module('statisticsApp')
  .directive('cleanbarchart', function () {
    scope:{
      localdata:'@'
    }
    return {
      template: '<div></div>',
      restrict: 'E',
      link: function postLink(scope, element, iAttrs) {
          // console.log(iAttrs);
          // console.log(iAttrs);
          // var attrs = JSON.parse(iAttrs.id);
          var attrs = iAttrs;
          element.highcharts({
            chart: {
              type: 'column',
              width:1000,
              zoomType: 'x'
            },
            title: {
              text: scope.localdata[attrs.id].title //title
            },
            xAxis: {
              categories: scope.localdata[attrs.id].categories, crosshair: true

            },
            yAxis: {
              min: 0
            },
            tooltip: {
            // code for tooltips
            },
            plotOptions: {
           // additional options
            },

            series: scope.localdata[attrs.id].series
          })
      }
    };
  });

Within my controller, I utilize a service along with a callback function to populate the localdata.

angular.module('statisticsApp')
  .controller('AboutCtrl', function ($scope, HttpDataService) {

     function done(data){

       console.log(data);
       $scope.localdata['test2'] = data; //HttpDataService.getUniqueUsers() ;
     }

     $scope.localdata = {} ;
     HttpDataService.getUniqueUsers(done) ;
});

The service structure is as follows:

angular.module('statisticsApp')
  .service('HttpDataService', function($http, $q, baseRestPath) {
    // AngularJS will instantiate a singleton by calling "new" on this function
    return {
      getUniqueUsers: function (callback, periodicity) {
        var url = baseRestPath + '/sessions/uniqueUsers';
        console.log(url);
        var dates = [];
        var values = [];

        $http.get(url).then(
          function successCallback(response){
            var data = response.data;
            data.forEach(function(dataLine) {
              dates.push(dataLine[1]);
              values.push(dataLine[0]);
            })
            console.log(values);
            callback({title: 'Unique Users', categories:dates, 'series': [ {name: 'Alltime', data:values} ]  });
            
          },function errorCallBack(response){
            //do nothing
          }
        );

// returns data
      }
    }
  });

To call the directive in my HTML, I use the following snippet:

<cleanbarchart id="test2"></cleanbarchart>

Even though the service functions correctly and returns the data appropriately, I encounter an error message:

Cannot read property 'title' of undefined

This issue potentially stems from the asynchronous nature of $http requests. Despite attempting to use the watch block to monitor either scope.localdata or scope.localdata[attrs.id], I have been unable to resolve this issue.

link: function postLink(scope, element, iAttrs) {
  scope.$watch('localdata',function(){
    element.highcharts.....
  }
}

or 

link: function postLink(scope, element, iAttrs) {
  scope.$watch('localdata[' + attrs.id + ']',function(){
    element.highcharts.....
  }
}

Your assistance with resolving this matter would be greatly appreciated.

Answer №1

To begin, it is important to update your service so that it returns a promise instead of utilizing a callback function. Referencing the $http documentation, you will find that $http.get yields an HttpPromise object that can be resolved at a later time.

Once this adjustment has been made, you can now pass the promise to the directive rather than passing the data directly.

Instead of:

$scope.localdata = {} ;
HttpDataService.getUniqueUsers(done) ;

You should modify it to:

$scope.localdataPromise = HttpDataService.getUniqueUsers();

Subsequently, within the directive, resolve the promise in this manner:

scope.localdataPromise.then(function (data) { /* resolve data and draw chart */ });

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

The issue of memory leakage with ng-grid and real-time data

My intention is to utilize ng-grid for visualizing high-frequency real-time data, but I am encountering issues with a memory leak. Interestingly, the memory leak does not occur when I opt for a simple HTML table with ng-repeat. My tech stack includes node ...

Guide to select all the checkboxes within rows using AngularJS

New to AngularJs, I am facing a challenge with the code below. The table is populated using Angularjs and includes a selectAll checkbox in the header that should select all checkboxes in the table when checked. However, due to sorting and filtering capabil ...

What is the best way to clear a canvas when the erase button is clicked using sketch.min.js?

I incorporated the sketch.min.js file obtained from this source. The functionality I aimed for was that clicking on the Eraser link should directly erase the canvas. To avoid the need of clicking twice on the eraser link and canvas, I required that a sing ...

Locate items across three different arrays

Is there a more efficient way to search for an element across 3 arrays and create a string using their values? I have attempted a solution and generated the output, but I am curious if there is a better approach available. var numbers = ['1',&ap ...

Is there a way to ensure that both new Date() and new Date("yyyy-mm-dd hh:mm:ss") are initialized with the same timezone?

When utilizing both constructors, I noticed that they generate with different timezones. Ideally, they should be in the same timezone to ensure accurate calculations between them. I attempted to manually parse today's date and time, but this feels li ...

The `$(this).data()` function removes any excess data from a database, stopping at the first occurrence of a

One issue I am encountering is when retrieving data with a whitespace. I need the complete string of data, not the trimmed version. When retrieving "data-title" or "data-type", the data gets cut at the whitespace. I tested by setting a static string in ...

Leveraging the outcome of an API request with Protractor

I have developed a small API that generates test data instantly. Each request creates a new user and provides the relevant data. For fetching the data, I utilize the 'request' package: var flow = protractor.promise.controlFlow(); var result = f ...

Retrieve the content of the nearest 'td' element using the '.closest()' method, then locate the desired

I am struggling to assign the value from a <td> to a variable. My approach involves utilizing the closest() and find() methods in jQuery to locate the desired <td>. Interestingly, when I use alert on the <td>, it displays the correct val ...

Error Encountered in AngularJS: Request Unexpected (No Additional Requests Anticipated)

In my AngularJS project, I'm facing a challenge in writing unit tests to verify that executing a promise's then function changes the location.url. The function login within the AuthenticationService service is responsible for this behavior. Belo ...

Next.js allows you to create a single page that corresponds to the root path '/' as well as a dynamic route '/param'

I have a single-page website built with Next.js. The home page, which displays a list of products, is located at route / and the corresponding code can be found in pages/index.js. Each product has an id, allowing users to jump directly to it using /#produc ...

Performing matrix manipulations using Mirror.js (Three.js)

I am currently working on creating water effects in three.js and I haven't come across any examples in three.js that incorporate both reflection and refraction. If you know of any examples, please feel free to share the links with me. Currently, I am ...

What is the best way to bring a JavaScript library into a TypeScript project if the library includes a declaration file?

I have been attempting to utilize the type definitions from the callbag library. Unlike other libraries, callbag declares its type definition file within its package.json and is not included in DefinitelyTyped. However, when I try to import the library, I ...

Validating RSS Feeds with Javascript

Hey, I'm looking to replicate something like this: I want to verify RSS feeds before submitting a form. <form name="form1" id="form1"> <input type="text" name="url" type="text" id="url" /> <input type="submit" name="submit" id="bu ...

"Troubleshooting the slow loading of PDF files when using React's render-pdf feature

After creating a table with the ability for each row to generate and download a PDF using render-pdf npm, I encountered an issue. When the user clicks the download button, the PDF preview opens on a new page. However, there are problems with rendering as a ...

Developing an Easy-to-Use PDF Popup Interface

I need a simple PDF modal where I can input the text: 'The sky is blue' and have it link to a PDF that opens up when clicked. I found a similar sample online, but it includes an image plus an image modal that pops up. I want to replace the imag ...

Retrieve the value associated with the data attribute of the chosen dropdown option

I need to extract the custom data attribute from the chosen option of a dropdown menu and insert it into a text box. This will be the second data attribute I'm working with. I plan to implement code that will run whenever the user changes the option ( ...

Issue with executing Jquery in PUG file: The $ sign is not being recognized despite jQuery being imported

I am encountering an issue where my jQuery code placed inside a pug template is not executing as expected. Despite including the jQuery file, when trying to run a jQuery function, I receive the error below: 40| P 41| ...

Issue: ngModel: Unassignable Value

I am currently working on a piece of code that dynamically generates a drop-down list. My goal is to set the selected value using ng-repeat. In order to achieve this, I have implemented a function in ng-model. However, I am encountering an issue with the f ...

Shut down the pop-up in Chrome before the DOM finishes loading

Utilizing the most recent iteration of the selenium web driver along with the Google Chrome browser, I am encountering an issue in my application. Following the click on the login button, a popup appears while the DOM is still loading. view image I simpl ...

Firefox seems to handle webpages smoothly, whereas IE struggles to display them properly

Check out the code snippet below: self.xmlHttpReq = new XMLHttpRequest(); self.xmlHttpReq.onreadystatechange = function() { if(self.xmlHttpReq.readyState == 4 && self.xmlHttpReq.status == 200) { xmlDoc = self.xmlHttpReq.response ...