1. ホーム
  2. angularjs

[解決済み] 入力フィールドにフォーカスを当てるには?

2022-03-25 02:50:54

質問

AngularJSで入力フィールドにフォーカスを設定する「Angularの方法」とは何ですか?

より具体的な要求事項

  1. が表示された場合 モーダル が開かれたら、あらかじめ定義された <input> このモーダル内の
  2. 毎回 <input> が見えるようになったら(例えば、何らかのボタンをクリックすることによって)、それにフォーカスを設定する。

最初の要件を実現しようとすると autofocus しかし、これはモーダルが初めて開かれたときにのみ動作し、特定のブラウザでのみ動作します (例: Firefoxでは動作しません)。

よろしくお願いします。

解決方法は?

<ブロッククオート
  1. モーダルが開かれたとき、そのモーダル内の定義済みの <input> にフォーカスを設定する。

ディレクティブを定義し、プロパティ/トリガーを $watch して、いつ要素にフォーカスを当てるかを知るようにします。

Name: <input type="text" focus-me="shouldBeOpen">

app.directive('focusMe', ['$timeout', '$parse', function ($timeout, $parse) {
    return {
        //scope: true,   // optionally create a child scope
        link: function (scope, element, attrs) {
            var model = $parse(attrs.focusMe);
            scope.$watch(model, function (value) {
                console.log('value=', value);
                if (value === true) {
                    $timeout(function () {
                        element[0].focus();
                    });
                }
            });
            // to address @blesh's comment, set attribute value to 'false'
            // on blur event:
            element.bind('blur', function () {
                console.log('blur');
                scope.$apply(model.assign(scope, false));
            });
        }
    };
}]);

プランカー

タイムアウトは、モーダルのレンダリング時間を確保するために必要なようです。

'2.' 何らかのボタンをクリックするなどして <input> が可視化されるたびに、それにフォーカスを設定する。

基本的に上記のようなディレクティブを作成します。 スコープのプロパティを監視し、それがtrueになったら(ng-clickハンドラで設定する)、次のように実行する。 element[0].focus() . ユースケースによっては、$timeoutが必要な場合もあれば不要な場合もあります。

<button class="btn" ng-click="showForm=true; focusInput=true">show form and
 focus input</button>
<div ng-show="showForm">
  <input type="text" ng-model="myInput" focus-me="focusInput"> {{ myInput }}
  <button class="btn" ng-click="showForm=false">hide form</button>
</div>

app.directive('focusMe', function($timeout) {
  return {
    link: function(scope, element, attrs) {
      scope.$watch(attrs.focusMe, function(value) {
        if(value === true) { 
          console.log('value=',value);
          //$timeout(function() {
            element[0].focus();
            scope[attrs.focusMe] = false;
          //});
        }
      });
    }
  };
});

プランカー


2013年7月更新 : 私のオリジナルの isolate scope ディレクティブを使用して、埋め込み入力フィールド (モーダル内の入力フィールド) で問題が発生する人を何人か見かけました。 新しいスコープを持たないディレクティブ (または新しい子スコープを持つ可能性のあるディレクティブ) は、その苦痛をいくらか軽減するはずです。 そこで上記では、分離スコープを使用しないように回答を更新しました。 以下は、元の回答です。

1.のオリジナル回答、アイソレートスコープを使用する。

Name: <input type="text" focus-me="{{shouldBeOpen}}">

app.directive('focusMe', function($timeout) {
  return {
    scope: { trigger: '@focusMe' },
    link: function(scope, element) {
      scope.$watch('trigger', function(value) {
        if(value === "true") { 
          $timeout(function() {
            element[0].focus(); 
          });
        }
      });
    }
  };
});

プランカー .

2.のオリジナル回答、isolateスコープを使用しています。

<button class="btn" ng-click="showForm=true; focusInput=true">show form and
 focus input</button>
<div ng-show="showForm">
  <input type="text" focus-me="focusInput">
  <button class="btn" ng-click="showForm=false">hide form</button>
</div>

app.directive('focusMe', function($timeout) {
  return {
    scope: { trigger: '=focusMe' },
    link: function(scope, element) {
      scope.$watch('trigger', function(value) {
        if(value === true) { 
          //console.log('trigger',value);
          //$timeout(function() {
            element[0].focus();
            scope.trigger = false;
          //});
        }
      });
    }
  };
});

プランカー .

ディレクティブの中でtrigger/focusInputプロパティをリセットする必要があるので、'='を使って双方向のデータバインディングを行っています。 最初のディレクティブでは、'@'で十分でした。 また、'@'を使用する場合、@は常に文字列になるため、トリガー値を"true"と比較することに注意してください。