简体   繁体   English

如何在 Angular 2 中打开模态元素后立即将焦点集中在模态元素上?

[英]How to set focus on the elements of the modal as soon as they are opened in Angular 2?

I am a newbie to Angular JS and with the new version of Angular 2 in place, I am facing trouble implementing the directive which can handle the force focus on the modal which is opened on clicking a button.我是 Angular JS 的新手,并且有了新版本的 Angular 2,我在实现指令时遇到了麻烦,该指令可以处理单击按钮时打开的模态上的强制焦点。

There are several similar questions which were asked in the past and the answers are in Angular 1 as follows:过去曾问过几个类似的问题,答案在 Angular 1 中如下:

app.directive('focusMe',
    ['$timeout',
        function ($timeout) {
            return {
                link: {
                    pre: function preLink(scope, element, attr) {
                      // ...
                    },
                    post: function postLink(scope, element, attr) {
                        $timeout(function () {
                            element[0].focus();
                        }, 0);

                    }
                }
            }
        }]);
});

I am trying to convert this same piece of code in Angular 2. But I am not sure how to achieve it.我正在尝试在 Angular 2 中转换同一段代码。但我不确定如何实现它。 Could anyone point me in the right direction by giving me more information on how to achieve this.任何人都可以通过向我提供有关如何实现这一目标的更多信息来指出我正确的方向。

Edit:编辑:

I tried to implement the directive as follows and when I debug the code, I even see that this directive is being called, but I am still unable to get the focus on the elements on the modal dialog:我尝试按如下方式实现该指令,当我调试代码时,我什至看到正在调用该指令,但我仍然无法将焦点放在模态对话框上的元素上:

import { Directive, ElementRef } from "@angular/core";

@Directive({
    selector: "[ModFocus]"
})

export class ModalFocus {

    constructor(private _el: ElementRef) {

        this._el.nativeElement.focus();
    }

}

Am I doing something wrong here?我在这里做错了吗? Or do I have to do something else other than just calling focus() on the nativeElement?或者除了在 nativeElement 上调用 focus() 之外,我还必须做其他事情吗?

HTML Modal: HTML 模态:

<div class="modal-dialog modal-sm" tabindex="-1">
        <div class="modal-content">
            <div class="modal-header">
                <h4 class="modal-title">Are you sure?</h4>
            </div>
            <div class="modal-body">
                Warning
            </div>
        <div class="modal-footer ok-cancel" ModFocus>
                <button type="button" class="btn btn-default" (click)="cancel()">Cancel</button>
                <button type="button" class="btn btn-primary" (click)="delete()" data-dismiss="modal">Delete</button>
            </div>
        </div>
    </div>

Thank you.谢谢你。

When you create a component with Angular 2, you use a different syntax comparing to AngularJS. 使用Angular 2创建组件时,与AngularJS相比,使用不同的语法。 Your sample code might look like: 您的示例代码可能如下所示:

import { Component, ElementRef, ViewChild } from "@angular/core";

@Component({
    selector: "whatever",
    template: `<input #myControl type='input'/>`
})
export class MyComponent {
    @ViewChild("myControl") myCtrl: ElementRef;

    constructor () {
        // This is wrong. It should be done in ngOnInit not in the
        // constructor as the element might not yet be available.
        //this.myCtrl.nativeElement.focus();   
    }
}

I was writing this from top of my mind without checking it, but this should give you a pretty good idea about the direction in which you should go. 我在没有检查的情况下从头脑中写出这个,但是这应该让你对你应该去的方向有个很好的了解。

UPDATE: 更新:

As you updated the question, here is something that I think is wrong. 当你更新问题时,我认为这是错误的。 In your new code you are setting the focus in the constructor. 在新代码中,您将在构造函数中设置焦点。 It might be the case that your view is still not generated and therefore the element to which you want to set the focus is still not available ( in my previous example I misguided you as I instantiated it in the constructor, when I wanted OnInit . I apologize for that. ). 可能是您的视图仍然没有生成,因此您想要设置焦点的元素仍然不可用( 在我之前的示例中,当我想要OnInit时,我在构造函数中实例化它时误导了您。为此道歉。 I would do the following: 我会做以下事情:

import { Directive, ElementRef, OnInit } from "@angular/core";

@Directive({
    selector: "[ModFocus]"
})

export class ModalFocus implements OnInit {

    constructor(private _el: ElementRef) {

    }

    ngOnInit(): any {
        // At this point, your element should be available.
        this._el.nativeElement.focus();
    }
}

OnInit is one of the lifecycle hooks that Angular 2 emits. OnInit是Angular 2发出的生命周期钩子之一。 I would suggest that you go through them to get the better understanding when they are invoked. 我建议你通过它们来获得更好的理解。

UPDATE 2: 更新2:

The problem is that Directives don't have templates. 问题是Directives没有模板。 The act upon the element to which they were added. 对添加它们的元素的行为。 When a directives is created its constructor looks like: 创建指令时,其构造函数如下所示:

constructor(private el: ElementRef, private renderer: Renderer) { } 构造函数(private el:ElementRef,private renderer:Renderer){}

The el should have access to this.el.nativeElement.focus() el应该可以访问this.el.nativeElement.focus()

Have a look at this article on angular.io about Attribute Directives 看看关于Attribute Directives的 angular.io上的这篇文章

My implementation of directive in my question was actually correct. 我在问题中执行指令实际上是正确的。 The problem why the focus was not going onto the modal was because of the tabindex = -1 placement was wrong. 焦点没有进入模态的问题是因为tabindex = -1放置错误。

The following is the directive which I created. 以下是我创建的指令。 I didn't use the ElementRef anymore directly. 我没有直接使用ElementRef Instead, I used the Renderer as Angular docs clearly mentioned to avoid the classes which are tagged with security risk . 相反,我使用Renderer作为明确提到的Angular文档来避免标记有安全风险的类

import { Directive, ElementRef, Renderer} from "@angular/core";
@Directive({
    selector: "[ModFocus]"
})

export class modalFocus {
    constructor(private _el: ElementRef, private renderer: Renderer) {
        this.renderer.invokeElementMethod(this._el.nativeElement, 'focus');
    }

}

HTML: HTML:

<div class="modal fade" tabindex="-1"> 
<div class="modal-dialog modal-sm">
        <div class="modal-content">
            <div class="modal-header">
                <h4 class="modal-title">Are you sure?</h4>
            </div>
            <div class="modal-body">
                Warning
            </div>
        <div class="modal-footer ok-cancel">
                <button type="button" class="btn btn-default" (click)="cancel()" ModFocus>Cancel</button>
                <button type="button" class="btn btn-primary" (click)="delete()" data-dismiss="modal">Delete</button>
            </div>
        </div>
    </div>
</div>

In the above html, I was actually missing the tabindex on the main tag with class modal fade. 在上面的html中,我实际上错过了使用类模态淡入淡出的主标签上的tabindex。 Adding tabindex there took the focus to the buttons on the modal when opened. 添加tabindex会在打开时将焦点集中在模态上的按钮上。

Husein gave valuable inputs which were really helpful. Husein提供了宝贵的意见,这些意见非常有用。 Hence, I am accepting his answer. 因此,我接受他的回答。 Thank you once again Husein. 再次感谢Husein。

trapFocus(){
    // add all the elements inside modal which you want to make focusable
const  focusableElements = 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])';
const modal:any = document.querySelector('#deactivate-modal'); // select the modal by it's id

const firstFocusableElement = modal.querySelectorAll(focusableElements)[0]; // get first element to be focused inside modal
const focusableContent = modal.querySelectorAll(focusableElements);
const lastFocusableElement = focusableContent[focusableContent.length - 1]; // get last element to be focused inside modal


document.addEventListener('keydown', function(e) {
let isTabPressed = e.key === 'Tab' || e.keyCode === 9;

if (!isTabPressed) {
return;
}

if (e.shiftKey) { // if shift key pressed for shift + tab combination
if (document.activeElement === firstFocusableElement) {
  lastFocusableElement.focus(); // add focus for the last focusable element
  e.preventDefault();
}
} else { // if tab key is pressed
if (document.activeElement === lastFocusableElement) { // if focused has reached to last focusable element then focus first focusable element after pressing tab
  firstFocusableElement.focus(); // add focus for the first focusable element
  e.preventDefault();
}
}
});

firstFocusableElement.focus();

  }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 角度模态打开后设置选项 - Set options after angular modal opened 打开模态时,如何将按钮聚焦在模态内 - How do I focus a button inside modal when the modal is opened 当模态打开时,如何将焦点设置在模态内部的第一个 TouchableHighlight 组件(或另一个,例如由 ref 给出)上? - How can I set focus on the first TouchableHighlight component (or another one, given by ref for instance) inside the modal when modal is opened? 如何设置模式输入的重点? - How to set focus on input in modal? 如何在新字段出现时立即将焦点传递给新字段(角度1.4)? - How to pass focus to a new field as soon as it appears (angular 1.4)? 如何在Firefox中将焦点设置为已打开的选项卡? - How to set focus to already opened tab in firefox? 如何测试$ modal是否在Angular / Jasmine中正确打开? - How to test if $modal is opened in Angular/Jasmine properly? 如何将焦点设置在 javascript 模态 window 上? - How to set the focus on a javascript modal window? Angular 2+如何在打开模态时关注模态输入? - Angular 2+ how to get focus to modal inputs on opening the modal? 角ui引导程序模态在打开状态下,如何在控制器中关闭? - angular ui bootstrap modal opened in state, how to close in controller?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM