Is there a way to send a boolean to a directive and activate a function when that boolean is altered, all without using $watch?

My goal was to achieve something akin to the following simplified example:

class ButtonController {
  set isFoo(value) {
    console.log(value);
    // do something here
  }
}

angular.module('myApp', []).directive('mButton', () => {
  return {
    restrict: 'E',
    replace: true,
    controller: ButtonController,
    controllerAs: 'button',
    template: '<button class="btn" type="button">Blah</button>',
    scope: {},
    bindToController: {
      isFoo: '='
    }
  };
});

and use the directive like so:

<div ng-app="myApp">
  <m-button is-foo="true"></m-button>
</div>

view demo here: http://codepen.io/anon/pen/zrWRVr?editors=1010

However, this leads to a $compile:nonassign error which I was able to resolve by doing the following:

<div ng-app="myApp" ng-init="foo=true">
  <m-button is-foo="foo"></m-button>
</div>

view demo here: http://codepen.io/anon/pen/VexweM?editors=1010

Nevertheless, I wanted to pass the boolean directly as shown in the previous markup. Is that not feasible? Must I really resort to something like the following if I desire to pass the boolean directly?

class ButtonController {
  set isFooWatcher(value) {
    console.log(value);
    // do something here
  }
}

angular.module('myApp', []).directive('mButton', () => {
  return {
    restrict: 'E',
    replace: true,
    controller: ButtonController,
    controllerAs: 'button',
    template: '<button class="btn" type="button">Blah</button>',
    scope: {},
    bindToController: {
      isFoo: '='
    },
    link(scope, element, attrs, ctrl) {
      scope.$watch(() => ctrl.isFoo, () => {
        ctrl.isFooWatcher = ctrl.isFoo;
      });
    }
  };
});

view demo here: http://codepen.io/anon/pen/QymxrZ?editors=1010

Answer №1

Today, I randomly discovered a solution to my problem. It turns out that the issue was with missing a getter for the property despite having a setter! The code snippet below showcases the correct implementation:

class ButtonController {
  set isFoo(value) {
    console.log(value);
    this._isFoo = value;
  }

  get isFoo() {
    return this._isFoo;
  }
}

angular.module('myApp', []).directive('mButton', () => {
  return {
    restrict: 'E',
    replace: true,
    controller: ButtonController,
    controllerAs: 'button',
    template: '<button class="btn" type="button">Blah</button>',
    scope: {},
    bindToController: {
      isFoo: '='
    }
  };
});

If you want to see a working example, check it out here: http://codepen.io/anon/pen/rxrZWe?editors=1010

Answer №2

To implement a one-way binding using the & in Angular, you can make some slight adjustments to your code:

class ButtonController {
  set isFoo(get) {
    console.log( get() );
    // perform actions here
  }
}

angular.module('myApp', []).directive('mButton', () => {
  return {
    restrict: 'E',
    replace: true,
    controller: ButtonController,
    controllerAs: 'button',
    template: '<button class="btn" type="button">Blah</button>',
    scope: {},
    bindToController: {
      isFoo: '&'
    }
  };
});

The benefit of this approach is that it allows you to pass either a direct boolean value like true, a model like myValue which contains a boolean, or even an expression such as:

<div ng-app="myApp">
  <m-button is-foo="someCondition && !data.invalid"></m-button>
</div>

Answer №3

To properly integrate a directive, you must include either of the following options:

scope: {
    value1 : '&'
    value2 : '='
}

& : this option allows the value to be used as a string

= : with this option, the value serves as a pointer to the value in scope. This is beneficial because it eliminates the need for a convoluted string in your DOM. Additionally, any updates made to the value in the parent controller will automatically reflect in the directive.

If you prefer another approach, you can also incorporate it into a link function, which is further elaborated on in the documentation. Read more here

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

What steps do I need to follow to send a POST request using JavaScript in Django while including the CSRF token?

I've encountered a similar issue where the solutions provided didn't quite work for me: Fetch, set-cookies and csrf Proper Django CSRF validation using fetch post request Even though I believe my post request content is correct, I still keep g ...

Failure to retrieve data with ajax call in php script

I am a beginner in the world of JS and PHP. I am taking on the challenge of teaching myself. Following the guidance provided in this answer from Stack Overflow, I attempted to implement it in my project. Unfortunately, I am facing challenges and would gre ...

The error message states: "An error occurred: Unable to find the 'HttpProvider' property within an undefined

import * as Web3 from 'web3' import { OpenSeaPort, Network } from 'opensea-js' const provider = new Web3.providers.HttpProvider('https://mainnet.infura.io') Hello everyone, I'm currently learning Node.js and encountered ...

how to include a personalized header in AngularJS HTTP requests

I'm looking to include a unique custom header in the $http.get method, but I'm unsure of the process. var hello = _helper.server.http($http, url) .success(function(response){ //do something }); Can someone guide me on how to ins ...

What is the best way to input information into my Google spreadsheet with React JS?

After using https://github.com/ruucm/react-google-sheets as a reference, I encountered a persistent gapi 404 error whenever I tried to run the code. It seems like the GitHub link might not exist, causing my app to fail. However, I could be mistaken. Is t ...

Unraveling the complexities of double-encoded UTF-8 in PHP

Trying to transmit data from an HTML page via Ajax to a PHP page. This is the jQuery code I'm using: $.ajax({ url: "test.php", type: "POST", data: { name: "João" } }).done(function (data) { alert(data); }) When sending ...

Enhance an item by introducing additional properties derived from its current key-value pairs

I have a task of converting the following object: myObj = { "pageName": "home", "dataExtract": "data1|data2=value2|data3=value3|data4=value4a,value4b,value4c"} Into this format: myObjMod = { 'pageName': 'home', 'dataExtract&apos ...

Why is the abort function in JavaScript important?

What possible scenarios would require me to utilize this feature? ...

Accessing Promise.all in the rejection function is not allowed

I have a service that retrieves data, and I make 5 calls to it with different parameters to retrieve various datasets. When the function is successful, everything works fine. However, in case of failure for any of the 5 calls, I need to handle it differen ...

Continuous loop of images displayed in a slideshow (HTML/JavaScript)

Greetings everyone, I am currently working on creating an endless loop slideshow of images for my website. Despite researching several resources, I am still struggling to get the code right. The issue I am facing is that only the image set in the HTML code ...

Struggling to initialize the primary module in AngularJS

Each time I attempt to inject a dependency, I encounter the following error message: Uncaught Error: [$injector:modulerr] Failed to instantiate module marbleApp due to: Error: [$injector:modulerr] Failed to instantiate module ngRoute due to: Error: [$inje ...

Issue with Ag-Grid's getRowClass not locating the appropriate CSS styling

I am facing a simple challenge at the moment. My goal is to dynamically change the background color of my rows, with the intention of incorporating this feature when expanding or contracting groups. Currently, I am attempting to utilize gridOptions.getRow ...

Error encountered on Google Chrome due to Firefox web worker functionality being incompatible

Within my web worker, I have a line where I define the onmessage handler as shown below: onmessage = function() {/*...*/} While this code works flawlessly in Firefox, it throws an error in Google Chrome: Uncaught ReferenceError: onmessage is not defined ...

Checking the image loading functionality with Cypress

I am interested in testing Cypress to verify that an image is successfully loaded onto a page. Here is a snippet of my source code: import React from "react"; export default class Product extends React.Component { render() { return ( <div ...

Detecting changes in URL hash using JavaScript - the ultimate guide

What is the most effective method for determining if a URL has changed in JavaScript? Some websites, such as GitHub, utilize AJAX to add page information after a # symbol in order to generate a distinct URL without having to refresh the page. How can one ...

Passing data retrieved from fetch requests in ReactJS using context: Best practices

Just started learning React and need some help. I'm trying to pass variables with json data to a component for further use but running into errors. What changes should I make to use variables with json data from Store.js in the product.js component? T ...

The React server-side rendering isn't reflecting changes made on the client-side route

Upon the first refresh, both the server and client side are updated; however, subsequent updates only affect the client side when switching pages with react router. For instance, refreshing the page or entering a new URL causes changes on the server and t ...

Guide on efficiently mapping an array containing arrays and simply retrieving the result

I am working with an array of arrays and I need to extract the values from each array. However, when I try to map over the arrays, I end up with just a single array and I'm not sure how to access the individual values. const arr = [ [1, 2, 3], ...

Is there a way to search for a specific item within a nested array?

I have 2 arrays within an array, each containing objects. How can I locate the object with the name "Sneijder"? const players = [ [ { id: 1, name: "Hagi", }, { id: 2, name: "Carlos", }, ], [ { id: 3 ...

Tips for implementing date filtering in Angular2

I am facing an issue in my class where I need to implement date filtering, similar to Angular 1: $filter('date')(startDate, 'yyyy-MM-dd HH:mm:ss') For Angular 2, it seems like the DatePipe class can be used for this purpose. However, ...