AngularJS utilizes the observe directive to dynamically inherit scope through attribute expressions

Here is my simple code:

.controller('Ctrl', ['$scope', '$timeout', function ($scope, $timeout) {
    $timeout(function () {
      $scope.x = 5;
    }, 2000);
  }])
.directive('ngHey', ['$parse', function ($parse) {
    return {
      'restrict': 'A',
      'scope': true,
      'link': function($scope, el, atr) {

        var go = function () {
            if ($parse(atr.ngHey)()) {

              alert('oiiiiiii');
            }
          };

        atr.$observe('ngHey', function (val) {
          if (val) {

            go();
          }
        });
      }
    };
  }]);

//view.html

<div ng-controller="Ctrl">
<span ng-hey="x > 3"></span>
</div>

I want the directive to fire when the expression changes to either true or false, but currently the alert never appears...

It only works if I use:

<div ng-controller="Ctrl">
    <span ng-hey="{{x > 3}}"></span>
    </div>

However, this is not what I desire. I want the directive to handle expressions like ng-if or ng-hide...

Any help or tips would be greatly appreciated, thank you

Answer №1

Instead of using $observe in this situation, consider using $watch on the scope. The $observe function observes an interpolated attribute, as documented here. Here's an example of how to implement it:

.directive('ngHey', ['$parse',
    function($parse) {
        return {
            scope: true,
            link: function($scope, el, atr) {

                var go = function(value) {
                    if (value) {
                        alert('oiiiiiii');
                    }
                };

                $scope.$watch(atr.ngHey, function(val) {
                    if (val) {
                        go(val);
                    }
                });
            }
        };
    }
]);

See a demo here: http://plnkr.co/edit/XakjA2I7lpJdo9YAZFEH?p=preview

UPD. Based on feedback from the original poster, the updated directive now looks like this:

.directive('ngHey', ['$parse',
    function($parse) {
        return {
            scope:{ngHey: '='},
            link: function($scope, el, atr) {

                var go = function(value) {
                    if ($scope.ngHey) {
                        alert('oiiiiiii');
                    }
                };

                $scope.$watch('ngHey', function(val) {
                    if (val) {
                        go();
                    }
                });
            }
        };
    }
]);

It's worth noting how $scope.ngHey is utilized in this context, eliminating the need to $eval the attribute.

See the updated demo here: http://plnkr.co/edit/XakjA2I7lpJdo9YAZFEH?p=preview

Answer №2

JSFIDDLE DEMO

Due to the delayed setting of the value of x by $timeout, the directive's condition checking for the attribute was always returning false. To address this, implement $watch to monitor changes in x within the go() function.

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

myApp.directive('ngHey', function () {
    return {
      'restrict': 'A',
       'scope': true,
      'link': function($scope, el, attr) {

        var go = function () {
            if ($scope.$eval(attr.ngHey)) {
              alert('oiiiiiii');
            }
          };

        $scope.$watch('x', function (val) {
          if (val) {
            go();
          }
        });
      }
    };
  });

Replace $parse with $scope.$eval, and similarly replace $observe with $watch.

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

Update the display using a button without the need to refresh the entire webpage

I am currently working on a website project that requires randomized output. I have successfully implemented a solution using Javascript, but the output only changes when the page is reloaded. Is there a way to update the output without refreshing the en ...

Limit the length of text using jQuery by specifying the maximum pixel width

Trying to utilize jQuery for a quick function that calculates the pixel width of a string on an HTML page and then shortens the string until it reaches a desired pixel width... Unfortunately, I'm encountering issues with this process as the text is n ...

Tips for sending a file array together with other string/int variables from JavaScript to PHP

I am looking to pass the imageArray[] along with a variable trackNo. Passing the imageArray[] is not an issue, but I am unsure of how to include other variables with the FormData(). When researching online, I only came across examples of people passing a ...

Error: Unable to access the 'login' property of an undefined object

An error occurred: Uncaught TypeError: Cannot read property 'login' of undefined........... import Login from '../components/Login.jsx'; import { useDeps, composeWithTracker, composeAll } from 'mantra-core'; export const com ...

What could be causing my Vue.js sorting array script to malfunction?

I'm encountering an issue with sorting the table by Date. The sort function used to determine the type of sorting no longer works, and I'm unsure why. html: <th @click = "sort('data_produktu')" class="date">Da ...

What could be causing my JavaScript alert to not appear on the screen?

Essentially, I've been attempting to trigger a Javascript alert using PHP. However, the alert isn't functioning at all. This is my echo statement that dynamically generates the alert echo "<script>alert('Uploaded file was not in the ...

Obtain the model value using Yii jQuery and then proceed to submit the form

Within the _form.php view, there is a presence of $model and a CActiveForm $form. I implemented JavaScript code to compare the value of $model->publication_date with the current date. If they are identical, the form will be submitted automatically. Othe ...

File resolution issue with TypeScript

While I am aware that using TypeScript outFile is generally advised against, I currently have no choice but to utilize it until a more suitable solution like AMD can be implemented. It seems like there may be a "module splitting issue" in my project. In t ...

Set iframe scroll to match the height of the user's screen resolution

Can the height of an iframe scroll be adjusted to match the size of the screen (browser)? Essentially replacing the default browser scroll with the iframe scroll. Here's what I'm looking to achieve: Currently, my browser scroll is disabled: < ...

What methods can I use to test a Django view that includes a form?

As I embark on developing an application using Django, I find myself faced with a particular challenge. I have created a view that receives a form from the HTML code and then searches the database for any instances of a model based on the values specified ...

"Debugging a simple demonstration showcasing NodeJS, AngularJS, and Express

Currently, I am following an online tutorial to learn a new concept. I have reached the part where I need to display data using HTTP GET from the controller, while the sample data is stored in the server file. I managed to fetch the data from the controlle ...

What is the best way to integrate a JSON response obtained from $http.get in Angular?

When retrieving a JSON using $http.get, I am facing compatibility issues with Angular. To make it compatible, I have to convert it like this: $http.get('/api/v1.0/plans'). success(function(data) { var plans = []; for(var prop ...

What are the differences between a Chrome app and extension? Is there any other way to access the tabs currently open in your

I need to develop an app that can access the tabs a user has open, but I'm struggling to find a way to do so without having my app run in Chrome itself. Creating an extension restricts the UI significantly, which is problematic since my app requires a ...

Modifying the data of a particular object in my rtk asynchronous thunk

I recently started using rtk and immer. I encountered an issue when trying to update my state with redux. For example, when a user logs in, I store their data in redux with the following structure: data = { "user_profile" : { "name&q ...

What is the method for generating three inputs simultaneously in a single line?

I'm facing a challenge in my code where I want each line to contain only three input fields. Whenever I try to add a fourth input field, the first one remains on the previous line while the other three move to the next line. Oddly enough, this issue o ...

Objects that are not defined in a Gruntfile for a legacy AngularJS project

My old AngularJS (1) application used to start without any issues. However, after updating my dependencies yesterday, I am now encountering an error where the module and require objects are suddenly undefined. // Generated on 2014-10-21 using generator-a ...

How can I determine the length of the returned array after a successful jQuery Ajax

I am struggling with looping through the Array returned from PHP. However, when I use jQuery .length, it returns 'undefined'. 'undefined' PHP: $items = array(); $items["country"] = "North Korea", $items["fruits"] = array( ...

What steps can I take to help EventListener locate a specific class if it is experiencing difficulty?

In the process of creating a responsive navigation bar, everything seems to be functioning correctly except for a small javascript error that arises in my sub menu when clicking. Despite thoroughly checking through my index, script, and style files, I am ...

Enhancing the getDate function in JavaScript with additional days

My function for selecting the date is working perfectly: formatDateField(event: Date, formControl: string) { this.form .get(formControl) .patchValue( this.datePipe.transform(event.getTime(), "yyyy-MM-dd'T'HH:mm:ss&quo ...

Commit the incorrect file name with the first letter capitalized

There seems to be an issue with the git not recognizing the correct filename casing. I have a file named User.js in my workspace, but when checking the git status, it displays user.js instead. Despite repeatedly changing and committing as User.js, the gi ...