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
'programing' 카테고리의 다른 글
ESLint는 Create React App에 어떻게 통합됩니까? (0) | 2023.03.10 |
---|---|
JSON 키에 따옴표로 묶인 문자열을 사용해야 하는 실질적인 이유가 있습니까? (0) | 2023.03.10 |
Express 및 ejs <%=를 사용하여 JSON 렌더링 (0) | 2023.03.10 |
JObject 계층에서 이름으로 특정 JToken 검색 (0) | 2023.03.10 |
리액트 아이콘 스타일링 방법 (0) | 2023.03.10 |