126

テキスト入力があり、ユーザーにスペースの使用を許可したくないので、入力したものはすべて小文字になります。

ng-modelでフィルターを使用することは許可されていません。

ng-model='tags | lowercase | no_spaces'

独自のディレクティブを作成することを検討しましたが、入力に関数を追加し、入力$parsers$formatters更新せず、入力に含まれる他の要素のみを更新しng-modelました。

現在入力している入力を変更するにはどうすればよいですか?

私は基本的に、StackOverflowの機能と同じように機能する「タグ」機能を作成しようとしています。

4

9 に答える 9

207

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つあります。

  • 無効な値はモデルに伝播されません
  • ディレクティブを使用すると、ウォッチャーを何度も複製することなく、このカスタム検証を入力に簡単に追加できます。
于 2013-01-20T13:31:48.080 に答える
29

モデルの値を監視し、変更時に更新することをお勧めします:http://plnkr.co/edit/Mb0uRyIIv1eK8nTg3Qng?p= preview

唯一の興味深い問題はスペースに関するものです。AngularJS1.0.3では、入力のng-modelは文字列を自動的にトリミングするため、最後または最初にスペースを追加してもモデルが変更されたことを検出しません(したがって、スペースは私のによって自動的に削除されません)コード)。ただし、1.1.1には、この機能を無効にできる「ng-trim」ディレクティブがあります(commit)。そこで、質問で説明した正確な機能を実現するために1.1.1を使用することにしました。

于 2013-01-19T23:31:16.757 に答える
23

この問題の解決策は、コントローラー側にフィルターを適用することです。

$scope.tags = $filter('lowercase')($scope.tags);

$filter依存関係として宣言することを忘れないでください。

于 2014-01-14T11:16:05.413 に答える
10

読み取り専用の入力フィールドを使用している場合は、フィルターでng-valueを使用できます。

例えば:

ng-value="price | number:8"
于 2017-12-10T22:36:55.860 に答える
5

$formattersコレクションと$parsersコレクションの両方に追加するディレクティブを使用して、変換が両方向で実行されるようにします。

jsfiddleへのリンクを含む詳細については、この他の回答を参照してください。

于 2015-10-20T12:34:49.853 に答える
3

私は同様の問題を抱えて使用しました

ng-change="handler(objectInScope)" 

ハンドラーで、objectInScopeのメソッドを呼び出して、それ自体を正しく変更します(粗い入力)。コントローラーで私はどこかでそれを開始しました

$scope.objectInScope = myObject; 

私はこれが派手なフィルターやウォッチャーを使用していないことを知っています...しかし、それはシンプルで素晴らしい働きをします。これの唯一の欠点は、objectInScopeがハンドラーへの呼び出しで送信されることです...

于 2014-10-07T17:25:12.387 に答える
1

複雑な非同期入力検証を行う場合は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) })
  };

})();
于 2016-05-02T17:24:13.020 に答える
0

あなたはこれを試すことができます

$scope.$watch('tags ',function(){

    $scope.tags = $filter('lowercase')($scope.tags);

});
于 2016-01-19T06:50:12.847 に答える
0

私はここに来て、入力テキストを積極的に変更し、入力時に最後の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>

于 2022-02-16T23:39:34.077 に答える