Ensuring input validity and blocking changes if not compliant with AngularJS patterns

I am looking to create an input field that only accepts the values 1, 2, or 3. To achieve this, I am working on a directive that will prevent any changes to the model if it doesn't match these specific values.
For example, if the value is 1 and I try to change it to 5, it should remain as 1.

I have created a simple fiddle http://jsfiddle.net/kannix/Q5YKE/, but I suspect using $parsers might not be the correct approach.

app.directive('myvalidator', function () {
    return {
        require: 'ngModel',
        link: function (scope, elm, attrs, ctrl) {
            var validValues = [1, 2, 3];
            ctrl.$parsers.push(function (value) {
                if (validValues.indexOf(value) === -1){
                    //what to do here? should refuse wrong value and leave the old one
                }   
            });
        }
    }   

})

Answer №1

In order to restrict key presses based on a specific criteria, I recently created a custom directive for this purpose. This directive accepts a regExp object that validates the incoming key presses and only allows them if they meet the specified criteria:

// validation of keystrokes using the provided regExp
app.directive("regExpRequire", function() {

    var regexp;
    return {
        restrict: "A",
        link: function(scope, elem, attrs) {
            regexp = eval(attrs.regExpRequire);

            var char;
            elem.on("keypress", function(event) {
                char = String.fromCharCode(event.which)
                if(!regexp.test(elem.val() + char))
                    event.preventDefault();
            })
        }
    }

})

To use this directive in your template, you can specify the regExp pattern within the input element like so:

<input type="text" reg-exp-require="/^[a-zA-Z]$/">

For example, if you want to restrict input to only numbers 1, 2, or 3, you can use the following code:

<input type="text" reg-exp-require="/^[1-3]*$/">

Answer №2

If you want to enforce a certain pattern, consider using the ng-pattern-restrict directive.

To implement this feature in your project, you can download the library by visiting this link: Download Here. Once you have the library, simply add the directive to your input element like this:

<input type="text" pattern="[A-Za-z]+" ng-pattern-restrict />

For more information and updates, you can check out the GitHub repository at: AlphaGit/ng-pattern-restrict

Answer №3

If you want to prevent specific characters from passing through, you can listen to the keypress event and filter them out. Check out this example on Plunker

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

app.controller('MainCtrl', function($scope) {
  $scope.name = 'World';
  $scope.validValues = ['a','1','2'];
});

app.directive('myValidator', function ($parse) {
    return {
        scope: {
          validValues: '=validValues'
        },
        link: function (scope, elm, attrs) {
          elm.bind('keypress', function(e){
            var char = String.fromCharCode(e.which||e.charCode||e.keyCode), matches = [];
            angular.forEach(scope.validValues, function(value, key){
              if(char === value) matches.push(char);
            }, matches);
            if(matches.length == 0){
              e.preventDefault();
              return false;
            }
          });
        }
    }   
});

Answer №4

After encountering issues with Ian Haggerty's answer form code, I had to make some modifications and additions. The code initially worked fine, but when I started testing it in various ways, problems arose. Specifically, I was attempting to test for values less than 100, which resulted in unexpected outcomes.

One particular issue was that if I inputted 100 and then tried to add a decimal point to make it 10.0, the code did not recognize this as valid based on my regex (despite allowing up to two decimals). It seemed to always tack on the new character at the end of the string being evaluated, even when I inserted it in the middle.

To address this discrepancy, I implemented a change where the original value is saved on "keypress," and then on "keyup" (or alternatively, "change"), the new value is checked against the regex. If deemed invalid, it reverts back to the original value.

Although this method briefly updates the model, it allows for inserting characters in the middle or beginning of the input field while still ensuring accurate regex matching. For Angular 1.3, utilizing ng-model-options="{debounce:250}" may help mitigate this issue. Keeping any code reliant on model changes idempotent proves to be incredibly beneficial.

usage: <input ... validate-with="/^([\d]{1,2}\.[\d]{1,2}|\.?[\d]{1,2}|100)?$/" />

.directive("validateWith", [function(){
    return {
        restrict: "A",
        link: function($scope, $el, $attrs){
        var regexp = eval($attrs.validateWith);
            var origVal;
        
            // saving the current value before any changes are made
            $el.on("keypress", function(e){
                origVal = $el.val();
            });

            // validating the new value after changes are made
            // reverting to the original value if invalid
            $el.on("keyup", function(e){
                 if(!regexp.test($el.val())){
                    $el.val(origVal);
                }
            });
        }
    }
}]);

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

Managing ajax requests for lazy loading while scrolling through the middle of the window can be a challenging task. Here are some tips on

I have implemented Lazy loading in my Project. I found a reference at which explains how to make an ajax call after scrolling and image upload with slow mode without allowing scrolling until the loader is shown. The code snippet I am using is as follows: ...

Tips on refreshing a div using jQuery while maintaining the functionality of addEventListener

Hi, I am facing an issue with updating the "div" element. The refresh works fine, but after refreshing when I try to click on the updated "div", the addEventListener in my JavaScript code does not seem to work anymore. Can someone please explain why this i ...

Unraveling encoded characters in URLs using Node.js

When I try to send a cookie back using res.cookie(JSON.stringify({bar: "baz"}), the value that I get in return is %7B%22bar%22%3A%22baz%22%7D. How can I decode this in a Javascript setting like node.js? ...

Learn the art of closing an AngularJS accordion automatically when another accordion is opened within an AngularJS application

I have encountered an issue with the AngularJS accordion functionality. It seems that when I have multiple accordions, such as accordion-1, accordion-2, and accordion-3, they all open simultaneously if clicked on individually. My main concern is: How can ...

Error: Running the command 'yarn eg:'live-server'' is not a valid internal or external command

Currently, I am utilizing yarn v1.6.0 to manage dependencies. I have globally installed live-server by running the following command: yarn global-add live-server However, upon executing it as live server, I encounter the following error: 'live-ser ...

Toggle menu visibility when body is clicked

<script> $(".bg").on('click', function(e) { e.preventDefault(); $("#navMenu").removeClass('open'); $("#searchBar").removeClass('active'); }); </script> My goal is to togg ...

Effectively accessing the Templater object within a user script for an Obsidian QuickAdd plugin

I have developed a user script to be used within a QuickAdd plugin Macro in Obsidian. The Macro consists of a single step where the user script, written in JavaScript following the CommonJS standard, is executed. Within this script, there is a task to gene ...

The AJAX callback is unable to access the method of the jQuery plugin

I have a scenario where I am fetching data from an AJAX response and attempting to update a jQuery plugin with that value within the success callback: $.ajax({ url: '/some/url', type: 'GET', dataType: 'json', succ ...

Automatic Refresh and Search Functionality on PHP Page

Can anyone help with a problem I'm having trying to implement auto-reload on a page with a table in the form of rows that contain usernames? I am currently using the jQuery searchable plugin from here to search for usernames within the div. The websi ...

Utilizing hooks in node.js functions

Is there a way to apply before and after hooks on a function? I need these hooks to trigger whenever the function is called. While Express.js middleware concept works for routes, I require similar hooks for functions on the server side. function main(){ ...

Diverse Marker Selection on Google Maps Using Angular

I am utilizing Angular Google Map for rendering maps and Google Places for searching and displaying nearby locations as markers. My goal is to display different markers for different types of places. For example, if there are schools in the collection, I w ...

Creating personalized headers for WebSocket in JavaScript

I am currently in search of a straightforward method to utilize WebSocket with custom headers for a web application, utilizing PHP as the backend and js+vuejs for the frontend. My application needs to establish a connection with a WebSocket server based o ...

Using Angular.js to update the `ng-model` with the value of text.textContent

There is a javascript event that dynamically updates the value of an input var posx = event.target.querySelector('input.posx'); posx.value = event.dx; This code successfully updates the html: <input type="text" ng-model="posx" si ...

Is it possible to efficiently bring in NPM packages with their dependencies intact in Deno?

I stumbled upon a helpful post outlining how to incorporate NPM modules in Deno: How to use npm module in DENO? The catch is, the libraries used in the example have absolutely no dependencies. But what if I want to utilize a dependency like Axios (not th ...

`Count the number of rows needed to accommodate text line breaks within a div element`

Is there a method to determine the number of lines that text breaks into using the CSS property word-break: break-all? For example, if I have a div like this: <div>Sample text to check how many lines the text is broken into</div> And the corr ...

Deactivate CS:GO Dedicated Server using Node.js child_process

I've been attempting to manage multiple Counter Strike: Global Offensive dedicated servers programmatically. The process is running smoothly, however, I am facing a challenge in shutting it down completely. Upon starting the server, two processes are ...

What is the best way to transfer an id from one const to another in JavaScript?

I have 2 APIs that I am using to fetch data. The first API, called getDetails, is used to retrieve student details. Within these student details, there is an ID that needs to be fetched from the second API and displayed in the first API. The second API is ...

Stop or terminate all ongoing requests in AngularJS

When switching routes, I want to prevent any pending requests from the previous route in order to avoid issues where responses from the previous route interfere with data on the current route. This sometimes happens when responses from the previous route t ...

Guide on verifying Unicode input in JavaScript?

I am looking to create a form where the user can only input Khmer characters (Unicode characters) and display an alert if they input anything else. Khmer Name: <input type="text" class="namekh" name="namekh"> To achieve this, here is a snippet of m ...

The concept of inheriting directives/scopes

Just wondering if directives declared within a Component in Angular 2 automatically apply to its children Components. And when it comes to variables declared on the Component, do they get inherited by the children Components or must they be explicitly pa ...