2

基本上,我想要完成的是在尝试提交表单后将焦点设置到第一个无效元素。此时,我将元素标记为无效,并且我可以获取$name元素的,因此我知道它是哪一个。

它正在“工作”,但正在抛出“$apply already in progress”错误......
所以我一定在这里做错了:)

到目前为止,这是我的代码:

$scope.submit = function () {

    if ($scope.formName.$valid) {
        // Good job.
    }
    else 
    {
        var field = null,
            firstError = null;
        for (field in $scope.formName) {
            if (field[0] != '$')
            {
                if (firstError === null && !$scope.formName[field].$valid) {
                    firstError = $scope.formName[field].$name;
                }

                if ($scope.formName[field].$pristine) {
                    $scope.formName[field].$dirty = true;
                }
            }
        }

        formName[firstError].focus();
    }
}

我的字段循环是基于这个解决方案的,我已经读过这个问题几次。似乎首选的解决方案是创建一个指令,但是向每个表单元素添加一个指令似乎有点过头了

有没有更好的方法来处理这个指令?

4

3 回答 3

2

指令代码:

app.directive('ngFocus', function ($timeout, $log) {
return {
    restrict: 'A',
    link: function (scope, elem, attr) {

        scope.$on('focusOn', function (e, name) {
            // The timeout lets the digest / DOM cycle run before attempting to set focus
            $timeout(function () {
                if (name === attr.ngFocusId) {
                    if (attr.ngFocusMethod === "click")
                        angular.element(elem[0]).click();
                    else
                        angular.element(elem[0]).focus();
                }
            });
        })
    }
}
});

控制器中使用的工厂:

app.factory('focus', function ($rootScope, $timeout) {
    return function (name) {
        $timeout(function () {
            $rootScope.$broadcast('focusOn', name);
        }, 0, false);
    };
});

样品控制器:

angular.module('test', []).controller('myCtrl', ['focus', function(focus) {
  focus('myElement');
}
于 2014-01-03T20:56:59.967 回答
0

建立一个指令绝对是要走的路。否则没有干净的方法可以在 angularjs 中选择元素。它只是不是这样设计的。我建议你在这个问题上查看这个问题。

您不必为每个表单元素创建一个指令。对每个表格都足够了。在指令中,您可以使用element.find('input');. 对于焦点本身,我认为您需要包含 jQuery 并使用它的焦点功能。

但是,您可以 - 我不建议这样做 - 直接在控制器中使用 jQuery。通常角度形式验证会添加诸如此类ng-invalid-required的类,您可以将其用作选择器。例如:

$('input.ng-valid').focus();
于 2013-11-08T02:29:38.477 回答
0

根据雨果的反馈,我设法整理了一个指令:

.directive( 'mySubmitDirty', function () {
    return {
        scope: true,
        link: function (scope, element, attrs) {

            var form = scope[attrs.name];

            element.bind('submit', function(event) {
                var field = null;
                for (field in form) {
                    if (form[field].hasOwnProperty('$pristine') && form[field].$pristine) {
                        form[field].$dirty = true;
                    }
                }

                var invalid_elements = element.find('.ng-invalid');
                if (invalid_elements.length > 0)
                {
                   invalid_elements[0].focus();
                }

                event.stopPropagation();
                event.preventDefault();
            });
        }
    };
})

这种方法需要 jquery,因为它element.find()使用一个类来查找 dom 中的第一个无效元素。

于 2013-11-08T17:01:20.283 回答