2013-02-08 70 views
9

測試用例:http://jsbin.com/ahugeg/4/edit(略長)焦點轉到輸入在AngularJS的關鍵事件

在上述試驗中的情況下,我有三個輸入元件,通過ng-repeat指令生成的。我在這個測試案例中的意圖是,如果在該方向上有可用輸入,則在這些輸入之一中按下向上/向下箭頭應將焦點移動到相應方向上的輸入。

我是AngularJS的新手,所以我可能會忽略一些簡單的方法來做到這一點。無論如何,我定義了兩個新的指令(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'ed元素的父項上定義了一個指令,該指令採用焦點將被移動的'input'的選擇器。我會在一分鐘後發佈我的解決方案。再次感謝。 – 2013-02-09 05:28:43

6

我有一個類似的問題,並使用這個簡單的指令。它的工作原理爲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

哈!很好,很簡單的解決方案。非常感謝。 – 2013-02-09 05:32:41

+0

偉大的解決方案。您需要更徹底地檢查focusVal。 ng-show和ng-hide使用toBoolean(value),不幸的是它是一個私有的角函數。我將其移至一個服務並調用Boolean.toBoolean(focusVal)=== true。 – shapeshifter 2013-07-16 01:15:02

4

通過@ Trevor的解決方案的啓發,這就是我看中了,

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's相比,我可以設置focus-iter屬性值的任意選擇器來明確指出焦點跳轉應該使用哪些元素。作爲一個瘋狂的例子,嘗試設置focus-iter屬性爲input:even :)。這有助於在我的應用程序中,input帶有相當多的額外標記,與測試用例不同。

+0

這實際上很乾淨你在那裏做的。我喜歡基本上如何工作的東西,比如'focus-iter =「form> *」'。 – 2013-02-09 06:12:55

+0

謝謝。或甚至'focus-iter =「[key-focus]」',當輸入具有'key-focus'屬性時,就像你的答案中的標記:) – 2013-02-09 06:51:40

+0

可以幫助我在表格單元格內輸入? – 2014-03-21 05:26:15