10

测试用例: http: //jsbin.com/ahugeg/4/edit(略长)

在上面的测试用例中,我有三个输入元素,由ng-repeat指令生成。我在这个测试用例中的意图是,如果在该方向上有可用输入,则在其中一个输入中点击向上/向下箭头应将焦点移至相应方向的输入。

我是 AngularJS 的新手,所以我可能会错过一些直接的方法来做到这一点。无论如何,我定义了两个新指令(on-upand on-down)来处理 up 和 down 事件,并调用$scope.focusNextand$scope.focusPrev方法,传递正确的条目,相对于焦点应该移动的条目。这就是我卡住的地方。

我知道这不是在控制器中处理 DOM 元素的角度方式,但我看不出如何将焦点视为模型的属性/属性。我什至想过有一个单独的$scope.focusedEntry,但是我应该注意那个属性的变化吗?即使我这样做并且我检测到更改,我如何访问与我想要关注的条目对应的输入元素?

非常感谢有关如何完成此操作的任何帮助。

4

3 回答 3

16

我只是把它写下来并简单地测试了它——它可以做你想做的事情,而不会在你的控制器和 HTML 中产生所有额外的混乱。看到它在这里工作。

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();
          }
        }
      });
    }
  };
});
于 2013-02-09T00:35:55.163 回答
6

我遇到了类似的问题并使用了这个简单的指令。它作为 ng-show 和 ng-hide 工作 - 只有当它的属性解析为 true 时才会有焦点:

.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);
                }
            });
        }
    }
})
于 2013-02-08T23:49:01.093 回答
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 的优势在于我可以为focus-iter属性值设置任意选择器,以准确指定焦点跳转应该使用的元素。作为一个疯狂的例子,尝试将focus-iter属性设置为input:even:)。这很有帮助,因为在我的应用程序中input,与测试用例不同,s 在它们周围带有相当多的额外标记。

于 2013-02-09T05:45:57.193 回答