访问嵌套在ng-repeat中的下一个/上一个输入的最佳方法是什么?

时间:2013-07-08 15:15:55

标签: angularjs

我将keyup绑定添加到嵌套在ng-repeats中的输入,以便顺利地从下一个输入类似于this question的输入。不同之处在于解决方案存在直接与兄弟姐妹相邻的输入。

这是我的html原型:

<div ng-repeat="student in students" >
  <div class="input-append">
    <input class="span3" type="text" ng-model="student.name"
       ng-required="student.name.split(' ').length>1" focus-others index="{{ $index }}" focus="{{ focus.value }}"/>
    <button class="btn btn-danger" type="button" ng-click="deleteInput($index)">X</button>
  </div>
</div>

我目前有两种解决方案都可以使用。


第一个解决方案 - 遍历dom寻找输入,匹配聚焦的输入,然后在keyup聚焦下一个输入:

app.directive('focusOthers', function($timeout){
  return function(scope, element){
    var inputs;
    $timeout(function(){
        inputs = document.querySelectorAll('input[type="text"]');
    },0)
    element.bind('keyup', function(e){
        var current = document.activeElement;      
        if (e.keyCode == 13){
            event.preventDefault();
            var i = 0;
            while( i<inputs.length){
                if (inputs[i]==current){                        
                    var nextInput = inputs[i+1];
                    nextInput.focus();
                    i=inputs.length;
                }
                i++;
            }
        }
    })
}
});

Here's a working plunk


第二个解决方案 - 这是一个更“有棱角”的解决方案,因为该指令处理元素属性中的信息,以确定哪个元素获得焦点。

app.directive('focusOthers', function(){
return {
    link: function(scope, element, attrs){
        // scope.index = attrs.index - wouldn't it be nice if this worked?
        attrs.$observe('index', function(val){
            scope.index = parseInt(val);
        });
        attrs.$observe('focus', function(val){
            if(scope.focus.value == scope.index){
                element[0].focus();
            }
        });

        element.bind('keyup', function(e){
            if(e.keyCode==13){
                scope.focus.value = scope.index + 1;
                scope.$apply();
            }
        });
    }
}
});

Here's the plunk此方法。

每个可能的缺点:

第一种方法是纯粹的dom遍历。我不一定有这个问题,但是每当你遍历dom并且$timeout用于等待渲染时,有人会喊出“那不是角度设计的。”

- 我想第二种方法更“有棱角”,但指令在属性上注册$observe,并且页面上有400多个输入的可能性,我不知道这是否会影响性能。

所以我的问题是,是否有更好的方法可以获得对这些嵌套输入的访问权限,这些输入既可以安抚角神,也可以轻松浏览浏览器?或者我的方法之一是更好的方法吗?或者我应该放弃并在Python / Jinja2中完成所有操作;)?

1 个答案:

答案 0 :(得分:0)

我认为更多浏览器/用户满意的方法是使用tabindex属性。您可以在每个输入元素上吐出此属性,并使用$ index值来获取ng-repeat所在的迭代次数。很多浏览器和移动设备都会使用此属性来提供表单和列表的导航(例如,当关注表单输入时,iOS中的前进/后退箭头)

另一种解决方案是使用指令每个元素

<input focus-this="{{$index}}"></input>

然后

directives.directive('focusThis', function(){
    return {
        link: function (scope, element, attrs){
            scope.$watch('focusedIndex', function(newVal, oldVal){
                if (newVal == attrs['focus-this']){
                    element.focus();
                }
                else {
                    element.blur();
                }
            });
        }
    };
});

您应该能够将keInown事件的focusedIndex更改为上一个/下一个,或者甚至可以根据需要跳转到特定索引。

警告:未经测试的代码。只是一个概念。可能需要调整。