Matching the scope property in AngularJS directives

I am currently working on creating a custom directive that will perform regex validation on specific input fields. The goal is for the directive to determine which regex pattern to use based on an attribute provided in the input element.

Here is an example of how an input field using this directive might look:

<input required tabindex="5" regex-validation regex="validationRegex.zipRegex" ng-model="payment.zip" type="text" />

Below is a snippet from the directive implementation where it initializes a controller with various regex patterns and defines the directive itself. However, there seems to be an issue with scope.regex.test returning undefined.

module.controller('Controller', function($scope) {
    $scope.validationRegex = {
        americanExpressRegex: new RegExp(/^(?!3[47]).*$/),
        cvvRegex: new RegExp(/^[0-9]{3,4}$/),
        currencyRegex: new RegExp(/^[$]?\d{0,18}\.?\d{0,2}$/),
        cityRegex: new RegExp(/^[a-zA-Z]+(?:[\s-][a-zA-Z]+)*$/),
        zipRegex: new RegExp(/^[0-9]{5}(?:-[0-9]{4})?$/),
        phoneRegex: new RegExp(/^(\d(\s|\.|\-)?)?\(?\d{3}\)?(\s|\.|\-)?\d{3}(\s|\.|\-)?\d{4}$/),
        /* jshint ignore:start */
        emailRegex: new RegExp("^[A-Za-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[A-Za-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[A-Za-z0-9](?:[A-Za-z0-9-]*[A-Za-z0-9])?\.)+[A-Za-z0-9](?:[A-Za-z0-9-]*[A-Za-z0-9])?$"),
        /* jshint ignore:end */
        numberRegex: new RegExp(/^\d+$/),
        addressRegex: new RegExp(/^[A-Za-z0-9 \-_\.,]{0,55}$/),
        bankAccountRegex: new RegExp(/^[0-9]{1,17}$/),
        routingNumberRegex: new RegExp(/^((0[0-9])|(1[0-2])|(2[1-9])|(3[0-2])|(6[1-9])|(7[0-2])|80)([0-9]{7})$/)
    };
})
    .directive('regexValidation', [function () {
        return {
        scope: { regex: "=" },
        link: function (scope, element) {
            element.bind('change', function () {
                console.log(scope.regex);
                //grab the element we are working with into a jquery element
                var ele = $(element);

                //grab the element value for multiple future use
                var value = ele.val();

                //if we have a value check with regex
                if (value && !scope.regex.test(value)) {
                    ele.parent().addClass("error");
                }
                    //this will set the element back to how it was and check to see if all validation is
                    //complete
                else {
                    ele.parent().removeClass("error");
                }
            });
        }
    };
}]);

Answer №1

Forget about using jQuery and embrace Angular for better results.

Angular is designed to handle input changes and process them efficiently. Utilize Angular's pipeline to engage with the value instead of relying on event listeners.

Take a look at the ngModelController documentation here.

I have explained this concept in more depth along with a demonstration here.

If you are working with a recent version of Angular, make use of $validator. For older versions, opt for $parser. Instead of assigning a class to indicate the state, leverage ngModel's $error state. Here is an example to help you get started.

Live demo

.controller('myCtrl', function($scope) {

  $scope.foo = 'abc';
  // In this example, it will always be invalid
  $scope.fooValidity = false;

})

.directive('myDirective', function() {

  var directive = {
    scope: {
      isValid: '=myDirective'
    },
    require: 'ngModel',
    link: function($scope, $element, $attrs, $ngModel) {

      // "whatever" is the property that will be assigned on the ngModel $error object
      $ngModel.$validators.whatever = function(val) {
        // Write your validation logic here
        // Return true or false for valid / invalid
        return $scope.isValid;
      };

    }
  };

  return directive;

})

;

Markup:

<!-- Add the `error` class by using the model's error object -->
<!-- Note that Anuglar will add a `ng-invalid-whatever` class for you -->
<form name="myForm" ng-class="{error:myForm.fooInput.$error.whatever}">
  <input ng-model="foo" name="fooInput" my-directive="fooValidity">
  <p ng-show="myForm.fooInput.$error.whatever">It's invalid!</p>
</form>

Answer №2

It is generally not recommended to mix AngularJS and jQuery together. However, there is a way to validate input without using jQuery. You can check out a working demo of this method here.

All you have to do is pass your model and regular expression to the directive, and then test the regular expression on model update.

app.directive('regexValidation', [
  function() {
    return {
      scope: {
        regex: "=",
        model: '=ngModel'
      },
      link: function(scope, element, attr) {
        scope.$watch('model', function(newValue, oldValue) {
          if (!newValue || scope.regex.test(newValue)) {
            element.removeClass("error").addClass('valid');
          } else {
            element.addClass("error").removeClass('valid');
          }
        });
      }
    };
  }
]);

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

Updating table width using AngularJS/jQuery after completion of ajax request

One of my challenges involves a table that defaults to a specific width, such as 80% of its parent div. Initially, the table remains hidden using 'ng-if' until an ajax call is completed in this manner: This is reflected in the HTML code snippet ...

What is the best way to save information from an axios promise into my database on separate lines?

Having a technical issue and seeking assistance: Currently, I am encountering an issue with my axios request to the database. After successfully retrieving the data, I aim to display it in a select form. However, the response is coming back as one continu ...

The Socket.io application is facing deployment issues on the Heroku platform

I have developed a simple chat server using nodejs, socket.io, and express, and now I am attempting to deploy it on Heroku using my Git repository. However, when I access the Herokuapp website for my application (), the display is not as expected: Below i ...

How come my fixed navigation bar is appearing above my sticky navigation bar even though I positioned it at the bottom in the code?

My current project involves creating a sticky bar and fixed navbar using Bootstrap 5. I structured my code with one file for the sticky navbar and another file for the fixed navbar. The challenge I faced was having the fixed navbar overlap the sticky navba ...

Using Styled components and react-router-dom v6 to emphasize the active navigation link upon clicking

I'm just starting out with react and I am trying to figure out how to keep my hover style active while the current page is open. I think I need to set a condition but I am not sure how. const StyledLi = styled.li` `list-style: none; displa ...

Tips for concealing a particular button that shares the same class designation

Is there a way to create a function in vanilla JavaScript that can hide a specific button? <button class"btn">button 1 </button> <button class"btn">button 2 </button> <button class"btn">button 3 </button> Specifically, ...

Categorizing the types of dynamically retrieved object values

I've developed a unique class with two properties that store arrays of tuples containing numbers. Additionally, I've implemented a method called "getIndex" which dynamically accesses these properties and checks for duplicate number values within ...

I am curious to know why my jQuery when().then() function is firing before the completion of the ajax request in the when clause

I have a situation where I need to set an async callback because a function is fetching content from a remote location. Here's what I am currently doing: $.when( priv[box.view.renderWith](content, box.view.gadget_id) ).then(function(late) { conso ...

Unable to find the Popper component in Material UI

Material-UI version "@material-ui/core": "^3.7.0" I have a requirement to display Popper on hover over an element, but unfortunately, the Popper is not visible. This section serves as a container for the Popper component. import PropTypes from &apos ...

The Viadeo Social Toolbox seems to be encountering technical difficulties at the moment

I attempted to utilize a Viadeo Social Toolbox, specifically the Viadeo Share Button, but it seems to be malfunctioning in certain browsers? I came across some outdated viadeo share URLs like this: http://www.viadeo.com/shareit/share/?url=${url}&title ...

What is the method for adjusting the size of text while rendering on a canvas?

When it comes to scaling text with CSS transform scale, for instance: transform: scale(2, 4); fontSize: 20px // Is including fontSize necessary? I also have the task of displaying the same text on a canvas element. function draw() { const ctx = document ...

JavaScript/AJAX Functionality Only Operates Correctly During Debugging

I am currently facing an issue with dynamically populating a website. The code works perfectly when I step through it, but it fails to work as intended on page load. Here is the relevant code snippet: <body onload="populate_all(string)";> function ...

Performing an OAuth2 request using AngularJS

I'm attempting to utilize AngularJS to request an access token, but I am uncertain about the proper approach. Below is the curl request that I have: curl -X POST -d "grant_type=password&username=&password=&scope=read" -u":" http://l ...

Believing that members possess a certain role when they actually do not

const { Discord, MessageEmbed } = require("discord.js"); module.exports = { name: "ban", description: "bans user from guild", execute(client, message, cmd, args, Discord) { const member = message.mentions.u ...

Difficulty encountered while implementing mouseover event listener for an SVG component

I'm having trouble triggering an event for an svg element. Here's the link to my jsfiddle example: https://jsfiddle.net/r1ahq5sa/ Here's the HTML code: <div class="row"> <div class="col-md-8"> <svg class="video-nav-bar ...

Does anyone have any insight on why I can't seem to remove an item from my list of tasks?

Having trouble with my React todo list. After submitting, the list item looks fine. I expect to be able to delete it by clicking on the item, but nothing happens. When I try to add another item, the page refreshes and all items are removed. The console ...

Combine arrays if the objects inside them are identical

Is anyone online? I need help. I have an array structured like this. var array = [ { roomNumber: 'R01', roomType: 'Deluxe', basic_facilities: 'Hot Water', additional_facilities: 'Iron' }, { roomNumber: 'R01 ...

When dynamically adding input fields in Bootstrap, there is a smaller gap between inline inputs

When adding a new list item dynamically in a modal using jQuery append, the spacing in the first li element seems to have a larger gap between the input fields compared to the rest that are added later. Even after checking the developer tools and confirmin ...

When trying to reference a vanilla JavaScript file in TypeScript, encountering the issue of the file not being recognized

I have been attempting to import a file into TypeScript that resembles a typical js file intended for use in a script tag. Despite my efforts, I have not found success with various methods. // global.d.ts declare module 'myfile.js' Within the re ...

Received an unexpected argument count of 1 instead of the expected 0 while passing a function as a prop to a child component

I transferred the deleteImgfunc function from the insertFarmDiaryDetail component to the InsertFarmDiarySubPage component, which acts as a child component. DeleteImgfunc is a parameter-receiving function. Despite creating an interface and defining paramet ...