Ways to transfer controller information to a personalized directive in AngularJS

I am trying to pass a variable from my controller to a custom directive in AngularJS.

Controller:

angular.
    module('orderOverview').
    component('orderOverview', {
        templateUrl: 'home-page/order-overview/order-overview.template.html',
        controller: ['Orders',
            function ControllerFunction(Orders) {
        var self = this;

        // Order Info
        Orders.getOverview().$promise.then(function(data) {
          self.LineItems = data;
        });
        // Order Info
      }
    ]
  });

Directive

angular.
    module('myApp').
    directive('gvInitializeOrderStatus', function() {
    return {
      scope: {
        field: '@',
        myData: '='
      },
      link: function(scope, element) {
        console.log('field:', scope.field);
        console.log('data:', scope.myData);
      }
    }
    });

HTML

<div gv-initialize-order-status field="InquiryDone" myData="$ctrl.LineItems">
    <span class="tooltiptext">Inquiry</span>
</div>

Although field logs properly when the page is loaded, data appears as undefined.

I have attempted various methods but am unable to resolve this issue. This should work as I intend it to in my mind.

In another section of the same template, I successfully passed data to a directive using ng-repeat. However, in this case, I do not want to use ng-repeat.

Successful ng-repeat HTML with passed data

<li ng-repeat="lineItem in $ctrl.LineItems">
    <div class="status-circle" 
         ng-click="toggleCircle($event, lineItem, 'InquiryDone')"
         field="InquiryDone" item="lineItem" gv-initialize-statuses>
        <span class="tooltiptext">Inquiry</span>
    </div>
</li>

In my other directive, gv-initialize-statuses, I utilized a similar concept in my scope object and used something like scope: { 'field': '=' } which worked effectively.

How can I achieve this without relying on ng-repeat?

Answer №1

Avoid Using Two-Way Binding with =

When creating directives, it is recommended to utilize $watch in the link function instead of two-way binding:

app.directive('gvInitializeOrderStatus', function() {
    return {
      scope: {
        field: '@',
        myData: '<'
      },
      link: function(scope, element) {
        console.log('field:', scope.field);
        console.log('data:', scope.myData);
        scope.$watch('myData', function(value) {
            console.log('data:', scope.myData);
        });
      }
    }
});

Unlike two-way binding using =, one-way binding with < is more efficient for performance reasons.


To improve code efficiency and ease migration to Angular 2+, consider implementing the $onChanges life-cycle hook in the controller:

app.directive('gvInitializeOrderStatus', function() {
    return {
      scope: {
        field: '@',
        myData: '<'
      },
      bindToController: true,
      controllerAs: "$ctrl",
      controller: function() {
        console.log('field:', this.field);
        console.log('data:', this.myData);
        this.$onChanges = function(changes) {
            if (changes.myData)
                console.log('data:', changes.myData.currentValue);
            };
        });
      }
    }
});

Using this approach will optimize the code and facilitate future transitions.


There are various levels of watch mechanisms:

The ng-repeat directive utilizes $watchCollection.

In some cases, the directive may require employing the $doCheck Life-Cycle hook.

For further details, refer to:

Answer №2

To retrieve the data in your directive, follow these steps:

Orders.getOverview().$promise.then(function(data) {
          self.LineItems = data;
          $rootScope.$broadcast('myData', data);
        });

In your directive, listen for the 'myData' event and use a callback function to handle it.

$scope.$on('myData', function(event, args) {

    var anyThing = args;
    // Implement your desired functionality here
});

Answer №3

The issue lies with the $promise.

At the moment when the directive becomes active, self.LineItems is not yet available. This is why the data appears as undefined.

You might want to consider using ng-if:

<div ng-if="$ctrl.LineItems" gv-initialize-order-status field="InquiryDone" myData="$ctrl.LineItems">
    <span class="tooltiptext">Inquiry</span>
</div>

I hope this information proves useful. Best of luck!

Answer №4

While researching $compile in the documentation, I came across a solution that worked for me. I discovered that it is possible to retrieve interpolated attribute values by accessing them through the attrs object instead of having them in the scope object. Here's how I implemented it.

Custom Directive

angular.
    module('myApp').
    directive('gvInitializeOrderStatus', function() {
    return {
      scope: {
        field: '@'
      },
      link: function(scope, element, attrs) {
        console.log('field:', scope.field);
        console.log('attrs:', attrs);
        attrs.$observe('lineItems', function(value) {
          console.log(value);
        })
      }
    }
    });

HTML Markup

<div gv-initialize-order-status field="InquiryDone" lineItems="{{$ctrl.LineItems}}">
     <span class="tooltiptext">Inquiry</span>
</div>

I made sure to include {{ }} around the lineItems attribute in the HTML. This setup with attrs.$observe allowed me to receive notifications of any changes to the value.

Answer №5

implementing directive

angular.
module('myApp').
directive('gvSetupOrderStatus', function() {
return {
  scope: {
    criteria: '@',
    dataModel: '='     // <- access data with this (dataModel to data-model in template)
  },
  link: function(scope, element) {
    console.log('criteria:', scope.criteria);
    console.log('content:', scope.dataModel);
  }
}
});

setting up in template

<div gv-setup-order-status field="InquiryDone" data-model="$ctrl.LineItems">
  <span class="tooltiptext">Inquiry</span>
</div>

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

Guide on defining Component displayName using arrow function Higher Order Component

Currently, I am attempting to include a displayname in my HOC and eliminate the comment eslint-disable-next-line react/display-name from the code provided below: const withMyHOC = () => <P extends MyProps>(WrappedComponent: React.ComponentType< ...

Tips for presenting styled HTML content within a dynamic list using HTML and JavaScript

Is there a way to display HTML formatted text within a dynamic list in HTML? I've tried implementing it, but the tags are being displayed instead of the formatted text. Here's an example of the code: <!DOCTYPE html> <html> <body> ...

Tips on displaying the appropriate object value in a text field based on the selection from a dropdown menu

In my Ruby on Rails form, I have a dropdown menu with various category names: <td> <div class="div1"> <%= f.collection_select(:category_id, Category.all, :name, id: 'category_select', :include_blank => & ...

Troubleshooting a rendering performance problem with an object rendered using Three.js

Having an issue with animations slowing down over time when rendering an obj file from Blender using Three.js. Here's the code snippet I'm working with: <script> var objcontainer, stats; var camera, scene, rendere ...

Error: The function `push` cannot be used on the variable `result` (TypeError)

Here is a snippet from my react component const mockFetch = () => Promise.resolve({ json: () => new Promise((resolve) => setTimeout(() => resolve({ student1: { studentName: 'student1' }, student2: { studen ...

I'm trying to figure out the best way to successfully pass a prop to another component in TypeScript without running into the frustrating issue of not being able to

I have been facing an issue while trying to pass a prop from a custom object I have defined. The structure of the object is as follows: export type CustomObjectType = { data?: DataObject }; export type DataObject = { id: number; name: stri ...

What could be causing the events of the confirm dialog buttons in Telerik's RadWindow to not fire?

Due to privacy concerns, I am unable to provide specific details about this issue. The confirm dialog feature is functioning flawlessly for the majority of users, except for one individual who is accessing the same environment using identical Internet Expl ...

The Spotify Whitelisted URI may show an error message: { "error": "invalid_grant", "error_description": "Redirect URI is invalid" }

Although there are similar questions out there, I'm facing a different issue. I am trying to obtain an access token from Spotify API, but all I keep getting is the dreaded "invalid redirect uri" error. Below is my API call: const request = require(& ...

In ReactJS, the radio button in Material UI selects the value of the previous button

In my ReactJS app, I've implemented a radio button group. However, I am encountering an issue where logging the value results in the previous button's value rather than the current one. For instance, if I switch from "all" to "awaited," the log s ...

What is the reason for not encountering an error when reading an array beyond its index limit?

Recently, while working on a pre-existing website with JavaScript code, I made an interesting discovery. I noticed that the code was accessing array items in a unique way: var value = myArray[0, 1]; This seems to be retrieving the second item of the arr ...

Enhancing Pixi.js functionality with TypeScript: Utilizing 'none' Module Settings

My project is a 100% JavaScript application that operates in the browser, consisting of around 20 JS files with all function names in the global scope. Whenever I make changes to a JS file, I can simply refresh the page and see the updates immediately. Ho ...

"Mastering the art of event delegation: A guide to effectively engaging with various

I have data that is generated dynamically, as shown in the snippet below: const resultsDiv = document.getElementById("results"); const getList = document.getElementById("example"); document.querySelector(".container").addEventListener("click", function ...

The auto-play feature fails to function on iPhone devices when using Reactjs

I am currently working with Reactjs and Nextjs. I have a video on my website that is functioning properly on Android phones but not on iPhones. How can I resolve this issue? I have attempted the following code: <video loop autoplay='' muted> ...

Challenges with rendering items in a FlatList component in React Native

I'm currently working on transferring data from a data.json file to video.js <Image source={{ uri: video.snippet.thumbnails.medium.url }} style={{ height: 200 }} /> and I want this file to be rendered in a flatlist <FlatList showsHorizo ...

Using Object.assign() in Internet Explorer 11 while working with Angular 2

Despite the countless discussions on this issue, I have not found a solution that works for me. This is the current content of my polyfills.browser.ts file: import 'ie-shim'; import 'core-js/es7/reflect'; import 'reflect-metadat ...

waiting for deferred to complete in esri javascript api before continuing with code execution - labelPoints

I'm encountering an issue with obtaining my labelPoints before completing the rest of my code. It seems to be related to a deferred/callback problem that I can't quite grasp, and I couldn't find many examples using the esri javascript api. ...

JavaScript game security with Ajax

My JavaScript game, created using jQuery, involves storing the player's position in a database. When the character is in motion, a request is sent to a specific URL such as mysite.com/map/x1/y3 (where x=1, y=3 represents the character's position) ...

Develop your own personalized Angular schematics that produces a file that begins with an underscore

Having trouble with custom Angular schematics file naming. I'm trying to create a theme SCSS file that starts with an underscore followed by a double underscore as a delimiter. For instance, I want the file name to be _mouse-theme.scss, using the nam ...

Adjusting the input value using JavaScript

My goal is to change the value of a C# variable behind-the-code using JavaScript. Here is my code: HTML & JS - function SetPostbackValues() { document.getElementById("hiddenControl").value = "Employer"; } function SetPostbackValues2() { ...

Displaying a PDF file in a browser using a byte array with JavaScript without the need for base64 encoding

I am currently dealing with an ASP .NET Web API where the POST function is sending back a byte array in C# code like this: return Ok(outputStream.ToArray()); outputStream is of type System.IO.MemoryStream and ToArray() returns a byte array. The purpose ...