我有一个文本输入,不想让用户使用空格,所有键入的内容都将变为小写。
我知道我不允许在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上的功能相同。
Answers:
我建议您观看模型值并在更改时对其进行更新:http ://plnkr.co/edit/Mb0uRyIIv1eK8nTg3Qng? p= preview
唯一有趣的问题是空格:在AngularJS 1.0.3 ng-model中,输入会自动修剪字符串,因此,如果在结尾或开头添加空格,它不会检测到模型已更改(因此,空格不会自动删除)码)。但是在1.1.1中,有一个“ ng-trim”指令允许禁用此功能(commit)。因此,我决定使用1.1.1来实现您在问题中描述的确切功能。
$watch
强制再次调用侦听器。在简单的情况下(过滤器是幂等的),您将最终使过滤器在每次修改时执行两次。
我相信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
如果我们要在输入的开头/结尾不允许空格,则需要使用指令。
这种方法的优点是2倍:
modelCtrl.$setViewValue(transformedInput); modelCtrl.$render();
有用的部分是有用的,它将链接到文档:docs.angularjs.org/api/ng.directive : ngModel.NgModelController 一个“保护”我的话的意思是,不仅可以从视图和我的方式掩盖了这一点。因此,我认为这取决于实际情况,如何修改范围。
modelCtrl
是指令所需的控制器。(require 'ngModel'
)
解决此问题的方法可能是在控制器端应用过滤器:
$scope.tags = $filter('lowercase')($scope.tags);
不要忘记声明$filter
为依赖项。
如果您要进行复杂的异步输入验证,则值得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);
});