Engaging with ng-change and select: Modifying data source results in a change

Take a look at this plunkr: http://plnkr.co/edit/ke4Cjg3gnf2pWUKW1f2b?p=preview.

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

app.controller('controller', ['$scope', '$timeout', function($scope, $timeout) {
    $scope.items = [
      {name:'candy'},
      {name:'chocolate'}
    ];
    $scope.choice = null;

    $scope.test = function() { 
      console.log( 'fired' );
    }
    
    $timeout( function(){
      $scope.choice = $scope.items[0];
    }, 2000);
    
    $timeout( function(){
      $scope.items = [
        {name:'hershey'},
        {name:'mint'}
      ];
    }, 5000);
}]);

Moreover

    <select 
      ng-model="choice" 
      ng-options="item as item.name for item in items"
      ng-change="test()">
    </select>

I am using a select box with ng-options and an ng-change event. Ng-change documentation states the following:

The ngChange expression is only evaluated when a change in the input value causes a new value to be committed to the model.

It will not be evaluated:

  • if the value returned from the $parsers transformation pipeline has not changed
  • if the input has continued to be invalid since the model will stay null
  • if the model is changed programmatically and not by a change to the input value

It seems that even if I dynamically change the source of ng-options, ng-change fires unless ng-model is null when the changes occur.

Do you think this is intentional or a bug? If it's intentional, how can I modify ng-options without triggering ng-change unless ng-model is first set to null? Otherwise, I may need to report this behavior as unusual.

Thank you!

Answer №1

Here's what's going on:

  1. First, you choose a value from the dropdown menu (for example, candy).
  2. After a certain amount of time has passed, a new array is created within $scope.items. AngularJS then updates the HTML dropdown menu with this new set of items, causing the selected item to change from its previous value (candy) to null.
  3. This change triggers the evaluation of the ng-change expression.

This process is considered valid because there was a visible change (from candy to null) that occurred not through direct manipulation of the model, but through changing the DOM element itself.

The solution to this issue will depend on your specific needs. In the provided example, the selected value will always update since all old options are replaced by new ones. However, consider another scenario where I remove chocolate and add two new values while keeping the candy option:

$timeout( function(){
  delete $scope.items[1]; // removes chocolate from the list.

  // Add new items
  $scope.items[1] = {name : 'hershey' };
  $scope.items[2] = {name : 'mint' };

}, 5000);

In this case, if the user selects "candy," the ng-change event won't trigger as the selected option remains the same. But if the user chooses "chocolate," the change will fire (going from "chocolate" to null). Here are some strategies you may want to consider:

  1. Only add items to the dropdown list without removing any existing options.
  2. If an option needs to be removed, set the value to null programmatically instead of relying on user selection (as this won't trigger the model change).
  3. To ensure ng-change fires consistently, replace the entire array. Then, include checks within the ng-change function to handle cases where the model doesn't update automatically.

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

Troubles with Geocoding functionality on Google Maps integration within Wordpress

I have a challenge where I want to utilize the title of a Wordpress post (a specific location) as a visible marker on a Google map. The code provided by Google successfully displays the map without any markers: <script>function initialize() { va ...

Protractor encountering difficulties using by.repeater() on ng-repeat element

I am currently facing an issue with my Angular HTML code while attempting to conduct end-to-end testing using protractor for clicking on a dropdown. Below is the snippet of the HTML code: <ul class="dropdown-menu"> <li ng-repeat="currency in ...

Tips for setting up a select dropdown in AngularJS using ng-options when the value is an object

How can I set the initial selection of a select field using ng-options? Consider the items we have: $scope.items = [{ id: 1, label: 'aLabel', subItem: { name: 'aSubItem' } }, { id: 2, label: 'bLabel', subItem: { ...

Incorporating an HTML element into a Vue template

I'm currently utilizing a chart component (Chartist) that needs an HTML element to serve as a parent during SVG rendering. The elements that the chart requires are generated within a v-for loop, meaning they are not part of the DOM when the chart is ...

Javascript - Displaying data retrieved from an external API with JSON

Seeking advice on how to effectively attach JSON values obtained from xhr.response to HTML labels. Any suggestions are appreciated. Thank you. On a different note, does anyone have recommendations for websites that provide concise explanations of basic JS ...

What is the best way to calculate the total of values in a JavaScript object?

In my array, I have a list of items with prices that I am attempting to sum up. Here is how it appears in the Chrome developer tools: (3) [{…}, {…}, {…}]0: {ID: 1, ProductName: " New phone 1", Price: "€ 600"}1: {ID: 3, ProductNa ...

JS on-click function is not functioning

Here is the HTML code I have for my navigation menu: <nav role="navigation" class="nav"> <ul class="nav-items"> <li class="nav-item"> <a href="#" class="nav-link"><span>About Us</span></a> ...

Combining jQuery with another library, what do you think?

I am working on a project that necessitates the incorporation of a tailor-made JavaScript library into the websites of end users. It's somewhat like a third-party tool for tracking, similar to Google Analytics. We will not have control over the other ...

Why does the script source direct me to localhost:5000?

https://i.sstatic.net/X0TKs.png Hello fellow developers! I've encountered an issue while attempting to keep my javascript file separate from my .ejs files. Despite pointing my script tag to "../client/index.js," which is the correct location of the f ...

Issue with Vue JS router component: Unable to reuse JavaScript file containing webpack imports after switching routes

Hey, I'm facing a bit of a complex issue here, but I'll do my best to explain it clearly. Currently, I'm using the latest versions of Vue and Vue-Router in my application with webpack. The main component in question is called CP.vue & ...

Repositioning the li element at the beginning of the list

I'm working on a collapsible Material UI feature and I want to ensure that when a user clicks on an item, it stays at the top of the list. For example, let's say we have a default list with items First, Second, and Third. When the user expands t ...

Implementing a "Halt on Failure" feature for Mochajs

Currently conducting tests using mochajs. var Mocha = require('mocha'); var mocha = new Mocha(); mocha.addFile('mocha/0000_1234.js'); mocha.addFile('mocha/0010_5678.js'); mocha.run(function(failures){ ... Any way to enable ...

Issues related to Angular button

As I embark on my journey of creating my very first Angular app, I've encountered a couple of stumbling blocks that have left me scratching my head in confusion. The issue arises when I try to include the following snippet within my template: <but ...

What is the best way to add an insert button to every row?

Take a look at the image provided. When I click on any register button, the last row is being inserted instead of the desired row. What I'm aiming for is this: when I click register, the entire selected row should be stored in a separate table. Whe ...

What is the best way to prompt a jQuery plugin to update the information it has retrieved?

I'm currently working on implementing jQuery Pagination along with a popup form. My question is, after saving data in the form, how can I refresh the Pagination plugin to only load the data for the current page without having to refresh the entire web ...

Top WebSocket/Perl solution for maximum effectiveness

Currently, the company I am employed at relies on Perl for all backend tasks. However, we are interested in implementing real-time communication between server processes and connected clients through web browsers. We currently use Apache as our web server ...

Issue: A malfunction was encountered during the rendering of the Server Components

Whenever I deploy my application to Vercel, I encounter the following error: production An error occurred in the Server Components render. The specific message is omitted in production builds to avoid leaking sensitive detail This issue only manifests on ...

React timer slide show malfunctioning

While I have some experience with React, I'm struggling with a seemingly simple problem that I just can't figure out. My goal is to cycle through an array of images and display the image at the current index. The console logs show the correct in ...

Tips for using Jquery to round up currency values

Is there a way to round up various currencies using jQuery? I have a specific requirement: 10.30 → 10 //Round down if below .5 10.60 → 11 //Round up if after .5 849.95 → 850 1,022.20 → 1022 ...

Utilizing a universal JavaScript array within the jQuery document(ready) function

After using jsRender to render the following HTML template, I encountered an issue with passing data values through jQuery selectors when submitting a form via AJAX. <div class="noteActions top" style="z-index: 3;"> <span onclick="noteAction(&a ...