Мой код ниже позволяет пользователям переключаться между полями ввода для телефонных номеров.Но когда пользователь выбирает текст в определенном блоке (либо вручную, либо когда пользователь использует tab / shift-tab для перемещения между блоками), пользователь не может набирать символы для перезаписи выбранного текста.Вместо этого он должен использовать клавишу Backspace для удаления текста, прежде чем вводить что-то новое.Для каждого из упомянутых ящиков телефонных номеров установлена максимальная длина (3 для первого и второго и 4 для третьего).Вот мой код:
Основная HTML-страница:
<div class="form-inline">
<rv-phone-input form="clientForm" inline="true" is-required="true" label="Cell Number" name="clientFormMobileNum" value="clientFormData.mobileNum"
ng-model="clientFormData.mobileNum" ng-model-options="{}" next-elem="rv-phone-input input[name='clientFormContactNum1']"></rv-phone-input>
</div>
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>
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; //new line entered by KT
var isRightArrow = e.which === 39; //new line entered by KT
// if (!isBackspace && (e.which < 48 || e.which > 57)) {
if ((!isBackspace && !isLeftArrow && !isRightArrow && (e.which < 48 || e.which > 57)) || e.shiftKey) { //new line entered by KT to replace the one above
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) {
} else if (inputLength >= max && !isBackspace && !isLeftArrow && !isRightArrow) { //new line entered by KT to replace the one above
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);
Ценюпомощь.