Using $scope.$on name parameter as an attribute within an AngularJS directive

My goal is to create a directive that allows me to pass in an attribute string, which will then be used as the "name" parameter when subscribing to events using $scope.$on. The process involves:

  1. An object is broadcasted using $rootScope.$broadcast, labeled as 'validationResultMessage', in a different controller.
  2. I have a directive with an attribute named "subscription" where I pass the string 'validationResultMessage'.
  3. The directive passes the value of the "subscription" attribute to its scope and subscribes to it using "$scope.$on".

The issue I'm facing is that the value of the attribute seems to be "undefined" during evaluation, causing me to inadvertently subscribe to "undefined" instead of "validationResultMessage".

Below is the directive I've created:

app.directive('detailPane', function () {
return {
    restrict: 'E',
    scope: {
        selectedItem: '=',
        subscription: '@',
    },
    templateUrl: 'app/templates/DetailPane.html',  //I'm also concerned that this might be causing my controller to be instantiated twice
    controller: 'DetailPaneController'

  };
});

Here is how I use the directive:

<td class="sidebar" ng-controller="DetailPaneController"  ng-style="{ 'display': sidebarDisplay }">
            <detail-pane 
                    selected-item='validationResult'
                    subscription='validationResultMessage'/>

</td>

And here is the controller where I'm trying to utilize this attribute:

app.controller('DetailPaneController', ['$scope', '$http', 'dataService', 'toastr', '$uibModal', '$rootScope', '$attrs', function ($scope, $http, dataService, toastr, $uibModal, $rootScope, $attrs) {
$scope.fetching = [];
$scope.validationResult = null;
$scope.sidebarDisplay = 'block';



console.log('subscription is ', $scope.subscription);
var thisSubscription = $scope.subscription;

//if I hardcode the param as 'validationResultMessage', this works
$scope.$on($scope.subscription, function (event, arg) {
    $scope.validationResult = arg;
    });
}]);

Answer №1

One solution I found to resolve this issue was to utilize only the internal DetailPaneController defined within the directive body. The problem stemmed from instantiating the controller twice - once as the parent controller using ng-controller= in the HTML, and again within the directive body. By simplifying the setup and using "@" binding, I was able to ensure everything resolved in the correct order. Additionally, I could incorporate another directive within the template to pass in my validationResult.

The revised configuration is as follows:

DetailPaneController:

app.controller('DetailPaneController', ['$scope', '$http', function ($scope, $http) {

$scope.$on($scope.subscription, function (event, arg) {
    $scope.validationResult = arg;
    $scope.exception = JSON.parse(arg.Exception);
    });
}]);

DetailPane Directive:

app.directive('detailPane', function () {
return {
    restrict: 'E',
    scope: {
        subscription: '@' //updated to not bind to validationResult
    },
    templateUrl: 'app/templates/DetailPane.html',
    controller: 'DetailPaneController'
    };
});

Directive Usage in HTML:

        <div class="sidebar" ng-style="{ 'display': sidebarDisplay }">
            <detail-pane subscription='validationResultMessage' />
        </div>

Directive Template (included for clarity):

<div class="well sidebar-container">
<h3>Details</h3>
<div ng-show="validationResult == null" style="padding: 15px 0 0 15px;">
    <h5 class=""><i class="fa fa-exclamation-triangle" aria-hidden="true" /> Select a break to view</h5>

</div>
<div ng-show="validationResult != null">
    <table class="table table-striped">
        <tr ng-repeat="(key, value) in validationResult">
            <td class="sidebar-labels">{{key | someFilter}}</td>
            <td >{{value | someOtherFilter : key}}</td>
        </tr>
    </table>
    <another-directive selected-item="validationResult" endpoint="endpoint" />
</div>

Answer №2

My answer will be posted first. If you need any clarification on the provided code snippet, please let me know so I can provide additional comments. Make sure to test the code provided below.

var app = angular.module('myApp', []);

app.directive('detailPane', function() {
  return {
    restrict: 'E',
    transclude: false,
    scope: {
      selectedItem: '=',
      subscription: '@'
    },
    link: function(scope, elem, attr) {
      scope.$on(scope.subscription, function(e, data) {
        scope.selectedItem = data.result;
        elem.text(data.message);
      });
    },
  };
});

app.controller('DetailPaneController', function($scope) {
  $scope.validationResult1 = "";
  $scope.validationResult2 = "";
});

app.controller('SecondController', function($rootScope, $scope, $timeout) {

  $timeout(function() {
    $rootScope.$broadcast('validationResultMessage1', {
      message: 'You fail!',
      result: 'Result from 1st fail'
    })
  }, 2000);

  $timeout(function() {
    $rootScope.$broadcast('validationResultMessage2', {
      message: 'You also fail 2!',
      result: 'Result from 2nd fail'
    })
  }, 4000);

});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<body ng-app='myApp'>
  <div ng-controller="DetailPaneController">
    <detail-pane class='hello' selected-item='validationResult1' subscription='validationResultMessage1'></detail-pane>
    <br/>
    <detail-pane class='hello' selected-item='validationResult2' subscription='validationResultMessage2'></detail-pane>

    <hr/>
    <span>{{validationResult1}}</span>
    <br/>
    <span>{{validationResult2}}</span>

  </div>
  <div ng-controller="SecondController">

  </div>
</body>

Answer №3

In my opinion, a good approach would be to monitor changes in the $scope.subscription variable and then initiate the subscription process when a new value is assigned.

$scope.$watch('subscription', function(newVal, oldVal){
 // Ensures the code does not trigger during initialization
 if(newVal !== oldVal){
   $scope.$on($scope.subscription, function (event, argument) {
      $scope.validationResult = argument;
   });
 }
});

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

Failed to execute test suite in React and Jest framework

While working on updates for our existing project, I encountered an error that is causing some of the tests to fail: FAIL src/components/changelog/__test__/ChangeLogOverView.test.tsx ● Test suite failed to run TypeError: Cannot create property & ...

Issue with retrieving relative time using Moment.js - fromNow()

I want to utilize moment.js to display relative time fromNow(), but I am encountering an issue where the values are being rounded and showing higher durations instead of exact completion times. For example, moment().subtract('s',110).fromNow() / ...

What could be causing the malfunction in one of the functions within my JavaScript code?

As a JavaScript beginner, I am currently working on creating a To-do App with JavaScript. Most of the functions are functioning perfectly except for one called doneTask at line 36. Despite numerous attempts to identify the issue, I have been unsuccessful s ...

jQuery and Bootstrap collide

Here is my jQuery code that toggles visibility of different divs based on a click event: $(function () { $(".kyle-div, .tracey-div, .frank-div, .rosie-div").hide(); $("a").bind("click", function () { $(".conor-div, . ...

Only perform the Rails ajax call once initially

I'm currently working on creating a drop down menu that contains a substantial amount of content, and I would like to use an ajax get call to load everything upon mouse enter. Here is my code written in coffeescript: class @SecondaryMenu construct ...

JavaScript function to add or subtract

I need to include additional inputs for "+ and -" 60mm and 120mm in my function. How can I achieve this without turning all of them into separate functions? <template> <card class="card"> <h2>Measurement</h2> <form&g ...

Transferring data from a stream in NodeJS to FrontEnd using ReactJS

How are you doing? I'm trying to figure out how to send a large data request from PostgreSQL to the FrontEnd in JSON format. Can anyone help with an example of how this can be achieved? Thank you. Here is my code: const express = require('expr ...

The controller in my template is not being passed by the $routeProvider

I attempted to dynamically load a template in Angular using ngRoute... However, I encountered an issue with the following code: (app.js route configuration) app.config(function($routeProvider) { $routeProvider.when("/password", { templateUrl ...

Leveraging Javascript within MVC3, either on a master page or child page

I'm currently developing a web application utilizing MVC3 and I am curious about the best practices for incorporating JavaScript. Specifically, I am uncertain about whether to include JavaScript in the master page as well as in individual child pages. ...

Retrieve information from jsonObject

Can anyone help me with counting the number of passes and fails for each subject in a JSON object array? Here is an example: [{"Subject":"Maths","status:"Pass"},{"Subject":"Maths","status:"Pass"}, {"Subject":"Maths","status:"Fail"},{"Subject":"Maths ...

What is the proper way to send a list as a parameter in a restangular post request

Check out this code snippet I found: assignUserToProject(pid: number, selectedUsers: any, uid: number) { let instance = this; return instance.Restangular.all("configure/assign").one(pid.toString()).one(uid.toString()).post(selectedUsers); } ...

Error: Reactjs - Attempting to access the 'name' property of an undefined variable

As I continue to learn about React, I have been experimenting with props in my code. However, I encountered an error where the prop is appearing as undefined. This issue has left me puzzled since I am still at a basic level of understanding React. If anyo ...

Maximizing Efficiency: Sending Multiple Responses during computation with Express.js

Seeking a way to send multiple responses to a client while computing. See the example below: app.get("/test", (req, res) => { console.log('test'); setTimeout(() => { res.write('Yep'); setTime ...

Having trouble getting ng-bind-html-unsafe to work within an AngularJS directive?

I am encountering a specific issue with my code. In the jsFiddle I shared, I am attempting to utilize ng-bind-html-unsafe within a template in my directive. The value of the attribute that I'm passing (item{{itemColumn.field}}) is dependent on being i ...

Having issues with socket.io connectivity on my Node server

I am setting up my node server to update all connected clients with real-time information. However, when I run the code provided below, the io.sockets.on('connection') callback keeps firing constantly, flooding the console with the message Client ...

incorporating event handlers to references retrieved from bespoke hooks

I have designed a simple custom hook in my React application to manage the onChange events of a specific input element. const useInput = () => { const ref = useRef(null); const handleChange = () => { console.log("Input has been ...

Guide to implementing dynamic conditional rendering in Vue.js loops (utilizing v-if within v-for)

I am currently working on a table component in a .vue file where I want to display icons based on the direction of the order clicked. For example: <th v-for="(column, index) in columns" :key="index" @click="sort( index )"> <span& ...

Is a delayed updating model preferred?

I find AngularJS's data-binding feature fascinating, but I have a specific requirement - I don't want the view to be updated automatically unless the user clicks a "save" button. Is there a way I can postpone the view update while still maintaini ...

Encountering TypeError: Unable to access the 'query' property as it is undefined

As I dive into learning AngularJS and sending requests to a Web API backend, I encountered the following error message: angular.js:13424 TypeError: Cannot read property 'query' of undefined In my project, I have a productListController define ...

Angular.js guarantees fetching data with $http.get

I encountered an issue with my service that makes an $HTTP.GET request. Initially, I tried to access the object $$state but found that the value inside was undefined. To resolve this, I delved into learning about promises and asynchronous calls by reading ...