我有一个文本输入框,不希望用户使用空格,并且所有键入的内容都会转换为小写字母。
我知道不能在ng-model上使用过滤器。
ng-model='tags | lowercase | no_spaces'
我考虑创建自己的指令,但将函数添加到$parsers
和$formatters
中并没有更新输入,只有其他具有ng-model
的元素更新了。
我该如何更改当前正在输入的输入内容?
我实际上正在尝试创建像StackOverflow这里的“标签”功能。
我有一个文本输入框,不希望用户使用空格,并且所有键入的内容都会转换为小写字母。
我知道不能在ng-model上使用过滤器。
ng-model='tags | lowercase | no_spaces'
我考虑创建自己的指令,但将函数添加到$parsers
和$formatters
中并没有更新输入,只有其他具有ng-model
的元素更新了。
我该如何更改当前正在输入的输入内容?
我实际上正在尝试创建像StackOverflow这里的“标签”功能。
我认为AngularJS的输入和ngModel
指令的意图是,无效的输入永远不应该进入模型。模型应始终有效。具有无效模型的问题在于,我们可能会有观察者触发并根据无效模型采取(不适当的)操作。
在我看来,这里的正确解决方案是插入到$parsers
管道中,并确保无效输入不会成为模型的一部分。我不确定您尝试如何处理事物或$parsers
对您来说究竟有什么问题,但是这里有一个简单的指令,可以解决您的问题(或者至少是我对问题的理解):
app.directive('customValidation', function(){
return {
require: 'ngModel',
link: function(scope, element, attrs, modelCtrl) {
modelCtrl.$parsers.push(function (inputValue) {
var transformedInput = inputValue.toLowerCase().replace(/ /g, '');
if (transformedInput!=inputValue) {
modelCtrl.$setViewValue(transformedInput);
modelCtrl.$render();
}
return transformedInput;
});
}
};
});
一旦上述指令被声明,它可以像这样使用:
<input ng-model="sth" ng-trim="false" custom-validation>
如@Valentyn Shybanov所提出的解决方案,如果我们想禁止输入开头/结尾的空格,则需要使用ng-trim
指令。
这种方法的优点有两个:
modelCtrl
是指令所需的控制器。(require 'ngModel'
) - Nate-Wilkins建议观察模型值并在更改时更新它:http://plnkr.co/edit/Mb0uRyIIv1eK8nTg3Qng?p=preview
唯一需要注意的问题是空格:在AngularJS 1.0.3中,input上的ng-model自动修剪字符串,因此如果您在末尾或开头添加空格,则不会检测到模型已更改(因此我的代码不会自动删除空格)。但是在1.1.1中,有一个'ng-trim'指令,允许禁用此功能(提交)。所以我决定使用1.1.1来实现您在问题中描述的确切功能。
$watch
中重新分配作用域变量会强制再次调用监听器。在简单情况下(其中您的过滤器是幂等的),每次修改都会导致过滤器执行两次。 - BorisOkunskiy解决这个问题的方法是在控制器端应用过滤器:
$scope.tags = $filter('lowercase')($scope.tags);
不要忘记声明$filter
为依赖项。
ng-value="price | number:8"
我有一个类似的问题,用了
ng-change="handler(objectInScope)"
在我的处理程序中,我调用了objectInScope的一个方法来正确地修改自身(粗略输入)。在控制器中,我已经在某个地方启动了这个过程。
$scope.objectInScope = myObject;
我知道这种方法没有使用任何高级过滤器或者监听器,但是它非常简单并且可以起到很好的作用。唯一不足的地方就是在传递给处理程序时需要传入 objectInScope 对象。
ng-model
抽象为具有自己验证方法的自定义类的一部分可能是值得的。
https://plnkr.co/edit/gUnUjs0qHQwkq2vPZlpO?p=preview
html
<div>
<label for="a">input a</label>
<input
ng-class="{'is-valid': vm.store.a.isValid == true, 'is-invalid': vm.store.a.isValid == false}"
ng-keyup="vm.store.a.validate(['isEmpty'])"
ng-model="vm.store.a.model"
placeholder="{{vm.store.a.isValid === false ? vm.store.a.warning : ''}}"
id="a" />
<label for="b">input b</label>
<input
ng-class="{'is-valid': vm.store.b.isValid == true, 'is-invalid': vm.store.b.isValid == false}"
ng-keyup="vm.store.b.validate(['isEmpty'])"
ng-model="vm.store.b.model"
placeholder="{{vm.store.b.isValid === false ? vm.store.b.warning : ''}}"
id="b" />
</div>
代码
(function() {
const _ = window._;
angular
.module('app', [])
.directive('componentLayout', layout)
.controller('Layout', ['Validator', Layout])
.factory('Validator', function() { return Validator; });
/** Layout controller */
function Layout(Validator) {
this.store = {
a: new Validator({title: 'input a'}),
b: new Validator({title: 'input b'})
};
}
/** layout directive */
function layout() {
return {
restrict: 'EA',
templateUrl: 'layout.html',
controller: 'Layout',
controllerAs: 'vm',
bindToController: true
};
}
/** Validator factory */
function Validator(config) {
this.model = null;
this.isValid = null;
this.title = config.title;
}
Validator.prototype.isEmpty = function(checkName) {
return new Promise((resolve, reject) => {
if (/^\s+$/.test(this.model) || this.model.length === 0) {
this.isValid = false;
this.warning = `${this.title} cannot be empty`;
reject(_.merge(this, {test: checkName}));
}
else {
this.isValid = true;
resolve(_.merge(this, {test: checkName}));
}
});
};
/**
* @memberof Validator
* @param {array} checks - array of strings, must match defined Validator class methods
*/
Validator.prototype.validate = function(checks) {
Promise
.all(checks.map(check => this[check](check)))
.then(res => { console.log('pass', res) })
.catch(e => { console.log('fail', e) })
};
})();
$scope.$watch('tags ',function(){
$scope.tags = $filter('lowercase')($scope.tags);
});
我来这里是寻找一个解决方案,可以在我们输入时主动修改输入文本并用*代替除了最后4位之外的所有内容。这可以通过$formatters实现。
例如:账户号码输入框:1234567890AHSB1
应该在输入框中显示为**********AHSB
答案只是稍微变化了一下 @pkozlowski.opensource 给出的解决方案。
angular.module('myApp').directive('npiMask', function() {
return {
require: 'ngModel',
link: function($scope, element, attrs, modelCtrl) {
modelCtrl.$formatters.push(function(inputValue) {
var transformedInput = inputValue.toString().replace(/.(?=.{4,}$)/g, '*');
if (transformedInput !== inputValue) {
modelCtrl.$setViewValue(transformedInput);
modelCtrl.$render();
}
return transformedInput;
});
}
};
});
<input-text
name="accountNum"
label="{{'LOAN_REPAY.ADD_LOAN.ACCOUNT_NUM_LABEL' | translate}}"
ng-model="vm.model.formData.loanDetails.accountNum"
is-required="true"
maxlength="35"
size="4"
npi-mask>
</input-text>