Home > Software engineering >  How to create a directive in Angular to mask us phone number without changing model?
How to create a directive in Angular to mask us phone number without changing model?

Time:07-07

I have a directive in Angular Js that masks phone numbers to US format (xxx) xxx-xxxx ,

const myApp = angular.module("myApp", []);

myApp.controller("MyCtrl", function ($scope) {
  $scope.validateModel = function name(params) {
  };
});

// Excercise 1
myApp.directive("canadaPhone", function ($filter, $browser) {
  return {
    require: "ngModel",
    link: function ($scope, $element, $attrs, ngModelCtrl) {
      const listener = function () {
        var value = $element.val().replace(/[^0-9]/g, "");
        $element.val($filter("tel")(value, false));
      };

      // This runs when we update the text field
      ngModelCtrl.$parsers.push(function (viewValue) {
        return viewValue.replace(/[^0-9]/g, "").slice(0, 10);
      });

      // This runs when the model gets updated on the scope directly and keeps our view in sync
      ngModelCtrl.$render = () => {
        $element.val($filter("tel")(ngModelCtrl.$viewValue, false));
      };

      $element.bind("change", listener);
      $element.bind("keydown", (event) => {
        const key = event.keyCode;
        // If the keys include the CTRL, SHIFT, ALT, or META keys, or the arrow keys, do nothing.
        // This lets us support copy and paste too
        if (key == 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) {
          return;
        }
        $browser.defer(listener); // Have to do this or changes don't get picked up properly
      });

      $element.bind("paste cut", () => {
        $browser.defer(listener);
      });
    },
  };
});
myApp.filter("tel", function () {
  return function (tel) {
    if (!tel) {
      return "";
    }

    let value = tel.toString().trim().replace(/^\ /, "");

    if (value.match(/[^0-9]/)) {
      return tel;
    }

    let city, number;

    switch (value.length) {
      case 1:
      case 2:
      case 3:
        city = value;
        break;

      default:
        city = value.slice(0, 3);
        number = value.slice(3);
    }

    if (number) {
      if (number.length > 3) {
        number = number.slice(0, 3)   "-"   number.slice(3, 7);
      } else {
        number = number;
      }

      return ("("   city   ") "   number).trim();
    } else {
      if (city) {
        return "("   city;
      } else {
        return "";
      }
    }
  };
});

// Excercise 2
<!doctype html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <title>SurexApp</title>
  <base href="/">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
  <!-- CSS only -->
  <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet"
    integrity="sha384-0evHe/X R7YkIZDRvuzKMRqM OrBnVFBL6DOitfPri4tjfHxaWutUpFmBp4vmVor" crossorigin="anonymous">


</head>

<body>

  <!-- Angular JS -->
  <div ng-app="myApp" ng-controller="MyCtrl">

    <div >
      <!-- <h1> Angular Js Excercises</h1> -->


      <!-- Excercise 1 -->
      <div>
        <label for="excercise1">Angular Js Excercise 1</label>
        <input type="text" ng-model="phone" id="excercise1" placeholder="(987) 654-3210" ng-change="validateModel()" canada-phone>
        <div> Model: {{phone}}</div>
      </div>


    </div>


  </div>

  <app-root></app-root>


</body>

</html>

How can I recreate the same directive in Angular ( typescript ) ?

I created a directive from another post but It alters the model too, My Requirement is that it should visually show as (xxx) xxx-xxxx, but the model value should not be changed i.e. it should be xxxxxxxxxx

My Stackblitz demo -> enter image description here

Working example: https://stackblitz.com/edit/ngx-mask-xrpqce?file=src/app/app.component.html

  • Related