What is the best way to implement dynamic variables in ng-model-options?

I am experiencing an issue with the ng-model-options not updating as expected. For instance, if you input 4:00 pm in both time fields in the snippet below, you'll notice that the UTC output differs - the first is 6 and the second is 8. This behavior is intentional. However, the problem arises when I select +0800 from the dropdown. This action should update the timezone variable, causing both time fields to display 8 when 4:00 pm is entered, as the first field should now be using the timezone variable specified in its ng-model-options. Unfortunately, this is not happening. Even after clearing the input and manually re-entering the time, the incorrect time is still displayed. How can I ensure that the timezone option in the ng-model-options utilizes a variable like timezone that is subject to change dynamically?

See the issue below:

angular.module('myApp', [])
  .controller('myController', function($scope) {
    $scope.timezones = ['+1000', '+0800'];
    $scope.timezone = $scope.timezones[0];
    
    $scope.time = '';
    $scope.eightTime = '';
  });

angular.element(document).ready(() => {
  angular.bootstrap(document, ['myApp']);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.11/angular.min.js"></script>
<div ng-controller="myController">
  <select ng-model="timezone">
    <option ng-repeat="timezone in timezones" ng-value="timezone">{{timezone}}</option>
  </select>
  <p>Selected Timezone: {{timezone}}</p>

  <input type="time" ng-model="time" ng-model-options='{timezone: timezone}' />
  <p>Using dropdown T.Z of '{{timezone}}': {{time.getUTCHours()}}</p>

  <input type="time" ng-model="eightTime" ng-model-options="{timezone: '+0800'}">
  <p>Hardcoded '+0800': {{eightTime.getUTCHours()}}</p>
  <!-- ^^^ This should be the output when '+0800' is selected in the dropdown -->
</div>

Answer №1

Based on information from the official documentation:

The ngModelOptions expression is evaluated only once during the linking of the directive; it is not continuously monitored for changes. However, it is still possible to customize the options for a single ngModel.NgModelController instance by utilizing

NgModelController#$overrideModelOptions()

To ensure it works for you, I made some adjustments to the code :)

angular.module('myApp', [])
  .controller('myController', function($scope) {
    $scope.timezones = ['+1000', '+0800'];
    $scope.timezone = $scope.timezones[0];
    $scope.time = '';
    $scope.eightTime = '';
    
    $scope.$watch('timezone',function(v){
        $scope.time = '';
        $scope.myForm.time.$overrideModelOptions({'timezone': $scope.timezone}); 
        // this will update the options whenever the timezone is changed.
    })
    
  });

angular.element(document).ready(() => {
  angular.bootstrap(document, ['myApp']);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
<div ng-controller="myController">
  <form name="myForm">
    <select ng-model="timezone" ng-options="timezone for timezone in timezones">
    </select> <!-- ng-options is the correct way to provide options to the select dropdown -->
    <p>Selected Timezone: {{timezone}}</p>

    <input type="time" name="time" ng-model="time" ng-model-options='{timezone: timezone}' />
    <p>Using dropdown T.Z of '{{timezone}}': {{time.getUTCHours()}}</p>
    <input type="time" ng-model="eightTime" ng-model-options="{timezone: '+0800'}">
    <p>Hardcoded '+0800': {{eightTime.getUTCHours()}}</p>
    <!-- ^^^ This should be the output when '+0800' is selected in the dropdown -->
  </form>
</div>

For more information on $overrideModelOptions, visit - https://docs.angularjs.org/api/ng/type/ngModel.NgModelController#$overrideModelOptions

Update:

You can achieve this by creating a separate directive.

**For versions >1.6.2 **

angular.module('myApp', ['kcd.directives'])
  .controller('myController', function($scope) {
    $scope.timezones = ['+1000', '+0800'];
    $scope.timezone = $scope.timezones[0];
    $scope.time = '';
    $scope.eightTime = '';
    
});
angular.module('kcd.directives', []).directive('kcdRecompile', ['$parse', function($parse) {
  'use strict';
  return {
    transclude: true,
    link: function link(scope, $el, attrs, ctrls, transclude) {
      var previousElements;

      compile();

      function compile() {
        transclude(scope, function(clone, clonedScope) {
          previousElements = clone;
          $el.append(clone);
        });
      }

      function recompile() {
        if (previousElements) {
          previousElements.remove();
          previousElements = null;
          $el.empty();
        }

        compile();
      }

      scope.$watch(attrs.kcdRecompile, function(_new, _old) {
        var useBoolean = attrs.hasOwnProperty('useBoolean');
        if ((useBoolean && (!_new || _new === 'false')) || (!useBoolean && (!_new || _new === _old))) {
          return;
        }
        if (useBoolean) {
          $parse(attrs.kcdRecompile).assign(scope, false);
        }
        recompile();
      }, typeof $parse(attrs.kcdRecompile)(scope) === 'object');
    }
  };
}]);

angular.element(document).ready(() => {
  angular.bootstrap(document, ['myApp']);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.0/angular.min.js"></script>
<div ng-controller="myController">
  <div kcd-recompile="timezone">
    <select ng-model="timezone" ng-options="timezone for timezone in timezones">
    </select> <!-- ng-options is the correct way to provide options to the select dropdown -->
    <p>Selected Timezone: {{timezone}}</p>

    <input type="time" name="time" ng-model="time" ng-model-options="{timezone: timezone}"/>
    <p>Using dropdown T.Z of '{{timezone}}': {{time.getUTCHours()}}</p>
    <input type="time" ng-model="eightTime" ng-model-options="{timezone: '+0800'}">
    <p>Hardcoded '+0800': {{eightTime.getUTCHours()}}</p>
    <!-- ^^^ This should be the output when '+0800' is selected in the dropdown -->
  </div>
</div>

Related Post - Dynamically Setting ngModelOptions in Angular

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

Utilizing jQuery to apply multiple classes simultaneously?

What is the purpose of allowing multiple classes to be added? Is there any real benefit to this feature or is it just unnecessary complexity? I attempted to utilize it, but found that it serves no practical function. ...

Leverage the function's argument to serve as the key and

Presented is a function that accepts key, value, and callback as arguments. The function has been designed with the principles of DRY (Don't Repeat Yourself) in mind. Its main purpose is to perform a lookup to an Elasticsearch endpoint using the key/v ...

NextJS encountered a JavaScript heap out of memory issue

While developing my NextJs project, it suddenly encountered an unknown issue that resulted in the following error message being logged: <--- Last few GCs ---> [8728:000001A567CE5290] 8719226 ms: Mark-sweep (reduce) 1827.7 (1944.2) -> 1827.7 (189 ...

Trouble with top attribute functionality within animate function

Why does the top attribute in the animate function of JQuery not seem to work, while the opacity attribute functions correctly in the code snippet below? $(function() { $(window).on('scroll', function() { ...

Establish a jQuery cookie to store language preferences

On the website I oversee, I want to implement a way to set a cookie for the selected language. The only information available is that users choose their preferred language by clicking on a dropdown menu with distinct classes assigned to each language - on ...

What is the appropriate way to retrieve an array that has been stored in the this.state property?

https://i.stack.imgur.com/y9huN.jpgAs a newcomer to react, I have been exploring the react documentation on making Ajax calls. While the docs make it seem simple to retrieve JSON information and set it to a state variable, I've encountered some challe ...

Tips on accessing InnerText with VUEJS

I'm struggling with displaying the innerText generated by my generatePseudonym() function in a modal dialog. To better illustrate, here is a screenshot of what I mean: https://i.sstatic.net/pEl5P.png I am aiming to show the output Anastasia Shah as th ...

CORS blocked in the live environment

error + whole page As a newcomer to JavaScript, I recently deployed my project. During development, everything was functioning well. However, I am now facing an issue with CORS when attempting to sign in (registration works without any problems, confirmin ...

What causes async / await function to be executed twice?

I am currently developing a node.js application using express. In this project, I have implemented a regular router that performs the following tasks: It searches for the myID in the DB, If the myID is found, it attempts to execute the addVisit() functio ...

Javascript continues to execute even after the designated element has been eliminated or substituted

I'm currently working on a WordPress auction site using WooCommerce that needs a countdown timer to display when a specific product auction is ending. Below is the JavaScript code for the countdown timer: const getElem = elem => document.q ...

Refresh a specific div element within an HTML file when the AJAX call is successful

After uploading the image, I want it to be displayed right away. To achieve this, I am looking to refresh the div with id="imagecontainer" within the success function of my ajax call. However, I would prefer not to rely on ("$id").load("href") as it does ...

Exporting a node express app for chai-http can be done by creating a module

I have set up an express app with multiple endpoints and am currently using mocha, chai, and chai-http for testing. Everything was running smoothly until I added logic for a pooled mongo connection and started creating endpoints that rely on a DB connectio ...

Creating a seamless integration of elements from two Vue.js components

As I work on developing the checkout page for an e-commerce app, I encounter the need to display a list of OrderItems from the database, each with its price and quantity. These items can be selected and grouped together. Additionally, I must also include a ...

What is the best way to generate conditional test scenarios with Protractor for testing?

Currently, there are certain test cases that I need to run only under specific conditions. it ('user can successfully log in', function() { if(siteAllowsLogin) { ..... } The problem with the above approach is that even when sitesNo ...

When the user clicks on an organizational chart, a new organizational chart will appear in a modal popup

Currently, I am developing a project with Highcharts where I have a specific requirement to display a modal popup when a node on an org chart is clicked. The popup should also contain another org chart. Below is the code snippet I am working with: [link to ...

Changing the color of an open Bootstrap 4 accordion panel when the page loads

I am looking to emphasize the panel that the user has opened. If a user clicks the button in the card header, the background turns red, which is working smoothly as demonstrated in the code snippet. In certain scenarios, the first panel is open by default ...

Encountering problems with parsing a lengthy JSON file

Can you spot the issue here? let stringinsta = JSON.parse({ "access_token":"129261**5ea59a4da481c65", "user":{ "username":"carlos_bellesso", ...

Deactivating controls while displaying the loading bar in AngularJS

I'm currently working on a web application using AngularJS. I want to incorporate a loading bar to signify long data load times from the server. To replicate heavy data loads, I am utilizing $timeout to trigger the loadbar when the operation begins a ...

Adding individual buttons at the bottom of each data row using Jquery: A step-by-step guide

Currently, I am receiving data from a backend using an AJAX GET method and displaying it in a list in HTML. However, I am facing some issues with including buttons within the list and making them functional by utilizing delegate and other methods. I would ...

Guide on how to create a promise with entity type in Nest Js

I am currently working on a function that is designed to return a promise with a specific data type. The entity I am dealing with is named Groups and my goal is to return an array of Groups Groups[]. Below is the function I have been working on: async filt ...