Retrieving ng-model using ng-change in AngularJS

Here is an example of the HTML code I am currently working with:

<select ng-model="country" ng-options="c.name for c in countries" ng-change="filterByCountry"></select>

This HTML snippet is being populated by the following object containing a list of countries:

$scope.countries = [{name:Afghanistan, country:AF}, {name:South Africa, country:ZA}, name:Albania, country:AL}, {name:Germany, country:DE}, {name:Andorra, country:AD} ...];

Despite setting up ng-change to run the filterByCountry function and update $scope.country when the dropdown value changes, it doesn't seem to be working as expected. Can anyone help me figure out what might be missing here?

Answer №1

When it comes to handling changes, the ng-change function triggers before the actual update of ng-model. To ensure that filterByCountry gets triggered every time $scope.country changes, regardless of whether it's due to a dropdown change or not, you should implement the following approach:

$scope.$watch('country', filterByCountry);

In my experience, I've found it more effective to respond to changes within the $scope rather than relying on DOM events whenever possible.

Answer №2

If you're curious about how ng-change works, it's important to note that this directive is triggered after the model value has been set.

But why is that?
To understand when ng-change is called, we can refer to the Angular source code where it is defined as an attribute directive with a specific directive definition object (DDO).

{
    restrict: 'A',
    require: 'ngModel',
    link: function(scope, element, attr, ctrl) {
      ctrl.$viewChangeListeners.push(function() {
        scope.$eval(attr.ngChange);
      });
    }
}

This snippet reveals that the ng-change directive is quite straightforward. When using ng-change='<expr>', a function is added to the $viewChangeListeners array to evaluate <expr> using $scope.$eval.

So, when exactly are the ViewChangeListeners invoked?

Referring to the documentation for ngModel.NgModelController, it states:

the new value will be applied to $modelValue and then the expression specified in the ng-model attribute. Lastly, all the registered change listeners, in the $viewChangeListeners list, are called.

Therefore, the ViewChangeListener for the ngChange directive is activated after the value is assigned to $modelValue. Consequently, the callback is executed after the model has been set.

Additionally, it's worth noting that this behavior remains consistent across all versions of Angular. The definition for ng-change has remained unchanged since v1.2.

Answer №3

According to James Lawson,

The ng-change function is actually triggered after the model value has been updated.

If you're still wondering,

Why am I experiencing the opposite outcome?

It's important to understand that the $scope is inherited prototypically from its parent. If your scope variable is a simple type like a string or boolean, it will be overridden in the child scope by the value set by the ng-model directive.

You can find where the child scope is initialized (on which DOM element) by inspecting with dev tools and looking for class="ng-scope" on the element.

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

Angular utilizing external parameter for Ajax requests

As a newcomer to Angular, I am eager to upgrade some old jQuery code with AngularJS. The task at hand is to extract a string from a span element, split it into two separate strings, and then use these as parameters in a GET request. I am dedicated to lea ...

What is the best way to change the orientation of a vector map?

Is there a straightforward method for rotating a vector-based map on CANVAS in order to integrate it into a browser navigation system? ...

Tips for swapping out a page for a component

Consider a scenario where we have a blog page containing a div element with the class "content" that displays previews of various articles. The goal is to dynamically replace the content within the div element with a specific article. How can this be acco ...

Stop all animations in JS and CSS

Looking for a way to halt all CSS and JavaScript animations, including canvas and webGL effects, on a specific webpage. Some animations can cause slow performance on certain browsers like Opera and Firefox, so I'm seeking a code snippet or guidance o ...

Converting HTML code to JSON using PHP scripting

Would appreciate your help in resolving a small issue. Although I came across this post, I am still encountering some errors: How can I convert HTML to JSON using PHP? I have created a PHP file that extracts a post from WordPress with the following forma ...

Hovers and click effects for navigating through images

The website I'm currently working on is stipz.50webs.com. p.s. HOME functionality is not active at the moment. Having successfully implemented the onhover and onmouseout features, my next goal is to enhance the navigation effects for each div/img so ...

Obtain the file path relative to the project directory from a Typescript module that has been compiled to JavaScript

My directory structure is as follows: - project |- build |- src |- index.ts |- file.txt The typescript code is compiled to the build directory and executed from there. I am seeking a dependable method to access file.txt from the compiled module without ...

Using Vue.js code on an HTML file is only possible when the necessary CDN is included

Just diving into Vue.js and I've got a header html that doesn't include the cdn link for Vue.js. <nav class="navbar navbar-toggleable-md navbar-inverse"> <div class="collapse navbar-collapse" id="navbarSupportedContent"> ...

The error message encountered is "Uncaught (in promise) Error: Unable to access attributes of an undefined object (reading 'launch')."

I am currently learning electron.js by developing a basic application that extracts information from a website. However, I am encountering a frustrating and annoying error. Here is the folder structure of my project The following code snippet represents ...

How to Restrict the Use of Conditional "If" Statements in Another Function in Angular 7

How can I use an IF condition inside a function to only execute once for a specific action and not for another action? I have a function that is called twice, but I want the first "IF" condition inside the function to only be triggered when the add bank b ...

Leverage the power of express-session in your NextJS project

Currently, I am working on developing a login system using NextJS and MySQL. I am looking to implement sessions for user login, but I am unsure of how to integrate express-session with NextJS. Can anyone provide guidance on whether express-session can be ...

Using Sequelize to Create/Post Data with Many-to-Many Relationship

I've been exploring how to implement a M:N Association using Sequelize. After examining the documentation (doc), I came across a solution that closely matches my requirements: User.belongsToMany(Profile, { through: User_Profile }); Profile.belongsToMa ...

The Node.js server delivers a different object to the client

I'm facing an issue while trying to send an object from the client to a Node.js server. Here is my Ajax call: $.ajax({ url: config.api.url, type: config.api.method, contentType: config.api.contentType, // application/x-www-form-urlencoded; cha ...

Steps for sending a request to the root resource

I've encountered a problem that stems from my limited knowledge of Express. Despite creating a project with Express, I'm unable to make calls to the root, only to the routes. I suspect the issue lies in my usage of app.use(...). app.js var inde ...

A guide on incorporating the close button into the title bar of a jQuery pop-up window

Check out this fiddle: https://jsfiddle.net/evbvrkan/ This project is quite comprehensive, so making major changes isn't possible. However, the requirement now is to find a way to place the close button for the second pop-up (which appears when you c ...

What is the best way to enable a DOM element's height to be resized?

I have a widget displayed in the corner of my browser that I would like to make resizable by dragging the header upwards to increase its height. The widget's position remains fixed with its bottom, left, and right properties unchanged, but I need the ...

Google Chrome is unable to process Jquery JSON .each() function

My website has a simple chat application that is functioning well. It uses ajax to request data in this manner: $.ajax({ url: "fetch/"+CHAT_SESSION_ID+"/"+LAST_MESSAGE_ID, dataType: "json", cache: false, success: function(data) { if (data.session_ac ...

How to send an html form with php, store it in a MySQL Database, and utilize Ajax and jQuery for

As a beginner in PHP form creation, I have been exploring various tutorials and combining different techniques to create my form. However, I am facing challenges as none of the tutorials cover everything comprehensively from beginning to end. While I beli ...

Having trouble displaying information in JavaScript after using getScript() to retrieve data from an API containing a JSON block database

I'm a newcomer to the world of Ajax/json/jquery and I find myself with a few inquiries. Currently, I am working with an API located at which contains a JSON block that looks something like this [{"id":"1","FirstName":"Micheal","LastName":"Kooling"}, ...

Establish a WebSocket connection via Meteor.js

How do we establish a Websockets connection in Meteor? Can we achieve this using the following code: ws = new WebSocket('ws://localhost/path'); ws.on('open', function() { ws.send('something'); }); ws.on('message&apo ...