Angular directive that watches for property changes without taking action

I've recently developed a directive that utilizes d3 for rendering, with data being passed in through props like this:

<my-directive words="fromControllerData"></my-directive>

The "fromControllerData" can be modified by the parent component, and I'm looking for a way to trigger a re-render of my directive.

How can I effectively detect changes in the data?

I've come across various examples, but none seemed to work for me...

You can view the project via this link: https://plnkr.co/edit/I6eyFMBrhoDpxfOsulrI?p=preview

You will find the directive implementation in:

app.js // line 48

I have tried using both scope.$watch and scope.$watchCollection...

Here's a snippet from the controller:

app.controller('AppController', ['$scope', '$rootScope', 'serverData', function($scope, $rootScope, serverData) {
$scope.data = {
    words: serverData
};

setTimeout(function() {
  console.log('changed');
  $scope.data.words = [];  
}, 1000);

}]);

And here's some code from the directive:

app.directive("gravityWordCloud", ['serverData', function(serverData) {
return {
    restrict: "EA",
    scope: {
        words: "="
    },
    link: function(scope, element, attrs) {
        // irrelevant stuff

        //this only works on initial load...
        //subsequent updates are not detected
        scope.$watchCollection('words', function() {
          console.log(scope.words);

        });

    }
}
}])

Answer №1

Here is a helpful code snippet:

scope.$watch('scope.words', function() {
    console.log(scope.words);
}, true);

By adding the 'true' parameter to the $watch function, you enable a 'deep' watch that compares the values of the object. The function signature can be found in the Angular documentation (https://docs.angularjs.org/api/ng/type/$rootScope.Scope):

$watch(watchExpression, listener, [objectEquality]);

Another technique is to create a function that returns the words and then watch that function:

scope.$watch(function() {
    return someFunctionThatReturnsWords();
}, function() {
    console.log(scope.words);
});

Correction: You should watch 'scope.words' instead of just 'words'

Answer №2

After incorporating the code snippet below into your Plunker, positive results were achieved:

const fetchPhrases = () => {
    return data.phrases;
}

data.$watch(fetchPhrases, () => {
    console.log(data.phrases);              
}, true);

Answer №3

It's interesting how such a small error can end up causing so much wasted time...

I realized that the "words" variable wasn't being updated in the controller scope when it was on "timeout." However, when I manually changed it later with another method while clicking something, I suddenly saw the timeout change as well.

In summary: when I switched from using plain JavaScript:

setTimeout

to AngularJS:

$timeout

everything started working correctly...

It seems like there might be something related to scopes causing this issue...

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

how to reorganize page sections using javascript

Hello, I am new to HTML5 and Javascript and I am trying to create a simple function that swaps the positions of two sections using an event trigger. The first function works fine, moving the section with ID "con" to the top. However, the second function i ...

Issue with Object.keys printing in an abnormal manner

My goal is to extract only the keys from an object, but instead of getting the desired output with the keys, I am seeing numbers. Here is the code snippet: data = {"property" : "{\"animalID\": \"12345\" ...

Convert a Twitter Direct Message Link by changing the `<button>` tag to an `<a>` tag

When you log into Twitter and have Direct Message enabled, a "Send Message" button will appear. Can someone please provide the URL for sending a DM to a specific user? I tried looking at the code but I could use some assistance. Any thoughts? Thank you in ...

Step-by-Step Guide: Running Multiple Yo Angular-Fullstack Applications on the Same Server and Port

On my development server, I have been experimenting with various applications. Currently, I am interested in running multiple yo angular-fullstack applications simultaneously on the same server, each having their own sub-directory. For instance, navigati ...

Dealing with Uncaught Type Errors in the Fixed Data Table

I am attempting to implement a fixed data table using the following code snippet. var MyCompi = React.createClass({ getInitialState: function() { return { rows : [ {"id":1,"first_name":"William","last_name":"Elliott","email":"<a ...

Issue with BootstrapVue b-table: selected rows are not saved when moving between pages with b-pagination

I implemented a b-table along with b-pagination in my Vue template: <b-table bordered hover responsive :items="items" :fields="fields" :sort-by.sync="sortBy" :sort-desc.sync="sortDesc" sort-icon-le ...

Configuring Firefox settings in Nightwatch

Is there a way to set Firefox preferences in nightwatch? I am trying to achieve the same thing in Java using nightwatch. To set Firefox preferences in nightwatch, you can use the following code snippet: FirefoxProfile profile = new FirefoxProfile(); prof ...

Defining a Global Variable using the jQuery $(this)

I have been looking for ways to simplify my coding process, and one method I've tried is assigning a global variable. var parent = $(this).parent().parent().parent(); var parentModule = $(this).parent().parent().parent().parent(); Throughout my code ...

Accessing images from Firebase within Ionic 3

Currently, I am developing a phone wallpapers application using Ionic 3. For storing and retrieving photos, I am utilizing the Firebase database. However, I am facing an issue when trying to display these photos in the app. For instance, if I upload three ...

What is the best way to distinguish between an active route featuring an id (e.g. /about#contact) and an active route without an id (e.g. /about) when using react router's <NavLink /> component?

My website has an about page ("/about") with a contact form linked to an id (e.g. contact-form). The navigation bar includes links for 'Home', 'About', and 'Contact'. I have added basic styling to indicate the active route: im ...

The timing of setTimeout within the $.each function does not behave as expected

I am looking to back up a list, delete all items within it, and then append each item one by one with a delay of 1 second between them. This is the approach I have taken: var backup = $('#rGallery').html(); $('#rGallery li').remove(); ...

Having difficulty implementing the .fadeIn jQuery function on a script for transitioning homepage images

I'm a beginner and I'm not sure if fadeIn is the right transition, but I want to create a crossfade effect between homepage images that switch every 3 seconds. The image changing is successful, but I can't figure out how to make them fade. C ...

Arranging multiple selections in Dojo's dijit

Just wondering if there's a built-in way in Dojo/Dijit multiselect to sort the options, or do I have to manually implement it? Many thanks Edit: I managed to solve my issue by implementing a sorting algorithm. Here's the code for anyone who mi ...

The art of toggling input values with Angular JS

I have a simple application where users input string values into two fields and the text is incorporated into a sentence. I am looking to add a button that, when clicked, will switch the values in the fields. HTML <body> <div ng-app="myApp" ng ...

Unusual results observed with the Promise.all method

There's a code snippet I'm working on where I need to await 5 promises, wait for 2 seconds, and then continue with another set of 5 promises. However, it seems like the two instances of Promise.all are not being awaited as expected. I wonder if I ...

What is the best way to create a grid item that maximizes the available space in ReactJS Material-UI?

Currently, I am working with the material-ui grid system in a reactjs project. In a column grid container layout, my goal is to display two grid items and have a third item fill up the remaining space between them. Essentially, I want it to look like this: ...

What is the Best Way to Enable Tooltips to Function from External Elements?

I am currently designing a map that features points with tooltips. When hovered over, the tooltips function correctly. I am interested in exploring the possibility of making the tooltips interact with an external navigation bar. My goal is to have specifi ...

Switch the parent container in AngularJS by utilizing ng-click functionality

Within two distinct containers, one container holds a button. Upon clicking it, this button should move to the second container. I am familiar with achieving this using jQuery: $(document).on('click', '.drag', function(){ if($(thi ...

Tips for pausing keyframes animation on its final animation frame

Is there a way to halt my animation at the 100% keyframe? What I'm attempting to accomplish is animating these boxes so that when you click on the top one, it moves to the bottom and vice versa. Any suggestions or ideas on how to achieve this? <h ...

Utilize DataTables with a custom search form for enhanced data filtering

I rely on DataTables for its advanced functionality in creating tables with paging capabilities. When submitting data through a standard jQuery Ajax request using my own form, the returned data is formatted and then passed to the DataTables function to en ...