Create an AngularJS directive that formats the model value for visual display, while retaining the original value in the model

I am facing a challenge in building an AngularJS directive for a currency textbox. The directive should take values (amount and currency code) from the model in the scope and then apply currency formatting to it. I am struggling to build this directive using ngModelController's parsers and formatters.

The issue I am encountering is that the parser is called first, but the modelValue is undefined because the data has not been returned from the server yet. How can I ensure that the parser is called only when the model is populated? Also, my calculation depends on the currency code retrieved from the database. How can I incorporate these two values in the parser?

I am unsure of how the render function should be implemented in my case.

Below is the HTML snippet:

<numericbox caption="RecurringAmount" controltype="currency" currencycode="{{Model.CurrencyCode}}" value="{{Model.RecurringAmount}}" />

And here is the TypeScript directive code:

export class NumericTextbox
    {
        constructor ()
        {
        var directive: ng.IDirective = {};
        directive.restrict = "E";
        directive.require = '^ngModel';
        directive.replace = true;
        directive.template = '<input type="text" />';
        directive.scope = true;

        directive.link = function ($scope: any, element: JQuerySE, attributes: any, ngModel: ng.INgModelController) {

            var injector = angular.element(document.getElementById('app')).injector();

            var currencyCacheService: CurrenciesCacheService;
            currencyCacheService = injector.get('currenciesCacheService');

            var currency = new Currency();
            var currencySymbol: string;

            ngModel.$formatters.push(function (modelValue) {

                if (modelValue) {
                    var amount: number = modelValue || 0;
                    var currencyCode: string = attributes.currency || "";

                    if (currencyCode) {
                        currency = currencyCacheService.GetItem(currencyCode);
                        currencySymbol = currency.CurrencySymbol || currency.ISOCurrencyCode;

                        var formattedNumber = accounting.formatMoney(modelValue,
                            currencySymbol,
                            currency.NumberDecimalDigits,
                            currency.CurrencyGroupSeparator,
                            currency.CurrencyDecimalSeparator);

                        return formattedNumber;
                    }

                    return modelValue;
                }

                return 0;
            });

            ngModel.$parsers.push(function (viewValue: string) {
                if (attributes.currenycode) {
                    var num = viewValue.substring(attributes.currenycode.len, viewValue.length - attributes.currenycode.len);
                    return num;
                }

                return viewValue;
            });

            $scope.$watch(function () {
                var amount: any = {};
                amount.currencycode = attributes.currencycode;
                amount.value = attributes.value;
                return amount;
            }, function (newVal, oldVal, scope) {
                debugger;
                    if (newVal != oldVal) {
                        var amount: number = newVal.value || 0;
                        var currencyCode: string = newVal.currencycode || "";

                        ngModel.$setViewValue({ num: amount, curr: currencyCode });
                    }
            });

            ngModel.$render = function () {
                //$scope.value =
                console.log(ngModel.$viewValue);
            };
        }    
            return directive;
        }
    }

This directive code is written in TypeScript.

Answer №1

In order to modify the appearance of a value, it is essential to consider using a filter instead of a directive. Here's an example:

<span>product.price|formatCurrency</span>

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

Retrieve a specified child object within its parent object using a string identifier

I have a situation where I need to create a JavaScript function that can extract a child object from a parent object based on a specific string identifier. Here is an example of what I'm looking for: function findChild(parent, name) { return par ...

The Vue component appears to be missing from the HTML code

I recently began learning Vue.js in school, and for my first assignment I need to print a h2 from a Vue component. However, I am having trouble getting it to work. Below is the code for the Vue component that I have created. var app = new Vue({ ...

How can I test for equality with an array item using v-if in Vue.js?

Currently, I am facing a challenge in my Vue.js project where I need to determine if a number is equal to an element within an array. Here is the code snippet that I am working with: <div v-if="someValue != arrayElement"> // </div> I am st ...

Exploring the Power of Multiple FindOne Queries in MongoDB

I have been working on expanding the data fields returned by our API. Currently, the API retrieves student information using the find method, and also includes some project details by retrieving the student info and using findOne to obtain information abou ...

Adding x days to a Unix timestamp can be achieved by converting the Unix timestamp

Currently, I have the following code snippet: let currentTS = Math.floor(+new Date() / 1000) This code successfully retrieves the current date in a unix timestamp. However, my goal now is to append an additional 14 days to this unix timestamp. Could some ...

Utilizing React to implement a search functionality with pagination and Material UI styling for

My current project involves retrieving a list of data and searching for a title name from a series of todos Here is the prototype I have developed: https://codesandbox.io/s/silly-firefly-7oe25 In the demo, you can observe two working cases in App.js & ...

Uninterrupted jQuery AJAX calls

I have a scenario where I need to periodically update an image on my view using ajax every 10 seconds. Any suggestions on how I can achieve this? Appreciate the help. ...

HighStocks should show categories instead of dates

The zoom function in HighCharts is what drew me to it initially. Everything was working perfectly until I encountered an issue that I can't seem to resolve. Here's my code snippet: http://jsfiddle.net/ma50685a/16/ $(function() { // Crea ...

What steps should I take in modifying my existing code to use jQuery to set my div to a minimum height rather than a fixed height?

Could someone assist me in adjusting my div to have a min-height instead of a regular height? Whenever I click on the "Learn more" button, it extends past my div because the function is designed to set a specific height rather than an equal height. $.fn.e ...

Exploring Node.js with the power of EcmaScript through Javascript Mapping

I am currently using Map in NodeJS version 0.10.36 with the harmony flag enabled. While I am able to create a map, set and retrieve data successfully, I am facing issues with other methods such as size, keys(), entries(), and forEach as they are returning ...

When attempting to render mathML in a canvas on Safari, the image load callback does not properly trigger, resulting in

I am currently working on rendering mathML into an HTML5 canvas. One suggestion I received was to embed the mathML as an SVG foreign object, render it into an image, and then display the image within the canvas. However, this method works fine in Firefox ...

I'm running into an issue where I am unable to retrieve a variable from a separate

Struggling to populate a dropdown menu as I keep encountering an undefined error for all currencies when trying to reference them. A third party provided me with this code to simply fill the dropdown and make some text edits, but I'm puzzled as to wh ...

What is the best way to link this interval service with a view component?

Exploring the AngularJS documentation for $interval, I came across an interesting example demonstrating how to utilize $interval in a controller to create a user-friendly timer in a view. The official example code can be found on the angularJS documentatio ...

Displaying all API data by default in Vue.js, even with filters, sorting, and search enabled - how can it be done?

I am currently utilizing Vue.js version 3 and below is the code snippet: <template> <h5>List of Products</h5> <h3>Filter</h3> <button v-on:click="resetOptions">Reset</button> & ...

How to simultaneously play a sound and display an alert message using JavaScript

My JavaScript code attempts to play a sound and then display an alert, but the alert always shows up first. When I click 'ok', the sound plays. How can I make it so that the sound plays before the alert appears? <script> function play() { ...

How can I pass props from a custom _app.js file to the <Navbar> component in Next.js?

How do I go about passing props to a Navbar component that will be included under the Head component? Although I successfully passed props in the index.js page using getServerSideProps, it seems to not work properly in the _app.js file. import ".. ...

I am facing difficulties in installing the necessary node modules for my Angular project

After attempting to run npm install, an error message is displayed towards the end: error syscall unlink 22396 error The operation was rejected by your operating system. 22396 error It's possible that the file was already in use (by a text editor or ...

Chess.js TypeScript declaration file for easy implementation

Currently, I am delving into learning typescript and have taken up the challenge of crafting a declaration file for the chess.js library. However, it seems that I am struggling to grasp the concept of creating one. Whenever I attempt to import the library ...

Troubleshooting the injection of filters in AngularJS Karma test setup

After diving into AngularJS, I've reached the point where writing tests is essential. However, I'm encountering some challenges from the get-go. Here's my karma config file: module.exports = function(config) { config.set({ basePath: ...

Creating a dynamic drag-and-drop layout in React using react-grid-layout

Utilizing the react-grid-layout package for implementing drag-drop and resize components, I have successfully achieved the functionality outlined in the documentation. Description of My Issue My challenge lies in creating a dynamic UI where the layout is ...