programing

AngularJs 형식의 첫 번째 잘못된 입력에 포커스 설정

lovejava 2023. 3. 10. 20:58

AngularJs 형식의 첫 번째 잘못된 입력에 포커스 설정

저는 AngularJs의 포커스 설정에 관한 기사 및 StackOverflow 질문을 몇 개 읽었습니다.

안타깝게도 제가 읽은 모든 예에서는 포커스를 얻기 위해 요소에 추가할 수 있는 몇 가지 속성이 있다고 가정합니다. 를 들어, focusMe 지시문입니다.

그러나 어떤 입력에 초점을 맞춰야 할지 미리 알 수 없는 경우에는 어떻게 해야 합니까?특히 $invalid set이 있는 형식의 첫 번째 입력 요소, 즉 검증에 실패한 요소에 포커스를 설정하는 방법은 무엇입니까?검증에 실패한 입력이 여러 개 있을 수 있기 때문에, 이것에 근거해 .focus()만을 호출하는 디렉티브는 사용할 수 없습니다(Accessibility/WCAG의 이유로, 이 디렉티브를 클릭하고, 검증에 실패한 최초의 필드를 검출하기 위해서, 키 프레스를 최소한으로 억제하는 것이 좋습니다).

$error 개체는 검증에 실패한 모든 컨트롤을 제공하지만 폼에 나타나는 순서가 아닌 오류 유형별로 그룹화됩니다.

이 일을 할 수 있는 엉터리 방법을 생각해 낼 수 있을 거야.포커스를 설정해야 할 때 일부 브로드캐스트를 수신하는 폼의 지시문입니다. 그러면 해당 지시문이 첫 번째 $valid 요소를 검색할 수 있습니다.그러나 이것은 매우 복잡해 보이고, 나는 이것이 이것을 하기 위한 더 나은 '각선적인' 방법인지 알고 싶다.

그래, 내가 생각했던 것보다 답은 간단했군

제가 필요한 것은 제출 이벤트를 찾는 이벤트 핸들러와 함께 폼 자체를 작성하라는 지시뿐이었습니다.그러면 .ng-invalid 클래스가 있는 첫 번째 요소를 찾기 위해 DOM을 통과할 수 있습니다.

jQLite 사용 예:

myApp.directive('accessibleForm', function () {
    return {
        restrict: 'A',
        link: function (scope, elem) {

            // set up event handler on the form element
            elem.on('submit', function () {

                // find the first invalid element
                var firstInvalid = elem[0].querySelector('.ng-invalid');

                // if we find one, set focus
                if (firstInvalid) {
                    firstInvalid.focus();
                }
            });
        }
    };
});

이 예에서는 Attribute 디렉티브를 사용하고 있으며, 이 디렉티브를 요소 디렉티브(제한: 'E')로 하고, 이 디렉티브를 로 변환하는 템플릿을 포함하도록 확장할 수 있습니다.하지만 이것은 개인적인 취향이다.

angular.element를 사용할 수도 있습니다.

angular.element('input.ng-invalid').first().focus();

보다

<form name="myForm" novalidate="novalidate" data-ng-submit="myAction(myForm.$valid)" autocomplete="off"></form>

컨트롤러

$scope.myAction= function(isValid) {
    if (isValid) {
        //You can place your ajax call/http request here
    } else {
        angular.element('input.ng-invalid').first().focus();
    }
};

ngMessages를 검증에 사용

노저리 방식

angular.element($document[0].querySelector('input.ng-invalid')).focus();

는 패스해야 .$document angular controller(각 )

angular.module('myModule')
.controller('myController', ['$document', '$scope', function($document, $scope){
    // Code Here
}]);

도 있고, 그 '지시문을 쓰다'와 .ng-submit컨트롤러에 로직을 구현합니다.

표시:

<form name='yourForm' novalidate ng-submit="save(yourForm)">
</form>

컨트롤러:

$scope.save = function(yourForm) {
  if (!yourForm.$valid) {
    angular.element("[name='" + yourForm.$name + "']").find('.ng-invalid:visible:first').focus();
    return false;
  }
};

순수 jQuery를 사용하여 첫 번째 비활성 입력을 선택할 수 있습니다.

$('input.ng-invalid').first().focus();

    .directive('accessibleForm', function () {
        return {
            restrict: 'A',
            link: function (scope, elem) {
                // set up event handler on the form element
                elem.on('submit', function () {
                    // find the first invalid element
                    var firstInvalid = elem[0].querySelector('.ng-invalid');
                    if (firstInvalid && firstInvalid.tagName.toLowerCase() === 'ng-form') {
                        firstInvalid = firstInvalid.querySelector('.ng-invalid');
                    }
                    // if we find one, set focus
                    if (firstInvalid) {
                        firstInvalid.focus();
                    }
                });
            }
        };
    })

한동안 이 아이디어를 가지고 놀다가 저처럼 DOM을 기어다니는 것에 반대하는 사람들에게 도움이 될 수 있는 해결책을 생각해 냈습니다.

폼 요소는 일관된 순서(위에서 아래로)로 등록되며, 그 이름과 유효성 확인 상태는 폼 이름이 무엇이든 스코프에서 사용할 수 있습니다(예: $scope.myForm).

이것은 DOM을 기어다니지 않고 대신 각도 js의 내부 구조를 기어다니지 않고 첫 번째 무효 폼 입력을 찾을 수 있는 방법이 있다고 생각하게 합니다.아래는 제 솔루션이지만 폼 요소에 초점을 맞추는 다른 방법이 있다고 가정합니다.저는 커스텀 디렉티브로 브로드캐스트하고 있습니다.브로드캐스트가 요소의 이름과 일치하면 그 자체에 초점을 맞춥니다(이것은 첫 번째 로드에 초점을 맞추는 요소를 제어할 수 있을 때 그 자체로 유용합니다).

첫 번째 비활성(서비스를 통해 컨트롤러와 공유되는 이상적)을 찾는 함수

function findFirstInvalid(form){
    for(var key in form){
        if(key.indexOf("$") !== 0){
            if(form[key].$invalid){
                return key;
            }
        }
    }
}

커스텀 포커스 디렉티브는

directives.directive('focus', function($timeout){
    return {
        require: 'ngModel',
        restrict: 'A',
        link: function(scope, elem, attrs, ctrl){
            scope.$on('inputFocus', function(e, name){
                if(attrs.name === name){
                    elem.focus();
                }
            });
        }
    }
});

나는 이안도켈리가 쓴 훌륭한 해결책을 약간 수정했다.이 솔루션은 스크롤에서 트리거되는 애니메이션을 추가한 후 선택한 요소에 초점을 맞춥니다.

myApp.directive('accessibleForm', function () {
    return {
        restrict: 'A',
        link: function (scope, elem) {

            // set up event handler on the form element
            elem.on('submit', function () {

                // find the first invalid element
                var firstInvalid = elem[0].querySelector('.ng-invalid');

                // if we find one, we scroll with animation and then we set focus
                if (firstInvalid) {
                     angular.element('html:not(:animated),body:not(:animated)')
                    .animate({ scrollTop: angular.element(firstInvalid).parent().offset().top },
                        350,
                        'easeOutCubic',
                        function () {
                            firstInvalid.focus();
                        });
                }
            });
        }
    };
});

한 줄만:

if($scope.formName.$valid){
    //submit
}
else{
    $scope.formName.$error.required[0].$$element.focus();
}

필드 ID를 수신하는 함수(이상적으로는 지시문)인 각 양식 요소에 속성을 추가할 수 있습니다.이 필드 ID는 $error 객체와 어떻게든 관련되어 있어야 합니다.이 함수는 ID가 $error 객체에 있는지 확인하고, ID가 있을 경우 오류의 속성 설정을 반환합니다.

<input id="name" class="{{errorCheck('name')}}">

에러가 발생했을 경우, 이 에러가 생성됩니다.

<input id="name" class="error">

이를 사용하여 유형을 설정할 수 있으며, 이제 오류가 있는 필드를 알 수 있습니다.불행히도 당신은 어느 것이 첫 번째 필드인지 모른다.

한 가지 해결책은 jQuery와 .first 필터를 사용하는 것입니다.이 루트를 이용하는 경우는, http://docs.angularjs.org/api/angular.element 를 참조해 주세요.

또 다른 해결 방법은 폼 필드에 함수의 필드 순서 매개 변수 {{errorCheck('name', 1)}을(를) 추가하는 것입니다.오류 필드 이름을 배열에 푸시한 다음 필드 순서 매개 변수를 기준으로 정렬할 수 있습니다.이렇게 하면 더 유연해질 수 있습니다.

이게 도움이 됐으면 좋겠다.

위의 chaojidan에서 영감을 받아 중첩 각도 1.5.9ng 형식을 사용하는 사용자에게 다음과 같은 변형을 제안했습니다.

class FormFocusOnErr implements ng.IDirective
{
    static directiveId: string = 'formFocusOnErr';

    restrict: string = "A";

    link = (scope: ng.IScope, elem, attrs) =>
    {
        // set up event handler on the form element
        elem.on('submit', function () {

            // find the first invalid element
            var firstInvalid = angular.element(
                elem[0].querySelector('.ng-invalid'))[0];

            // if we find one, set focus
            if (firstInvalid) {
                firstInvalid.focus();
                // ng-invalid appears on ng-forms as well as 
                // the inputs that are responsible for the errors.
                // In such cases, the focus will probably fail 
                // because we usually put the ng-focus attribute on divs 
                // and divs don't support the focus method
                if (firstInvalid.tagName.toLowerCase() === 'ng-form' 
                    || firstInvalid.hasAttribute('ng-form') 
                    || firstInvalid.hasAttribute('data-ng-form')) {
                    // Let's try to put a finer point on it by selecting 
                    // the first visible input, select or textarea 
                    // that has the ng-invalid CSS class
                    var firstVisibleInvalidFormInput = angular.element(firstInvalid.querySelector("input.ng-invalid,select.ng-invalid,textarea.ng-invalid")).filter(":visible")[0];
                    if (firstVisibleInvalidFormInput) {
                        firstVisibleInvalidFormInput.focus();
                    }
                }
            }
        });            
    }
}

// Register in angular app
app.directive(FormFocusOnErr.directiveId, () => new FormFocusOnErr());

그 이유는focus()는 jqLite 및 Angular docs on 요소에서 지원되지 않습니다.

@Sajan이 말한 약간의 수정이 나에게 효과가 있었다.

angular.element("[name='" + this.formName.$name + "']").find('.ng-invalid:visible:first')[0].focus();

비방향성 기반 방식은 다음과 같습니다.각 페이지 하단에 실제로 바닥글의 index.html에 있는 '다음' 버튼이 있기 때문에 이 버튼을 사용했습니다.이 코드를 main.js에서 사용합니다.

if (!$scope.yourformname.$valid) {
      // find the invalid elements
      var visibleInvalids = angular.element.find('.ng-invalid:visible');


      if (angular.isDefined(visibleInvalids)){
        // if we find one, set focus
        visibleInvalids[0].focus();
      }

      return;
    }

언급URL : https://stackoverflow.com/questions/20365121/set-focus-on-first-invalid-input-in-angularjs-form