2013-02-08 10 views
9

テストケース:http://jsbin.com/ahugeg/4/edit(やや長い)変更フォーカス

上記テストケースでは、私はng-repeat指令によって生成された三つの入力要素を有します。このテストケースでの私の意図は、これらの入力の1つに上下の矢印を打つと、その方向で利用できる入力があれば、対応する方向の入力にフォーカスが移動するはずです。

私はAngularJSを初めて使うので、これを行うには簡単な方法で行方不明になるかもしれません。とにかく、アップイベントとダウンイベントを処理するために、2つの新しいディレクティブ(on-upon-down)を定義し、$scope.focusNext$scope.focusPrevメソッドを呼び出し、フォーカスを移動する相対的なエントリを渡します。これは私が立ち往生している場所です。

私はそれは、コントローラでのDOM要素に対処するため角度ウェイではないですけど、私はフォーカスは、モデルの属性/プロパティとして見ることができるか見ることができません。私は別の$scope.focusedEntryを持っていると思っていましたが、はそのプロパティの変更についてを見ますか?私が行って変更を検出したとしても、どの項目にフォーカスしたいエントリに対応する入力要素にアクセスすることができますか?

これをどのように行うべきかについての助力は大変ありがとうございます。

答えて

15

私はちょうどこれを書いて、簡単にそれをテスト - それはすべての余分な混乱せずに何をしたいんあなたのコントローラーとHTMLで。それを参照してくださいhereを参照してください。

HTML:

<body ng-controller="Ctrl"> 
    <input ng-repeat="entry in entries" value="{{entry}}" key-focus /> 
</body> 

コントローラー:

function Ctrl($scope) { 
    $scope.entries = [ 'apple', 'ball', 'cow' ]; 
} 

指令:@トレバーのソリューションに触発さ

app.directive('keyFocus', function() { 
    return { 
    restrict: 'A', 
    link: function(scope, elem, attrs) { 
     elem.bind('keyup', function (e) { 
     // up arrow 
     if (e.keyCode == 38) { 
      if(!scope.$first) { 
      elem[0].previousElementSibling.focus(); 
      } 
     } 
     // down arrow 
     else if (e.keyCode == 40) { 
      if(!scope.$last) { 
      elem[0].nextElementSibling.focus(); 
      } 
     } 
     }); 
    } 
    }; 
}); 
+0

ありがとうございます。あなたの解決策は私に自分の考えと動機を与えました。私は 'ng-repeat'要素の親に対して、フォーカスを移動させる' input'のセレクタを取るディレクティブを定義して、やや異なるアプローチをとっています。私は解決策を1分で投稿します。再度、感謝します。 –

6

私は同様の問題があり、この単純な指令を使用しました。 would-のみ焦点を当てて、それは属性がtrueに解決だ場合には、NG-ショーとNGに隠すように動作します

.directive('focusOn',function() { 
    return { 
     restrict : 'A', 
     link : function($scope,$element,$attr) { 
      $scope.$watch($attr.focusOn,function(focusVal) { 
       if(focusVal === true) { 
        setTimeout(function() { 
         $element.focus(); 
        },50); 
       } 
      }); 
     } 
    } 
}) 
+0

ハ!ニースとシンプルなソリューションです。ありがとうございます。 –

+0

すばらしい解決策。 focusValをより完全にチェックする必要があります。 ng-showとng-hideは、残念ながらプライベートな角度関数であるtoBoolean(値)を使用します。私はこれをサービスに移動し、Boolean.toBoolean(focusVal)=== trueを呼び出します。 – shapeshifter

4

、ここで私は落ち着い何、

app.directive('focusIter', function() { 

    return function (scope, elem, attrs) { 
     var atomSelector = attrs.focusIter; 

     elem.on('keyup', atomSelector, function (e) { 
      var atoms = elem.find(atomSelector), 
       toAtom = null; 

      for (var i = atoms.length - 1; i >= 0; i--) { 
       if (atoms[i] === e.target) { 
        if (e.keyCode === 38) { 
         toAtom = atoms[i - 1]; 
        } else if (e.keyCode === 40) { 
         toAtom = atoms[i + 1]; 
        } 
        break; 
       } 
      } 

      if (toAtom) toAtom.focus(); 

     }); 

     elem.on('keydown', atomSelector, function (e) { 
      if (e.keyCode === 38 || e.keyCode === 40) 
       e.preventDefault(); 
     }); 

    }; 
}); 

これは、すべての繰り返し入力の親要素に属性focus-iterを設定することを定義します。実際の動作はこちら:http://jsbin.com/ahugeg/10/を参照してください。

@ Trevorの利点は、focus-iter属性の値に任意のセレクタを設定して、フォーカスジャンプが動作する要素を正確に指定できることです。クレイジーな例として、focus-iter属性をinput:even :)に設定してみてください。これは、私のアプリケーションでは、inputにテストケースとは異なり、かなりの余分なマークアップが付いてくるので便利です。

+0

それは実際にあなたがそこでやったことでかなりきれいです。私は基本的にどのように 'focus-iter =" form> * "'のように動作するのが好きです。 –

+0

ありがとうございます。あなたの答えのマークアップのような 'key-focus'属性を持つ入力の場合、' focus-iter = "[key-focus]" 'でも: –

+0

は、テーブルのセル内の入力を助けますか? –

関連する問題