Watching the scope.$watch item is not effective for fields within JavaScript objects

Struggling with observing the properties of JavaScript objects has been a challenge for me. I attempted to explain this issue in more detail here, but unfortunately, I haven't found a solution yet...

To elaborate on the problem further, you can find a working example here.

Below is the code snippet from my directive:

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

var ctrl = function($scope) {
        $scope.amount = '0.00';

        $scope.values = {
                amount: 0.00
        };
};

myApp.directive('currency', function($filter) {
    // Directive logic goes here
});

Here is how my HTML layout looks like:

<div ng-app="myApp">
    <div ng-controller="ctrl">
        {{amount}}<br>
        <input type="text" style="text-align: right;" ng-model="amount" currency separator="point" fraction-size="2"></input>
    </div>
</div>

The aim is to link the input value to the values.amount variable in the outer controller, however, the watch functionality within my directive seems to be malfunctioning...

The desired behavior should add extra zeros to the input when a user inputs a decimal point. For instance, if the initial value in the input field is "42" and the user adds a decimal point resulting in "42.", then two additional zeros should automatically append making it "42.00".

When using ng-model="amount" for data binding, the logic within the input element functions correctly, but the value of amount in the outer controller fails to update.

On the other hand, utilizing ng-model="values.amount" for binding prevents both the values.amount in the outer controller and the input element's logic from functioning properly.

My goal is to bind the input element to values.amount via ng-model="values.amount", despite encountering obstacles and inconsistencies with this approach.

If anyone can offer assistance or suggestions to resolve this dilemma, I would greatly appreciate it.

Answer №1

The issue arises due to the expression not functioning properly

scope[attrs.ngModel] = ...

In the scenario where amount is involved, it simply assigns to scope.amount. However, in the case of values.amount, it doesn't assign to scope.values.amount; rather, it assigns to the 'values.amount' property of the scope.

An alternative approach would be to utilize the $parse service as shown below.

var parsed = $parse(attrs.ngModel); // Parsing the expression
var currentValue = parsed(scope); // Evaluating the expression
parsed.assign(scope, 'newvalue'); // Assigning the expression

This solution should address the issue, although you might consider implementing parsers and formatters for a more elegant resolution. Instead of manually interpreting the model's value, you can manage viewing and updating through the ngModel controller that has been required, utilizing parsers and formatters to regulate conversion.

  • Fiddle with a minor fix
  • Fiddle showcasing parsers and formatters

Answer №2

After analyzing your issue, I have come up with the following solution:

1) Remove the directive scope
2) Include ngModel in the link function
3) Eliminate the unnecessary part of your code

scope[attrs.ngModel] = "0" + scope.separator;
for(var i = 0; i < scope.fractionSize; i++) {
   scope[attrs.ngModel] += "0";
};

Instead of using $watch, implement the following:

ngModel.$parsers.unshift(function(viewValue) {
   var pattern = /^\s*(\-|\+)?(\d*[\.,])$/;

   if (pattern.test(viewValue)) {
      viewValue += "00";
   };

   element.val(viewValue); // set the element's view value
   return viewValue; // set the new model value
});

I have tested this method and it is functioning correctly.

Check out the jsFiddle demo

For more information, refer to this post

Cheers!

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 is the best way to incorporate scripts into the HTML of my Google Apps Script or Google Sheets?

I'm having trouble getting my Apps Script-based HTML to include any scripts. My doGet function for the HtmlService is working fine: function doGet() { return HtmlService.createHtmlOutputFromFile('myhtmlfilename'); } Regardless of whether ...

Display/Collapse SELECT choices?

Consider this scenario : <select class="form-control" name="blah" ng-model="$ctrl.form.blah" ng-options="item.id as item.name group by item.etype | uppercase for item in $ctrl.opts"></select> My goal is to toggle the display of each GROUP b ...

Error: The function init is missing and cannot be found when the HTML button is clicked

In my attempt to utilize a function within HTML, I am encountering difficulty implementing it in an Angular TS component. An error message indicates that the code must be correct as it is being provided by TensorFlow. The snippet of code in question is as ...

The Parcel build was unsuccessful due to an error from @parcel/resolver-default: The file '../../../../../css/main.css' could not be loaded within the './src' directory

I utilize [email protected]. Whenever I attempt to load an external css or javascript file in my index.html, Parcel consistently fails to build with the following error: Build failed. @parcel/core: Failed to resolve './css/main.css' from & ...

Displaying information collected from a submission form

I am in the process of designing a cheerful birthday card and I need to transfer data from a form to the birthday card page. How can I take information from the first div (which contains the form) and display that data in the second div? <!DOCTYPE ...

Is there a way to manipulate the appearance of a scroller using JavaScript?

I'm intrigued by how fellow front-end developers are able to customize the scrollbar shape on a webpage to enhance its appearance. Can anyone guide me on using JavaScript to accomplish this? ...

Establish initial content for the specified div area

I need help setting page1.html to display by default when the page loads. Can you provide some guidance? Appreciate your assistance in advance. <head>     <title>Test</title>     <meta http-equiv="content-type" content="tex ...

Spring Security does not generate an error if the authorization header is missing following a login using AngularJS

Working on implementing HTTP Basic Authentication using Spring Security and Angular JS by including the Authorization header in $http headers: const headers = { authorization: "Basic " + btoa(this.login + ":" + this.password) }; this._$http.get("user ...

How come this state remains bound to this function even after it has been updated? - Using NextJS version 13.3.0 with React

A unique scenario arises where a button triggers the display of a modal created using a dialog HTML element. This button is stored in a state (thingsToRender) based on a condition, which is simulated within a useEffect hook. The issue lies in the fact that ...

What is the significance of storing the array length in the selection sort algorithm?

The code snippet below is taken from the Grokking algorithm book: const findSmallestIndex = (array) => { let smallestElement = array[0]; // Stores the smallest value let smallestIndex = 0; // Stores the index of the smallest value for (let i = 1 ...

Properly Selecting ng-options in AngularJS

When using AngularJS, I have the following code for a select tag: <select ng-init="getdata()" data-ng-model="ob.id" data-ng-options="level.id as level.desc for level in levels" data-ng-selected="ob.id == level.id"> <opt ...

Unable to fetch permissions for user:email via GitHub API

Currently, I am utilizing node-fetch to fetch an OAuth2 token from an OAuth2 GitHub App. The obtained token allows me to successfully retrieve user information from "https://api.github.com/user". However, I also require the email address, which necessitate ...

How to change a POST request to a PUT request using Express and keeping the

In my express app, I have set up two routes like this: router.post('/:date', (req, res) => { // if date exists, redirect to PUT // else add to database }) router.put('/:date', (req, res) => { // update date }) W ...

Display error messages upon submitting the form

I am currently working on an Angular 6 Form with validation. My main goal is to display error messages only after the form has been submitted. It is crucial that these messages remain constant while the user types in the input field. For instance, if a use ...

Learn the steps to send an email using CodeIgniter and troubleshoot any errors present in the provided code

<?php class Greetings extends CI_Controller { public function __construct() { parent::__construct(); $this->load->library('email'); // loading the email library } function display() { ...

Leverage the power of Meteor by incorporating templates to dynamically inject HTML based on an event

I am currently generating HTML using JQuery on an event. However, I believe a better approach would be to use templates in Meteor, especially if the HTML becomes more complex. Template.example.onRendered(function() { paper.on({ 'cell:mous ...

Update web page content using JavaScript onClick

I'm trying to figure out how to refresh my page every time a door is clicked. Can anyone help me with where I should add window.location.reload(); in my code? Here's the link to my pen: https://codepen.io/tacodestroyer/pen/bROpeQ function open ...

What is the best way to stop a current action when a new action is initiated?

My current setup involves an action creator that performs a costly calculation and triggers an action when the user inputs data in real-time. The challenge arises when multiple inputs are entered, as I want to avoid running the entire expensive calculati ...

Steps to deactivate a particular date on the Jquery UI datepicker:

I am struggling to disable specific dates (20, 21, 25 OCT 2015) using the JQuery UI datepicker. Despite my efforts, I have not been able to achieve the desired output. Below is a snippet of my code for reference. <!doctype html> <html lang="en" ...

Is there a way to change the projection of id in mongoose?

I have a microservice in Node.js, where I am using Mongoose to retrieve a document from my mongoDB. The document has multiple properties, but I only need to display 3 of them: The properties I want to display are '_id' as 'id', 'n ...