AngularJs 양식의 첫 번째 잘못된 입력에 초점 설정
AngularJs의 포커스 설정과 관련된 여러 기사와 StackOverflow 질문을 읽었습니다.
불행히도 내가 읽은 모든 예제는 포커스를 얻기 위해 요소에 추가 할 수있는 몇 가지 속성 (예 : focusMe 지시문) 이 있다고 가정합니다 .
그러나 포커스를 설정할 입력을 미리 알지 못하면 어떻게합니까? 특히 $ invalid 세트가있는 양식의 첫 번째 입력 요소, 즉 유효성 검사에 실패한 요소에 포커스를 설정하는 방법은 무엇입니까? 유효성 검사에 실패하는 입력이 여러 개있을 수 있으므로이를 기반으로 .focus () 호출을 시도하는 지시문을 사용할 수 없습니다. (저는 접근성 / WCAG 이유로이 작업을 수행하고 있으며, 확인에 실패한 첫 번째 필드를 찾기 위해 키 누름을 최소화하기 위해 제출을 클릭하는 것이 좋습니다).
$ error 개체는 유효성 검사에 실패한 모든 컨트롤을 제공하지만 양식에 나타나는 순서가 아닌 실패 유형별로 그룹화됩니다.
이 작업을 수행하는 약간의 방법을 생각해 낼 수 있다고 확신합니다. 포커스를 설정해야 할 때 일부 브로드 캐스트를 수신하는 양식의 지시문-해당 지시문은 첫 번째 $ invalid 요소를 검색 할 수 있습니다. 그러나 이것은 매우 복잡해 보이며 이것이 더 나은 '각진'방법인지 알고 싶습니다.
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();
}
};
유효성 검사를 위해 ngMessage를 사용했습니다.
no jquery 방식
angular.element($document[0].querySelector('input.ng-invalid')).focus();
이 방법을 사용할 때 $document
각도 컨트롤러에서 매개 변수 로 전달해야합니다.
angular.module('myModule')
.controller('myController', ['$document', '$scope', function($document, $scope){
// Code Here
}]);
네, 대답은 생각보다 간단했습니다.
필요한 것은 제출 이벤트를 찾는 이벤트 핸들러와 함께 양식 자체에 배치하는 지시문뿐이었습니다. 그러면 DOM을 탐색하여 .ng-invalid 클래스가있는 첫 번째 요소를 찾을 수 있습니다.
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 지시문을 사용하며,이를 요소 지시문 (restrict : 'E')이되도록 예제를 확장하고이를. 그러나 이것은 개인적인 취향입니다.
다른 답변으로 지시문을 만들거나 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();
}
});
}
}
});
iandotkelly가 작성한 훌륭한 솔루션을 약간 수정했습니다. 이 솔루션은 스크롤시 트리거되는 애니메이션을 추가하고 그 후에 선택한 요소에 초점을 맞 춥니 다.
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 객체에 있는지 확인하고, 그렇다면 오류에 대한 속성 설정을 반환합니다.
<input id="name" class="{{errorCheck('name')}}">
오류가 발생하면이를 생성합니다.
<input id="name" class="error">
이를 사용하여 스타일을 설정할 수 있으며 이제 오류가있는 필드를 알 수 있습니다. 불행히도 당신은 첫 번째 필드가 무엇인지 모릅니다.
한 가지 해결책은 jQuery와 .first 필터를 사용하는 것입니다. 이 경로로 가면 http://docs.angularjs.org/api/angular.element를 확인 하십시오.
Another solution would be to add into your form fields a field order parameter for the function: {{errorCheck('name', 1)}}. You could push the error field names to an array, then sort them by the field order parameter. This could give you more flexibility.
Hope this helps.
I was inspired by chaojidan above to suggest this variation for those who are using nested angular 1.5.9 ng-forms:
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());
That's because focus()
is not supported in jqLite and from the Angular docs on element.
A minor tweak with what @Sajan said worked for me,
angular.element("[name='" + this.formName.$name + "']").find('.ng-invalid:visible:first')[0].focus();
A non-directive based method could look like this. It is what i used, since i have a 'next' button at the bottom of each page that is actually in index.html in the footer. I use this code in 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
'UFO ET IT' 카테고리의 다른 글
관리자를 사용할 수 없습니다. (0) | 2020.12.03 |
---|---|
SQL 명령에 대한 명령 시간 초과 늘리기 (0) | 2020.12.03 |
iOS Swift를 사용한 NSURLConnection (0) | 2020.12.03 |
R의 magritrr에서 %> %와 같은 파이썬의 기능성 파이프 (0) | 2020.12.03 |
오류 404.3 JSON 파일을 찾을 수 없습니다. (0) | 2020.12.02 |