What is the best way to monitor a variable using the controllerAs syntax in Angular?

When utilizing the standard controller syntax in AngularJS, you have the ability to watch a variable with code like this:

$scope.$watch(somethingToWatch, function() { alert('It changed!'); });

However, with the controllerAs syntax, how can I easily react to changes in an active controller?

For more detail, I have a single controller in a side panel that manages the application's context (such as user selection, start time, end time, etc.). Therefore, when the user switches to a different context, the main view needs to react and update accordingly. The context values are stored in a factory and each controller is injected with that factory.

Answer №1

If you want to monitor a specific item on the controller instance or any object, using a watcher evaluator function can be very useful. You have the flexibility to return any variable you want.

  var vm = this;
  //Here, vm represents the cached controller instance.
  $scope.$watch(function(){
     return vm.propToWatch;
  }, function() { 
      //Do something
  }, true);//<-- turn on this if needed for deep watch

Another method is using a bound function to bind the this context.

$scope.$watch(angular.bind(this, function(){
     return this.propToWatch;
    //You can simply return the variable here
 }), listenerFn);

You can also use the ES5 function.bind:

 $scope.$watch((function(){
     return this.propToWatch;
 }).bind(this), listenerFn);

In the TypeScript environment, the syntax becomes even shorter.

$scope.$watch(()=> this.propToWatch, listenerFn);

Although you can watch the controller alias inside the controller ($scope.watch('ctrlAs.someProp'), it can lead to a few issues:

  • It requires knowing the exact alias used for the controller in various places where the controller is implemented, which contradicts the purpose of using controllerAs:'anyVMAlias' for readability.

  • When unit testing the controller, you need to ensure the same alias is used, adding an extra step, especially for TDD.

  • Using a watcher with a watcher function instead of a string reduces the internal steps taken by the angular $parse to convert the expression, as seen in the switch-case of the $parse implementation.

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

Insert an HTML tag into JSLint

Is there a way to include an HTML tag in JSLint's list of recognized tags? I'm encountering some errors with the following message: JSLint: Unrecognized tag 'foo'. How can I make the foo tag recognized by JSLint as a valid HTML tag? ...

Learn how to import MarkerClusterer from the React Google Maps library without using the require method

The sample provided utilizes const { MarkerClusterer } = require("react-google-maps/lib/components/addons/MarkerClusterer");, however, I would prefer to use the import method. I attempted using: import { MarkerClusterer } from 'react-google-maps/lib ...

Methods for applying a style property to a div element with JavaScriptExecutor in Selenium utilizing C#

I have been attempting to change the style of a div element using JavascriptExecutor in C#, but so far, nothing has happened. IJavaScriptExecutor js = (IJavaScriptExecutor)driver; IWebElement element = driver.FindElement(By.XPath("//div[contains(@class, ...

"Utilize Cypress to simulate clicking a button by triggering the enter key

Currently, I'm conducting testing on my application and attempting to trigger a button click using the Enter key: <v-btn class="submit-button" block color="primary" @click="login" > Log In < ...

Is there a better method to determine the width when utilizing the jQuery UI resizable feature for improved efficiency?

I'm currently working on a website that features a resizable sidebar. I want the icons and text within the sidebar to shrink proportionally when the user resizes it. Right now, I have implemented an if statement to check if the sidebar's width fa ...

Generate an li element that is interactive, containing both text and a span element

I am dealing with a JSON array that looks like this: var teamDetails=[ { "pType" : "Search Engines", "count" : 5}, { "pType" : "Content Server", "count" : 1}, { "pType" : "Search Engines", "count" : 1}, { "pType" : "Business", "count" : 1,}, { "pTyp ...

Dealing with AngularJS: The issue of Factory being undefined when injected into a controller

I'm currently working on a straightforward example of an AddressBook Angular application. I've set up a factory that returns an array of records, and this data is then displayed in a list view using a List controller angular.module('abModul ...

Using Try and Catch effectively - tips and strategies

As I delve into learning JavaScript on my own, one topic that caught my attention is the try/catch structure. The tutorial I came across only covers how to implement it, but lacks in explaining its practical applications. Is there anyone who can shed som ...

Prompting a 401 error immediately after attempting to login through the Express REST API

Recently, I've encountered a strange issue with the controller for my login route. It was working perfectly fine yesterday without any hiccups, but suddenly it stopped functioning properly. Despite not making any changes to the code, it now consistent ...

Which specific indexOf method is the most appropriate for my use case?

While exploring a codebase, I came across this code snippet that adds the indexOf function: if (!Array.prototype.indexOf) { Array.prototype.indexOf = function(elt /*, from*/) { var len = this.length >>> 0; var from = Number(arguments ...

Google Script: How to automatically open a newly created text document after its creation

I decided to try out this script for generating Google text documents from Google Spreadsheet data. However, I noticed that the new text document created from a template is always placed in the default folder. This means that I have to manually locate the ...

Handling errors in XMLHttpRequest using Axios in React JS

I am currently utilizing the REACT-JS framework for my FRONT-END development: Below is the action I am calling from REDUX-REACT export function UserLogin(values) { var headers = { 'Access-Control-Allow-Origin': '*', ...

Retrieve JSON information utilizing a specific value stored in the localStorage

After an extensive search online yielded no results, I decided to seek assistance here. This is what I have managed to gather so far: JSON I possess a JSON file containing various lists of words that require retrieval based on user input. The structure ...

Retrieving Data from Outside Source using AngularJS

Is there a way to retrieve JSON-Text-Stream data from a specific URL (e.g. SOMEURL/ean.php?id=4001513007704)? The returned result typically appears as follows: { "product": { "ean_id": "4001513007704", "title": "Gerolsteiner Mineralw ...

Discover how to obtain an access token using Yelp API V3 with JavaScript

Currently in the process of learning how to utilize this system, however there appears to be an issue with my code. $.ajax({ dataType: "POST", url: "https://api.yelp.com/oauth2/token", grant_type: "client_credentials", client_i ...

Exploiting jQuery UI in a Web Browser Bookmarklet

When using CoffeeScript, even though the code is very similar to JavaScript: tabs_html = "<div id='nm-container'><ul><li><a href='#tabs-1'>Guidelines</a></li><li><a href='#tabs-2'& ...

What is the best way to eliminate the bottom border of an input field?

Seeking advice on how to eliminate the border-bottom of an input field when typing starts. .car-list-input { font-family: 'Source Sans Pro', sans-serif; border-radius: 3px; font-size: 14px; font-weight: 400 !important; height: 35px; ...

The Wikipedia API is unable to be loaded using the XMLHttpRequest

I have encountered this error before on this platform, and although I managed to fix it, I am seeking a more in-depth explanation of the solution. For a project where I am learning, I decided to create a Wikipedia Viewer application. The first step was to ...

Tips for positioning HTML elements at the exact mouse location as it moves, without any delay?

Currently, I am in the process of developing a web-based drawing application that does not rely on using a canvas. My decision to avoid using a canvas is because I plan to incorporate CSS Keyframes into the HTML elements upon placement. This approach allow ...

Eliminate operation in React with the help of Axios

Within my React application, I have implemented a callback method for deleting data from an API using the axios library: deleteBook(selectedBook) { this.setState({selectedBook:selectedBook}) axios.delete(this.apiBooks + '/' + this.select ...