【问题标题】:AngularJS: Move to next form input element after successful validationAngularJS:成功验证后移动到下一个表单输入元素
【发布时间】:2013-07-30 15:17:52
【问题描述】:

我编写了一个自定义指令来验证我的表单字段。当满足某些条件时(即它是脏且有效的),我想将焦点自动设置到下一个输入元素。这是我的用户的要求,以便他们可以最有效地浏览表单。

简化的指令如下所示:

directive('custom', ['$parse', function($parse) {
    return {
        restrict: 'A',
        require: ['ngModel', '^ngController'],
        link: function(scope, element, attrs, ctrls) {
           var model=ctrls[0], form=ctrls[1];

           scope.next = function(){
                return model.$valid
            }

            scope.$watch(scope.next, function(newValue, oldValue){
                if (newValue && model.$dirty){
                    ???
                }
            })

现在我的问题是:我如何识别 - 下一个输入元素(即下一个兄弟元素)或可能通过 tabindex - 并专注于它 不使用 Jquery?

对我来说,目前还不清楚,如何在没有 Jquery 的情况下从可用的“范围”或“元素”属性中获取下一个输入元素;并且 JQlite 没有“焦点”方法。基本上,我需要一个有效的替代品???在我的代码中。

非常感谢任何帮助。谢谢 于尔根

【问题讨论】:

标签: forms validation angularjs


【解决方案1】:

您可以使用 [0] 从 angular/jqLit​​e 对象(没有)中获取底层的 input 元素(具有 focus() 函数)。

app.directive('custom', ['$parse', function($parse) {
    return {
        restrict: 'A',
        require: ['ngModel'],
        link: function(scope, element, attrs, ctrls) {
           var model=ctrls[0], form=ctrls[1];

           scope.next = function(){
                return model.$valid;
            }

            scope.$watch(scope.next, function(newValue, oldValue){
                if (newValue && model.$dirty)
                {
                    var nextinput = element.next('input');
                    if (nextinput.length === 1)
                    {
                        nextinput[0].focus();
                    }
                }
            })
        }
    }
}])

http://jsfiddle.net/Y2XLA/

【讨论】:

  • 第一次它在长度等于 3 时作为例外工作。但是当我们再次尝试在文本框中输入时,它不能作为例外工作。此外,在最后一个文本框中,它允许在初始时间本身输入 3 个以上的字符
  • 它按预期工作:当输入的状态从无效变为有效时,下一个输入获得焦点。因此,正如所料,除非您首先使该输入无效(例如,通过删除所有内容),否则更改较早的(有效)文本框不会做任何事情。在示例中,有效性为 minlength=3,因此允许超过 3 个字符(此外,首先没有提到不允许无效输入。)
  • 如果输入不是全部在表单的顶层,这不会找到下一个输入!
【解决方案2】:

element.next().focus() 如果您有一个复杂的表单并且输入嵌套到不同的 div 中,则可能无法正常工作。 我写完了这个指令(这里我把重点移到 Enter 上,但可以适应任何事件):

.directive('enterToTab', function($timeout) {
  return {
    restrict: 'A',
    link: function(scope, element, attrs) {
      var procAttr = 'data-ett-processed';

      $timeout(function() { // Use $timeout to run the directive when the DOM is fully rendered
        var formElements = element[0].querySelectorAll('input:not([' + procAttr + '="true"]), select:not([' + procAttr + '="true"]), textarea:not([' + procAttr + '="true"])');

        // Run through all elements in form
        var formElementsLength = formElements.length;
        for (var i = 0; i < formElementsLength; i++) {          // Add tabindex attribute
          formElements[i].setAttribute('tabindex', i + 1);

          // Go to next element on Enter key press
          formElements[i].addEventListener('keypress', function(event) {
            if (event.keyCode === 13) { // Enter
              // Prevent Angular from validating all the fields and submitting
              if (event.target.tagName !== 'TEXTAREA') { // Not on textarea, otherwise not possible to add new line
                event.stopPropagation();
                event.preventDefault();
              }

              var nextIndex = parseInt(event.target.getAttribute('tabindex')) + 1;

              // Move focus to next element
              // TODO: find next visible element
              var nextElem = element[0].querySelector('[tabIndex="' + (nextIndex) + '"]');

              if (nextElem) {
                nextElem.focus();
              }
            }
          });
          formElements[i].setAttribute(procAttr, true); // Add attribute to prevent adding 2 listeners on same element
        }
      });
    }
  };
});

【讨论】:

  • 此代码中阻止了许多有用的“陷阱”:thumbsup:
【解决方案3】:
  1. 事件应该在 HTML 组件中(keypress) = "keyFocus($event)"
  2. 方法应该类似于.ts 文件。

    keyFocus(input1){ input1.srcElement.nextElementSibling.focus(); }

【讨论】:

    【解决方案4】:

    AngularJS 已经包含 jQuery 的轻量级版本,因此您也可以使用它... http://docs.angularjs.org/api/angular.element

    你可以试试这样的:

    element.next().focus()

    【讨论】:

    • 我已经详细说明了我的问题
    • 我已经尝试过 element.next(),但这似乎不起作用。此外,angular.element 没有焦点方法。
    • 也许$(element).next().focus() 会起作用。 focus() 是一个普通的 javascript 方法。
    • 但是“$”是 JQuery,不是吗。我正在寻找没有 Jquery 的解决方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-28
    • 2015-10-22
    • 1970-01-01
    相关资源
    最近更新 更多