Communication Between Directives in AngularJS

Recently, I've been working on a custom filter directive in Angular:

app.directive('filter', function(){
  return {
    restrict: 'E',
    transclude: true,
    scope: {
        callFunc: '&'
    },
    template:
            '   <div>' +
            '       <div ng-transclude></div>' +
            '   </div>',
    controller: function($scope, $element, $attrs){
        this.getData = function() {
            $scope.callFunc()
        }
    }
  }   
});

app.directive('positions', function(){
  return {
    require: '^filter', 
    scope: {
        selectedPos: '='
    },
    template:
            '  Positions: {{selectedPos}}' +
            '  <ul>' +
            '   <li ng-repeat="pos in positions">' +
            '           <a href="#" ng-click="setPosition(pos); posRegData()">{{pos.name}}</a></a>' +
            '       </li>' +
            '  </ul>',
    controller: function($scope, $element, $attrs){
          $scope.positions = [
            {name: '1'},
            {name: '2'},
            {name: '3'},
            {name: '4'},
            {name: '5'}
          ];
          $scope.selectedPos = $scope.positions[0].name;
          $scope.setPosition = function(pos){
            $scope.selectedPos = pos.name;
          };

    },
    link: function(scope, element, attrs, filterCtrl) {
        scope.posRegData = function() {
            filterCtrl.getData();
        }
    }
  }   
})

Here's the controller code snippet related to the directive:

app.controller('keyCtrl', ['$scope', function($scope) {
  var key = this;
  key.callFunc = function() {
    key.value = key.selectedPos;
    console.log(key.selectedPos)
  }
}]);

I noticed that the value for key.selectedPos in the controller is only updated correctly on the second click. Any insights into why this might be happening?

You can view a live example of this issue on Plunker.


One possible workaround involves passing a parameter when calling the callFunc() method.

In this approach, I update the function in the controller:

key.callFunc = function(filterParams)
, and modify the usage of the method as
call-func="key.callFunc(filterParams)

Then, within the filter directive, I adjust the getData method like so:

this.getData = function(val) {
  $scope.callFunc({filterParams: val})
}

In the positions directive, I pass the relevant value like this:

scope.posRegData = function() {
  filterCtrl.getData({position: scope.selectedPos});
}

Finally, in keyCtrl, I access the value as follows:

key.callFunc = function(filterParams) {
  key.value = filterParams.position;
  console.log(filterPrams.position)
}

For a practical demonstration of this alternate approach, check out this Plunker.

Considering the scale of your application, do you think this method is a viable solution?

Answer №1

Isolated scopes function in a specific way, which explains why the parent scope (typically the controller) updates only after the digest cycle runs following the ng-click function calling the callFunc. To address this issue, consider placing your callFunc code inside a $timeout, although this will trigger another digest cycle.

An alternative solution is to store the value within an object so that any changes made to the object will be immediately reflected in the controller that holds the reference:

In the controller:

key.selectedPos = { value: {}};

key.callFunc = function() {
    key.value = key.selectedPos.value;  
    console.log(key.selectedPos.value)
} 

In the directive:

$scope.selectedPos.value = $scope.positions[0].name;
$scope.setPosition = function(pos){
    $scope.selectedPos.value = pos.name;
};

For a demonstration, refer to this plunker.

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

"Learn the steps to include multiple g:select options in your application

Click here to download an image Is it possible to dynamically append a combobox below the User combobox when the "ADD" button is clicked using JavaScript? I attempted this with jQuery last night, but I couldn't get it to work properly. <g:select ...

Unable to shake off a sudden burst of information following the ajax page load

I am facing an issue with my page that involves making different ajax calls based on user clicks. There are four IDs, and only one should be visible at a time. However, when new ajax content is loaded into a div, I experience a brief flash of the previou ...

Vue JS TypeScript component is unable to locate injected instance properties

Currently, I'm utilizing typescript alongside vue in my project. Within the app structure, there exists a service that acts as a global entity for all sub-components. I stumbled upon this native solution provided by Vue JS, which facilitates injecti ...

The hamburger menu functions properly on the homepage but is not working on the individual about page

The burger menu was causing issues initially due to a simple spelling mistake, which I only noticed later. However, the current issue seems more complex. I am now creating separate pages for different sections of my website, such as About Me, Education, et ...

Traversing a multidimensional array with jQuery

In my quest to iterate through a multidimensional array, I encountered the need to remove the class "list" from the divs within the array. However, there could be multiple divs with this class on my site. My initial approach involved using two for-loops, ...

Testing an Angular component that utilizes an AngularJS service: A comprehensive guide

In my hybrid angular application, I am utilizing AngularJS services alongside Angular services. This setup works seamlessly in the application. export function myServiceFactory(i: any): any { return i.get('MyService'); } export const myService ...

Exploring iPhone Safari Web App: Discovering functions tailored for iPhone users

I am exploring the possibilities of accessing native iPhone features while developing a Web App using html/css/javascript and running it in Safari. I am curious to know if I can tap into smartphone-specific features, especially those unique to iPhone/iTou ...

JS | How can we make an element with style=visibility:hidden become visible?

HTML: <div id="msg-text"><p><b id="msg" name="msg" style="visibility:hidden; color:#3399ff;">This is a hidden message</b></p></div> JS: $('#url').on('change keyup paste', function() { $('# ...

Leveraging GSAP and Vue by utilizing props to dynamically calculate a maxWidth

I am working on animating buttons in my application using GSAP. The idea is that when a user clicks the button, it should animate the maxWidth of the button. I want this to be dynamic by adding a percentage of the max width set using props. Is it possibl ...

What is the correct method for successfully incorporating Vue Router through CDN to enable the functionality of history mode?

I insert scripts into an html document in the following way: <script src="https://unpkg.com/vue/dist/vue.js"></script> <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script> After adding ...

I am having trouble with searching for places using the Google API in my Node

Recently, I've been working on integrating the Google Maps API places feature into my project. Thankfully, I came across an npm module that simplifies the process of connecting it to node. Check out the npm module here! After downloading the module ...

Can someone help me identify the table rows that are adjacent to a dropped row in a jQueryUI Sortable setup?

My current setup involves using the jQueryUI Sortable plugin on a table, and thankfully everything appears to be functioning correctly. Both the HTML and JavaScript are passing validation. However, I am faced with the challenge of finding a way to identi ...

Generating interactive elements in VUE is key

I am unsure about how to dynamically create components without using the <component :is=''> tag. I would like to insert a component into the DOM through JavaScript. Similar to how you would add a new modal in jQuery with $("body").append(" ...

Code Wizard

I am currently working on a project to develop an HTML editor. How it Needs to Function Elements Inside: Text Area - Used for typing HTML as text Iframe - Displays the typed HTML as real [renders string HTML to UI] Various Buttons Functionality: When ...

Working with conditional properties in an AngularJS application across two controllers

Managing Controllers in my Application In my application, I am working with two controllers: Controller 1: When a button is clicked, I open a menu and set the property this.isTelephoneMenuOpen = true;. The result is that the menu opens with options ...

Is there a way in MVC3 / .net4 to convert a JSON formatted JavaScript array into a C# string array?

I am facing a challenge with my MVC3/.Net service where it is receiving arguments in the form of a JSONified Javascript array. I want to convert them into a C# array of strings. Is there a built-in solution available for this task, or do I need to create ...

There was an error in reading the 'rotateOnAxis' property due to its undefined nature

When working with files downloaded from three.js such as cube.obj and cube.mtl, rotating them appears to work without any issues. However, when attempting to rotate files created in Adobe Dimension like capsule.obj and capsule.mtl, an error pops up as seen ...

Error: WebView element type is not valid. A valid string was expected

Here is my basic React code : import React from "react"; import { Text, StyleSheet,View } from "react-native"; import { WebView } from 'react-native'; const App = () => { return( <WebView source={{ ...

Can a Vue app be created as a standalone application?

Can a Vue application be created without requiring Vue as a runtime dependency? For example, rather than having the browser load vue.js and the app like this <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script src= ...

Customize the text color of the active tab in Material-UI Tabs

I am facing a situation where I have this specific object: const tabStyle = { default_tab:{ color: '#68C222', width: '33.3%', backgroundColor: '#FFFFFF', fontSize: 15 }, active_tab: ...