私はテキストを入力していますが、ユーザーにスペースの使用を許可したくないので、入力したものはすべて小文字になります。
私は、例えばng-modelでフィルタを使うことが許可されていないことを知っています。
ng-model='tags | lowercase | no_spaces'
私は自分自身のディレクティブを作成することを検討しましたが、$parsers
と$formatters
に関数を追加しても入力は更新されず、ng-model
を持つ他の要素のみが更新されました。
現在入力中の入力を変更するにはどうすればよいですか。
私は本質的にはStackOverflowでここにあるもののように機能する 'タグ'機能を作成しようとしています。
私はモデルの値を監視し、変更時にそれを更新することをお勧めします: http://plnkr.co/edit/ Mb0uRyIIv1eK8nTg3Qng?p =プレビュー
唯一の興味深い問題はスペースに関するものです。AngularJS 1.0.3では、入力時のng-modelは文字列を自動的にトリミングするので、最後または最初にスペースを追加してもモデルが変更されたことは検出されません。コード)。しかし1.1.1にはこの機能を無効にすることができる 'ng-trim'ディレクティブがあります( commit )。だから私はあなたがあなたの質問で述べた正確な機能性を達成するために1.1.1を使うことにしました。
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つあります。
この問題を解決するには、コントローラ側にフィルタを適用します。
$scope.tags = $filter('lowercase')($scope.tags);
$filter
を依存関係として宣言することを忘れないでください。
読み取り専用の入力フィールドを使用している場合は、ng-valueをfilterと共に使用できます。
例えば:
ng-value="price | number:8"
変換が両方向に確実に実行されるように、$ formattersコレクションと$ parsersコレクションの両方に追加するディレクティブを使用してください。
Jsfiddleへのリンクを含む詳細については、 この他の答え を参照してください。
私は同様の問題を抱えて使用しました
ng-change="handler(objectInScope)"
私のハンドラーでは、objectInScopeのメソッドを呼び出して自分自身を正しく変更します(粗入力)。コントローラで私はどこかでそれを始めました
$scope.objectInScope = myObject;
私はこれがどんな派手なフィルタもウォッチャーも使用しないのを知っています...しかしそれは簡単で素晴らしい仕事をします。唯一の欠点は、objectInScopeがハンドラへの呼び出しで送信されることです。
複雑で非同期の入力検証をしている場合は、独自の検証メソッドを使用してカスタムクラスの一部としてng-model
を1つ上のレベルに抽象化することをお勧めします。
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);
});