24

Ich verwende diese Angular Directive, um Telefonnummern in einem Eingang zu (999) 999-9999 zu formatieren. Dies funktioniert großartig, bis ein Benutzer einen Fehler macht und die eingegebene Telefonnummer ändert.Verhindern, dass zusätzliche Zeichen eingegeben werden

können Sie dieses Problem replizieren, indem Sie den Code unten ausgeführt wird und die folgenden Aktionen ausführen:

• die Nummer Telefon Geben Sie (555) 123-4567
• Setzen Sie den Cursor nach dem 4 Charakter und löschen.
• Geben Sie 0 zweimal ein.

Sie können sehen, dass die 0 zweimal hinzugefügt und das 7 Zeichen gelöscht wird.

Ein weiteres Problem ist, wenn ein Benutzer versucht, das 1 Zeichen zu löschen und zu ändern. Ihr Cursor wird bis zum Ende der Eingabe gedrückt.

Ich bin sicher, dass dies auf ein Problem mit dem Phonenumber-Filter zurückzuführen ist, aber ich bin mir nicht sicher, wie ich das angehen soll.

function MyCntl($scope) { 
 
    $scope.myModel = {}; 
 
    $scope.myPrompt = "Input your phonenumber here!"; 
 
} 
 

 
var phonenumberModule = angular.module('phonenumberModule', []) 
 
    
 
\t .directive('phonenumberDirective', ['$filter', function($filter) { 
 
\t \t /* 
 
\t \t Intended use: 
 
\t \t \t <phonenumber-directive placeholder='prompt' model='someModel.phonenumber'></phonenumber-directive> 
 
\t \t Where: 
 
\t \t \t someModel.phonenumber: {String} value which to bind only the numeric characters [0-9] entered 
 
\t \t \t \t ie, if user enters 617-2223333, value of 6172223333 will be bound to model 
 
\t \t \t prompt: {String} text to keep in placeholder when no numeric input entered 
 
\t \t */ 
 
    
 
\t \t function link(scope, element, attributes) { 
 
    
 
\t \t \t // scope.inputValue is the value of input element used in template 
 
\t \t \t scope.inputValue = scope.phonenumberModel; 
 
    
 
\t \t \t scope.$watch('inputValue', function(value, oldValue) { 
 
\t \t \t \t 
 
\t \t \t \t value = String(value); 
 
\t \t \t \t var number = value.replace(/[^0-9]+/g, ''); 
 
\t \t \t \t scope.phonenumberModel = number; 
 
\t \t \t \t scope.inputValue = $filter('phonenumber')(number); 
 
\t \t \t }); 
 
\t \t } 
 
\t \t 
 
\t \t return { 
 
\t \t \t link: link, 
 
\t \t \t restrict: 'E', 
 
\t \t \t scope: { 
 
\t \t \t \t phonenumberPlaceholder: '=placeholder', 
 
\t \t \t \t phonenumberModel: '=model', 
 
\t \t \t }, 
 
\t \t \t //templateUrl: '/static/phonenumberModule/template.html', 
 
\t \t \t 
 
      template: '<input name="phonenumber" ng-model="inputValue" type="tel" class="phonenumber" placeholder="{{phonenumberPlaceholder}}" title="Phonenumber (Format: (999) 9999-9999)">', 
 
\t \t }; 
 
\t }]) 
 
    
 
\t .filter('phonenumber', function() { 
 
\t  /* 
 
\t  Format phonenumber as: c (xxx) xxx-xxxx 
 
\t  \t or as close as possible if phonenumber length is not 10 
 
\t  \t if c is not '1' (country code not USA), does not use country code 
 
\t  */ 
 
\t  
 
\t  return function (number) { 
 
\t \t  /* 
 
\t \t  @param {Number | String} number - Number that will be formatted as telephone number 
 
\t \t  Returns formatted number: (###) ###-#### 
 
\t \t  \t if number.length < 4: ### 
 
\t \t  \t else if number.length < 7: (###) ### 
 
    
 
\t \t  Does not handle country codes that are not '1' (USA) 
 
\t \t  */ 
 
\t   if (!number) { return ''; } 
 
    
 
\t   number = String(number); 
 
    
 
\t   // Will return formattedNumber. 
 
\t   // If phonenumber isn't longer than an area code, just show number 
 
\t   var formattedNumber = number; 
 
    
 
\t \t \t // if the first character is '1', strip it out and add it back 
 
\t \t \t var c = (number[0] == '1') ? '1 ' : ''; 
 
\t \t \t number = number[0] == '1' ? number.slice(1) : number; 
 
    
 
\t \t \t // # (###) ###-#### as c (area) front-end 
 
\t \t \t var area = number.substring(0,3); 
 
\t \t \t var front = number.substring(3, 6); 
 
\t \t \t var end = number.substring(6, 10); 
 
    
 
\t \t \t if (front) { 
 
\t \t \t \t formattedNumber = (c + "(" + area + ") " + front); \t 
 
\t \t \t } 
 
\t \t \t if (end) { 
 
\t \t \t \t formattedNumber += ("-" + end); 
 
\t \t \t } 
 
\t \t \t return formattedNumber; 
 
\t  }; 
 
\t });
.phonenumber { 
 
    min-width: 200px; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> 
 

 
<div ng-app="phonenumberModule" ng-controller="MyCntl"> 
 
    <p>phonenumber value: {{ myModel.phonenumber }}</p> 
 
    <p>formatted phonenumber: {{ myModel.phonenumber | phonenumber }}</p> 
 
    <form name="phoneForm"> 
 
     <phonenumber-directive placeholder="myPrompt" model='myModel.phonenumber'></phonenumber-directive> 
 
     <div ng-show="phoneForm.phonenumber.$error.minlength"> 
 
      <p>Enter a valid phone number</p> 
 
     </div> 
 
    </form> 
 
</div>

+0

Was haben Sie versucht, das zu beheben? – smnbbrv

+0

'ng-show =" phoneForm.phonenumber. $ Error.minlength "" Diese letzte Klammer wirft einen Fehler auf. – spenibus

+0

@spenibus Korrigiert. Obwohl das nicht der Grund meines Problems war. Danke für die Köpfe hoch. – floatleft

Antwort

1

Können Sie überprüfen Plunker bitte ... ich hoffe, das ist, was u wollen ..

http://plnkr.co/edit/0IBJBRb2JtvZnq6PtBiV?p=preview

Maskierung und regex Unterstützung .. (beta) Verbrauch: # für beide, ein für Zeichen, 9 ist für Zahlen ... (Maskenfilter funktioniert nicht als angenommen wird es überprüfen.

<maskinput ng-mask-model="value" ng-mask="9 (999) 99-9999" ng-mask-regex="[^0-9]+"></maskinput> 
+2

hat immer noch eine Menge Bugs mit Auswahlwiederherstellungen ... –

+0

muss auf Tastendruck arbeiten, um Bugs mit Schalter zu beheben ... ich weiß nicht, welche Benutzer beheben müssen .. Bugs behoben werden können. Hauptprobleme sind bekommen und Cursor einstellen Position und es ist behoben .. Ich kann nicht alle Fixes .. – Saltuk

+0

Sie können sich nicht auf 0/4 Positionen verlassen, weil es '1 (234) 567-8900' Format –

2

Ich denke, Sie sollten ein editierbares Feld (wie Eingabe von Typ Text) verwenden, um die Nummer und ein schreibgeschütztes Feld (wie eine Beschriftung) einzugeben, um es formatiert anzuzeigen, da der formatierte Wert nur eine Anzeige betrifft , also sollte es nicht editierbar sein.

Also habe ich Ihr Snippet geändert, um das zu tun.

function MyCntl($scope) { 
 
    $scope.myModel = {}; 
 
    $scope.myPrompt = "Input your phonenumber here!"; 
 
} 
 

 
var phonenumberModule = angular.module('phonenumberModule', []) 
 
    
 
\t .directive('phonenumberDirective', ['$filter', function($filter) { 
 
\t \t /* 
 
\t \t Intended use: 
 
\t \t \t <phonenumber-directive placeholder='prompt' model='someModel.phonenumber'></phonenumber-directive> 
 
\t \t Where: 
 
\t \t \t someModel.phonenumber: {String} value which to bind only the numeric characters [0-9] entered 
 
\t \t \t \t ie, if user enters 617-2223333, value of 6172223333 will be bound to model 
 
\t \t \t prompt: {String} text to keep in placeholder when no numeric input entered 
 
\t \t */ 
 
    
 
\t \t function link(scope, element, attributes) { 
 
    
 
\t \t \t // scope.inputValue is the value of input element used in template 
 
\t \t \t scope.inputValue = scope.phonenumberModel; 
 
    
 
\t \t \t scope.$watch('inputValue', function(value, oldValue) { 
 
\t \t \t \t 
 
\t \t \t \t value = String(value); 
 
       oldValue = String(oldValue); 
 
       // get rid of input non digits chars 
 
\t \t \t \t var number = value.replace(/[^0-9]+/g, ''); 
 
       var oldNumber = oldValue.replace(/[^0-9]+/g, ''); 
 
\t \t \t \t 
 
       var filteredNumber = $filter('phonenumber')(number); 
 
       // get rid of filter non digits chars 
 
       scope.phonenumberModel = filteredNumber.replace(/[^0-9]+/g, ''); 
 
       inputValue = scope.phonenumberModel; 
 
       var filteredOldNumber = $filter('phonenumber')(oldNumber); 
 
       if(filteredNumber.length === filteredOldNumber.length) { 
 
        scope.maxlength = filteredNumber.length; 
 
       } 
 
       else { 
 
        scope.maxlength = Math.max(number.length, 11); 
 
       }      
 
\t \t \t }); 
 
\t \t } 
 
\t \t 
 
\t \t return { 
 
\t \t \t link: link, 
 
\t \t \t restrict: 'E', 
 
\t \t \t scope: { 
 
\t \t \t \t phonenumberPlaceholder: '=placeholder', 
 
\t \t \t \t phonenumberModel: '=model', 
 
\t \t \t }, 
 
\t \t \t //templateUrl: '/static/phonenumberModule/template.html', 
 
\t \t \t 
 
      template: '<input name="phonenumber" ng-model="inputValue" type="tel" maxlength="{{maxlength || 11}}" class="phonenumber" placeholder="{{phonenumberPlaceholder}}" title="Phonenumber (Format: (999) 9999-9999)"> <label>Formatted:{{inputValue | phonenumber}}</label>', 
 
\t \t }; 
 
\t }]) 
 
    
 
\t .filter('phonenumber', function() { 
 
\t  /* 
 
\t  Format phonenumber as: c (xxx) xxx-xxxx 
 
\t  \t or as close as possible if phonenumber length is not 10 
 
\t  \t if c is not '1' (country code not USA), does not use country code 
 
\t  */ 
 
\t  
 
\t  return function (number) { 
 
\t \t  /* 
 
\t \t  @param {Number | String} number - Number that will be formatted as telephone number 
 
\t \t  Returns formatted number: (###) ###-#### 
 
\t \t  \t if number.length < 4: ### 
 
\t \t  \t else if number.length < 7: (###) ### 
 
    
 
\t \t  Does not handle country codes that are not '1' (USA) 
 
\t \t  */ 
 
\t   if (!number) { return ''; } 
 
    
 
\t   number = String(number); 
 
    
 
\t   // Will return formattedNumber. 
 
\t   // If phonenumber isn't longer than an area code, just show number 
 
\t   var formattedNumber = number; 
 
    
 
\t \t \t // if the first character is '1', strip it out and add it back 
 
\t \t \t var c = (number[0] == '1') ? '1 ' : ''; 
 
\t \t \t number = number[0] == '1' ? number.slice(1) : number; 
 
    
 
\t \t \t // # (###) ###-#### as c (area) front-end 
 
\t \t \t var area = number.substring(0,3); 
 
\t \t \t var front = number.substring(3, 6); 
 
\t \t \t var end = number.substring(6, 10); 
 
    
 
\t \t \t if (front) { 
 
\t \t \t \t formattedNumber = (c + "(" + area + ") " + front); \t 
 
\t \t \t } 
 
\t \t \t if (end) { 
 
\t \t \t \t formattedNumber += ("-" + end); 
 
\t \t \t } 
 
\t \t \t return formattedNumber; 
 
\t  }; 
 
\t });
.phonenumber { 
 
    min-width: 200px; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> 
 

 
<div ng-app="phonenumberModule" ng-controller="MyCntl"> 
 
    <p>phonenumber value: {{ myModel.phonenumber }}</p> 
 
    <p>formatted phonenumber: {{ myModel.phonenumber | phonenumber }}</p> 
 
    <form name="phoneForm"> 
 
     <phonenumber-directive placeholder="myPrompt" model='myModel.phonenumber'></phonenumber-directive> 
 
     <div ng-show="phoneForm.phonenumber.$error.minlength"> 
 
      <p>Enter a valid phone number</p> 
 
     </div> 
 
    </form> 
 
</div>

5

eine Benutzereingabe ändern, da sie geben als störend empfunden werden kann und führt immer zu Problemen wie diejenigen, die Sie beschreiben.

Im Allgemeinen ist es einfacher zu implementieren und weniger frustrierend für den Benutzer, die Benutzeroberfläche stattdessen zu ändern. Eine übliche Lösung für den Fall von Telefonnummern besteht darin, drei Eingabefelder nebeneinander anzuordnen, wobei die Formatierungszeichen dazwischen angezeigt werden.

Mit Angular kann eine einzelne Direktive erstellt werden, um diesen mehrteiligen Eingabemechanismus zu umbrechen und ein einzelnes verkettetes Ergebnis dem Rest der App zugänglich zu machen.