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/bootstrap@5.2.0-beta1/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 class="container app-container"> <!-- <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 -> https://stackblitz.com/edit/angular6-phone-mask-7tglv9?file=app%2Fapp.component.html
Advertisement
Answer
Good comments under the question. If the end result is the need to mask the phone number, being able to change the number but still keep the unmasked number in the control, then I would recommend using a package for this. Complex template operations on input and form is no easy feat. https://www.npmjs.com/package/ngx-mask
Trick here is to use X
with custom pattern. Idea from: https://github.com/JsDaddy/ngx-mask/issues/547#issuecomment-548596982
Html:
<div> TEL: <input matInput type="text" [(ngModel)]="tel.value" [hiddenInput]="true" mask="(000) 000-0000" [patterns]="pattern" /> </div> <div>TEL model: {{ tel.value }}</div>
TS:
@Component({ selector: 'my-app', templateUrl: './app.component.html', styleUrls: ['./app.component.css'], }) export class AppComponent { pattern = { '0': { pattern: new RegExp('\d'), symbol: 'X' } }; tel = new FormControl('4045912375'); }
Working example: https://stackblitz.com/edit/ngx-mask-xrpqce?file=src%2Fapp%2Fapp.component.html