Необходимо ограничить допустимые значения поля ввода (и длину текста) с помощью js - PullRequest
0 голосов
/ 18 сентября 2018

Получил следующий код, чтобы ограничить ввод в поле ввода только цифрами (без алфавитов, без специальных символов) и ограничить ввод 3 символами для первых двух блоков и 4 для третьего поля.Но я не могу запретить пользователю вводить специальные символы (те, которые пользователь нажимает Shift + число, чтобы получить), а также я не могу ограничить количество символов в поле до 3, 3 и 4 соответственно.Чего не хватает в моем коде?Кроме того, поведение этих текстовых полей в Chrome особенно странно - Chrome даже не позволяет вводить какие-либо значения в какие-либо поля ввода.Я также хотел бы разрешить возможность использования Ctrl-c, Ctrl-x и Ctrl-v (для копирования, вырезания и вставки данных) в этих полях, но не могу понять, как их реализовать.Что бы это ни стоило, я просмотрел несколько предложений по этой теме, но все еще не могу исправить свой код.

Код из rvPhoneInput.js:

(function(angular) {
  'use strict';

  angular.module('rvComponents')
    .component('rvPhoneInput', {
      bindings: {
        compare: '=?',
        form: '<',
        inline: '<?',
        isRequired: '<?',
        label: '@?',
        name: '@',
        nextElem: '@?',
        value: '=',
        isDisabled: '<?'
      },
      controller: PhoneInputController,
      require: {
        modelCtrl: 'ngModel',
        modelOptsCtrl: 'ngModelOptions'
      },
      templateUrl: './components/rvPhoneInput/rvPhoneInput.html'
    });

  function PhoneInputController($element, $scope, $window) {
    var ctrl = this;

    ctrl.phone = [
      {
        name: ctrl.name + 1,
        num: ''
      },
      {
        name: ctrl.name + 2,
        num: ''
      },
      {
        name: ctrl.name + 3,
        num: ''
      }
    ];

    ctrl.modelOpts = {
      allowInvalid: true
    };
    $element.attr('ng-model-options', JSON.stringify(ctrl.modelOpts));

    $scope.$watch('$ctrl.value', function(newVal) {
      if (newVal) {
        if (newVal.length === 10) {
          ctrl.phone[0].num = newVal.substring(0, 3);
          ctrl.phone[1].num = newVal.substring(3, 6);
          ctrl.phone[2].num = newVal.substring(6, 10);
        }
      } else {
        ctrl.phone[0].num = ctrl.phone[1].num = ctrl.phone[2].num = '';
      }
    });

    $scope.$watchGroup(['$ctrl.phone[0].num', '$ctrl.phone[1].num', '$ctrl.phone[2].num'], function(newVals) {
      var newPhoneNum = (newVals[0] || '') + (newVals[1] || '') + (newVals[2] || '');
      if (newPhoneNum) {
        if (ctrl.value !== newPhoneNum) {
          ctrl.value = newPhoneNum;
          ctrl.modelCtrl && ctrl.modelCtrl.$setViewValue(newPhoneNum);
        }
      } else {
        ctrl.value = undefined;
      }
    });

    ctrl.$onInit = function() {
      if (ctrl.modelCtrl) {
        ctrl.modelCtrl.$validators.sameNum = function(modelVal) {
          return !modelVal || !ctrl.compare || (modelVal && modelVal !== ctrl.compare);
        };
        ctrl.modelCtrl.$validators.phoneLength = function(modelVal) {
          return !modelVal || (modelVal && modelVal.length === 10);
        };
      }
      if (ctrl.modelOptsCtrl) {
        angular.merge(ctrl.modelOptsCtrl.$options, ctrl.modelOpts);
      }
    };

    $element.on('phoneFocus', function(evt) {
      $element.find('input[name="'+ctrl.phone[0].name+'"]').focus();
    });

    ctrl.maxlength = maxlength;
    ctrl.validateRequired = validateRequired;

    function maxlength(e, max, pos) {
      if (e.which === 9 || e.which === 13 || e.which === 16) {
        return true;
      }

      var isBackspace = e.which === 8;
      var isLeftArrow = e.which === 37;
      var isRightArrow = e.which === 39;          

      if (!isBackspace && !isLeftArrow && !isRightArrow && (e.which < 48 || e.which > 57)) {
      return e.preventDefault();
      }

      var inputLength = (ctrl.phone[pos].num || '').length;
      if (inputLength === max - 1 || ((inputLength === 1 || !inputLength) && isBackspace)) {
        var watcher = $scope.$watch(function() {
          return (ctrl.phone[pos].num || '').length;
        }, function(newVal) {
          // focus to next element when input's pre-determined length is reached
          if (newVal === (pos === 2 ? 4 : 3) || !newVal) {
            var elem;
            if (!newVal) {
              elem = $element.find('input[name="'+ctrl.phone[pos === 0 ? pos : pos-1].name+'"]');
            } else {
              elem = (pos === 2) ? $(ctrl.nextElem) : $element.find('input[name="'+ctrl.phone[pos+1].name+'"]');
            }
            elem.focus();

            // destroy watch
            watcher();
          }
        });
      } else if (inputLength >= max && !isBackspace && !isLeftArrow && !isRightArrow) {
        e.preventDefault();
      }
    }

    function validateRequired() {
      return ctrl.form.$submitted && ctrl.phone.every(function(phone) {
        return ctrl.form[phone.name].$error.required;
      }) && !ctrl.isDisabled;
    }
  }

  PhoneInputController.$inject = ['$element', '$scope', '$window'];
})(angular);

и вот код измой HTML-файл (rvPhoneInput.html):

<div ng-class="$ctrl.inline ? 'form-inline' : 'form-group'">
  <label ng-if="$ctrl.label">{{$ctrl.label}}<span style="color:red;" ng-if="$ctrl.isRequired">*</span></label>
  <div ng-class="$ctrl.inline ? 'd-inline-block' : ''">
    <span class="color-black">(</span>
    <input type="text" name="{{$ctrl.phone[0].name}}" class="form-control" ng-model="$ctrl.phone[0].num" ng-required="$ctrl.isRequired"
      ng-minlength="3" ng-model-options="$ctrl.modelOpts" ng-keydown="$ctrl.maxlength($event, 3, 0)" ng-disabled="$ctrl.isDisabled">
    <span class="color-black">)</span>
    <input type="text" name="{{$ctrl.phone[1].name}}" class="form-control" ng-model="$ctrl.phone[1].num" ng-required="$ctrl.isRequired" ng-disabled="$ctrl.isDisabled"
      ng-minlength="3" ng-model-options="$ctrl.modelOpts" ng-keydown="$ctrl.maxlength($event, 3, 1)">
    <span class="color-black">-</span>
    <input type="text" name="{{$ctrl.phone[2].name}}" class="form-control" ng-model="$ctrl.phone[2].num" ng-required="$ctrl.isRequired" ng-disabled="$ctrl.isDisabled"
      ng-minlength="4" ng-model-options="$ctrl.modelOpts" ng-keydown="$ctrl.maxlength($event, 4, 2)">
  </div>
  <div ng-if="$ctrl.validateRequired()" class="error-label">
    <div class="text-danger">This is a required field.</div>
  </div>
  <div ng-messages="$ctrl.form.$submitted && $ctrl.form[$ctrl.name].$error" class="error-label">
    <div class="text-danger" ng-message="sameNum">Your <span style="text-transform: lowercase">{{$ctrl.label}}</span> cannot be the same as your cell number.</div>
    <div class="text-danger" ng-message="phoneLength">Phone number must be 10 digits.</div>
  </div>
</div>

1 Ответ

0 голосов
/ 24 сентября 2018

Я не знаю способ Angular (я использую "Vue"), но этот фрагмент позволит вводить в поле только цифры, скобки, пробел и тире.Вы можете сделать только цифры , если хотите, используя var regx = /\d/;

Во-первых, я использую type="tel" - это не поможет вам для ограничения ввода или проверки, но это намекает на мобильные устройства, что они могут установить пользовательскую клавиатуру, оптимизированную для ввода с телефона.

var regx = /[0-9 ()-]/;
var inp = document.getElementById('field1');

inp.addEventListener('keypress', function(e) {
    console.log('key: ' + e.key);
    if (! e.key.match(regx)) {
        // if the key doesn't match the allowed characters,
        // prevent it from being entered.
        e.preventDefault();
    }
});
<form action="#">
    <label for="field1">Phone:</label>
    <input type="tel" id="field1" name="stuff" placeholder="Enter Phone" />
</form>

Это ограничение гарантирует, что набираются только разрешенные символы, но все еще нуждается в проверке - например, это позволит вам ввести 7)-3 82(-), который содержит только разрешенныесимволов, но, очевидно, это недопустимо.

Вы можете использовать проверку html5 pattern , но вы можете оказаться слишком ограничительными ... например, когда я принимаю ввод с телефона, я разрешаюразнообразие форматов: (nnn) nnn-nnnn, nnnnnnnnnn, nnn-nnn-nnnn, nnn.nnn.nnnn (и это даже не учитывает международные телефонные номера)

Не забудьте проверить оба в JS на клиентеа также проверка на сервере.

Подробнее о типе ввода "tel" см. Документ MDN , особенно раздел Проверка .

Конечно, кто-то, возможно, уже написал виджет Angular для телефонных номеров, поэтому вам не придется писать это самостоятельно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...