2016-08-10 3 views
3

Ich versuche, Eingabetext-Anweisung zu erstellen, die nur Zahlen innerhalb eines bestimmten Bereichs akzeptiert. Ich habe versucht, den Wert als Integer zu analysieren, natürlich min und max hat nicht funktioniert.Lassen Sie nur Zahlen im Bereich in das Textfeld eingeben

Ich möchte nicht den Eingang [type = "number"] verwenden.
Letztendlich versuche ich ein Geburtsdatum frei Eingabe Textfeld zu erstellen. wie unten gesehen:

date-of-birth.png

Die Richtlinie I angepasst habe [die ich im Moment zu verwenden, ich versuche] - das Original @angularjs: allows only numbers to be typed into a text box

app.directive('onlyDigits', function() { 
    return { 
     restrict: 'A', 
     require: '?ngModel', 
     link: function (scope, element, attrs, modelCtrl) { 
      modelCtrl.$parsers.push(function (inputValue) { 
       if (inputValue == undefined) return ''; 
       var transformedInput = inputValue.replace(/[^0-9]/g, ''); 
       var theInt = parseInt(transformedInput); 
       if (transformedInput !== inputValue) { 
        modelCtrl.$setViewValue(transformedInput); 
        modelCtrl.$render(); 
       } 
       return theInt; 
      }); 
     } 
    }; 

gefunden werden kann Was Ich hoffte zu tun, nachdem ich das gelöst habe, ist eine bedingte ng-show zu tun, um einen Fehler für ein span-Element zu zeigen - wenn der Benutzer einen Wert über 31 (für den Tag) 12 (für den Monat) und so weiter eingegeben hat.

Ich begrüße alle Vorschläge.

Vielen Dank.

+0

Was ist der Grund, dass Sie nicht wollen, 'type = "number"'? Wegen winziger Scroll-Tasten, die bei der Zahleneingabe erscheinen? – oKonyk

+0

Hey danke für die Nachricht. Nein, ich kann diese mit CSS verstecken. Da 'minlength' und' maxlength' 'attrs' nicht mit' type = "number" funktionieren und wenn ich diese attrs dann manuell benutze, benötigt es dann mehr DOM-Manipulation über jQuery, also versuche ich zu sehen wenn es einen mehr eckigen Weg gibt, dies mit dem Eingabetyp zu tun, der als "Text" bleibt. –

+0

Wenn Sie möchten, dass der Text eingereicht wird, um als Nummer zu fungieren, habe ich eine Lösung dafür, aber nicht in eckiger Weise, sondern nur in Javascript. Alles, was Sie tun müssen, ist zu überprüfen, ob sich Ihr charCode in dem von Ihnen angegebenen Bereich befindet. Wenn Sie wollen, kann ich den Code hier psot –

Antwort

3

Ich hatte genau das gleiche Problem. Ich habe "alles" ausprobiert, um es benutzerfreundlich zu machen und ungültige Werte nicht zu akzeptieren. Schließlich gab ich scheinbar einfache Lösungen auf, wie ng-pattern, und mit Hilfe eines Freundes @Teemu Turkia kamen wir auf die Richtlinie integers-only.

Es type="text" verwendet, unterstützt sowohl min und max, nicht akzeptiert Zeichen über Zahlen und - (als ein erstes Zeichen in dem Fall minimal negativ ist) eingegeben werden.

Außerdem wird ng-model niemals mit einem ungültigen Wert wie leere Zeichenfolge oder NaN, nur Werte zwischen gegebenem Bereich oder null zugewiesen.

Ich weiß, zunächst sieht es eher einschüchternd;)

HTML

// note: uses underscore.js 
<body> 
    <form name="form"> 
    <header>DD/MM/YYYY</header> 
    <section> 
     <input type="text" 
      name="day" 
      ng-model="day" 
      min="1" 
      max="31" 
      integers-only> 
     <input type="text" 
      name="month" 
      ng-model="month" 
      min="1" 
      max="12" 
      integers-only> 
     <input type="text" 
      name="year" 
      ng-model="year" 
      min="1900" 
      max="2016" 
      integers-only> 
    </section> 
    <section> 
     <span ng-show="form.day.$invalid">Invalid day</span> 
     <span ng-show="form.month.$invalid">Invalid month</span> 
     <span ng-show="form.year.$invalid">Invalid year</span> 
    </section> 
    </form> 
</body> 

JavaScript

/** 
* numeric input 
* <input type="text" name="name" ng-model="model" min="0" max="100" integers-only> 
*/ 
angular.module('app', []) 
.directive('integersOnly', function() { 
    return { 
    restrict: 'A', 
    require: 'ngModel', 
    scope: { 
     min: '=', 
     max: '=' 
    }, 
    link: function(scope, element, attrs, modelCtrl) { 
     function isInvalid(value) { 
     return (value === null || typeof value === 'undefined' || !value.length); 
     } 

     function replace(value) { 
     if (isInvalid(value)) { 
      return null; 
     } 

     var newValue = []; 
     var chrs = value.split(''); 
     var allowedChars = ['0','1','2','3','4','5','6','7','8','9','-']; 

     for (var index = 0; index < chrs.length; index++) { 
      if (_.contains(allowedChars, chrs[index])) { 
      if (index > 0 && chrs[index] === '-') { 
       break; 
      } 
      newValue.push(chrs[index]); 
      } 
     } 

     return newValue.join('') || null; 
     } 

     modelCtrl.$parsers.push(function(value) { 
     var originalValue = value; 

     value = replace(value); 

     if (value !== originalValue) { 
      modelCtrl.$setViewValue(value); 
      modelCtrl.$render(); 
     } 

     return value && isFinite(value) ? parseInt(value) : value; 
     }); 

     modelCtrl.$formatters.push(function(value) { 
     if (value === null || typeof value === 'undefined') { 
      return null; 
     } 

     return parseInt(value); 
     }); 
     modelCtrl.$validators.min = function(modelValue) { 
     if (scope.min !== null && modelValue !== null && modelValue < scope.min) { return false; } 
     return true; 
     }; 
     modelCtrl.$validators.max = function(modelValue) { 
     if (scope.max !== null && modelValue !== null && modelValue > scope.max) { return false; } 
     return true; 
     }; 
     modelCtrl.$validators.hasOnlyChar = function(modelValue) { 
     if (!isInvalid(modelValue) && modelValue === '-') { return false; } 
     return true; 
     }; 
    } 
    }; 
}); 

Ergebnis

image


Verwandte Plunker hier http://plnkr.co/edit/mIiKuw

+1

Vielen Dank für Ihre Hilfe @Mikko!, Sie sind ein Genie! ** Das funktionierte wie ein Zauber! ** FYI zu jemand anderem, der dies verwendet, download [Unterstreich.js] (http://underscorejs.org/), so dass die Funktion '_.contains()' innerhalb der Direktive funktioniert! –

0

Diese Lösung nutzt die Min- und Max-Attribute Werte der Eingabefelder zu begrenzen. Es verwendet auch ngModelOptions, um den Modellwert erst nach einem definierten Intervall zu aktualisieren. Auf diese Weise können Benutzer Werte eingeben, bevor der Modellparser auf die Eingabe einwirkt.

angular.module("app", []); 
 
angular.module("app").directive('onlyDigits', function() { 
 
    return { 
 
    restrict: 'A', 
 
    require: '?ngModel', 
 
    scope: { 
 
     min: "@", 
 
     max: "@" 
 
    }, 
 
    link: function(scope, element, attrs, modelCtrl) { 
 
     modelCtrl.$parsers.push(function(inputValue) { 
 
     if (inputValue == undefined) return ''; 
 
     var transformedInput = inputValue.replace(/[^0-9]/g, ''); 
 
     var theInt = parseInt(transformedInput); 
 
     var max = scope.max; 
 
     var min = scope.min; 
 
     if (theInt > max) { 
 
      theInt = max; 
 
     } else if (theInt < min) { 
 
      theInt = min; 
 
     } 
 
     modelCtrl.$setViewValue(theInt.toString()); 
 
     modelCtrl.$render(); 
 
     return theInt; 
 
     }); 
 
    } 
 
    } 
 
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script> 
 

 
<body ng-app="app"> 
 
    <input type="text" ng-model="month" ng-model-options="{ debounce: 200 }" only-digits min="1" max="12"> 
 
    <input type="text" ng-model="day" ng-model-options="{ debounce: 200 }" min="1" max="30" only-digits> 
 
    <input type="text" ng-model="year" ng-model-options="{ debounce: 500 }" only-digits min="1900" max="2050"> 
 

 
</body>

2

Hier Lösung ohne kundenspezifische Richtlinien. Es ist immer noch input type="number" aber benötigte Funktionalität wird erreicht.

ist hier plunker

<!DOCTYPE html> 
 
<html> 
 
    <head></head> 
 

 
    <body ng-app="app" ng-controller="dobController as dob"> 
 
    <h3>Date of birth form</h3> 
 
    <form name="dobForm" class="form" novalidate=""> 
 
     <div> 
 
      <label for="date">DD</label> 
 
      <input type="number" ng-model="dob.date" name="date" min="1" max="31" integer /> 
 
      <label for="month">MM</label> 
 
      <input type="number" ng-model="dob.month" name="month" min="1" max="12" integer /> 
 
      <label for="year">YYYY</label> 
 
      <input type="number" ng-model="dob.year" name="year" min="1900" max="2016" integer /> 
 
      
 
      <div style="color: red;" ng-if="dobForm.$invalid"> 
 
       <p ng-show="dobForm.date.$error.min || dobForm.date.$error.max"> 
 
       date must be in range 1 to 31! 
 
       </p> 
 
       <p ng-show="dobForm.month.$error.min || dobForm.month.$error.max"> 
 
       month must be in range 1 to 12! 
 
       </p> 
 
       <p ng-show="dobForm.year.$error.min || dobForm.year.$error.max"> 
 
       year must be in range 1900 to 2016! 
 
       </p> 
 
      </div> 
 
      
 
      </div> 
 
    </form> 
 
    
 
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.0/angular.js"></script> 
 
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.0/angular-messages.js"></script> 
 
    <script> 
 
     var app = angular.module('app', []); 
 

 
     app.controller('dobController', function($scope) {}); 
 
    </script> 
 
    <style> 
 
     input[type=number]::-webkit-inner-spin-button, 
 
     input[type=number]::-webkit-outer-spin-button { 
 
      -webkit-appearance: none; 
 
      margin: 0; 
 
     } 
 
    </style> 
 
    
 
    </body> 
 

 
</html>

enter image description here

+0

Und das ist der Grund, warum das so schwer ist! Ich meine, das ist eine schöne Lösung, aber es akzeptiert z. aufeinanderfolgende '+' und '-' werden eingegeben, ohne $ Fehler zu geben, und auch' .' und ','. Sehen Sie hier http://i.imgur.com/MsqGQ38.png –

+0

Ja, ich stimme diesem Punkt voll und ganz zu. Akzeptierte Lösung ist viel umfassender. – oKonyk

Verwandte Themen