Почему документ пуст?
** ОБНОВЛЕНО ** решением, которое близко к работе:
Я пытаюсь получить ссылку "Перейти к содержимому", чтобы перейти к первому фокусируемому элементу после "#content-start".
Логин-base.component.ts:
import { Component, OnInit } from '@angular/core';
import { Inject, Injectable } from '@angular/core';
import { DOCUMENT } from '@angular/platform-browser';
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.scss']
})
export class BaseLoginComponent implements OnInit {
constructor(
@Inject(DOCUMENT) private document: any
) {
}
skip() {
console.log(document);
console.log(document.querySelector);
var content = document.querySelector(`#content-start`); // ?? document is null!!
if (content) {
var control = content.querySelector('input, button, a');
console.log(control);
//if (control) {
// control.focus(); // first only
//}
}
};
ngOnInit() {
this.document.getElementById('skipLink').onclick = this.skip;
this.document.getElementById('skipLink').onkeypress = function (e) {
if (e.keyCode == 13) {
this.skip();
}
}
}
}
login.component.html:
<div class="login-page">
<section class="main container" id="content-start">
<input type="text"/>
Это на самом деле работает, поскольку console.log(control) возвращает
<input _ngcontent-c4="" id="username" name="username">
что на самом деле правильный контроль.
Но я не могу просто установить.focus(), потому что у меня есть фрагмент HTML, а не объект с методами, такими как.focus();
А есть ли угловой эквивалент $(control) в jQuery?
3 ответа
Как вы узнали, skipLink
должен быть методом класса вашего компонента. Для того, чтобы поддерживать правильный this
Внутри skipLink
, вы можете установить обработчики событий с addEventListener
и функции стрелок:
public ngOnInit() {
this.document.getElementById('skipLink').addEventListener("click", () => {
this.skipLink();
});
this.document.getElementById('skipLink').addEventListener("keypress", (e) => {
if (e.keyCode == 13) {
this.skipLink();
}
}
}
private skipLink() {
let control: HTMLElement = this.document.querySelector('input, button, a');
if (control) {
control.focus();
}
}
Вы можете увидеть код на работе в этом поршне.
Как упомянул Кевин, используя ViewChild
это более стандартный способ ссылки на элемент в компоненте. Вы можете определить ссылочную переменную шаблона на целевом элементе (например, #firstButton
в шаблоне компонента ниже), получить ссылку на него с ViewChild
и получить сам HTML-элемент с nativeElement
имущество. Что касается обработчиков событий, вы можете установить их с угловой привязкой (например, (click)="skipLink()"
).
Этот метод показан в этом плункере:
import { Component, NgModule, Inject, ElementRef, ViewChild } from '@angular/core';
...
@Component({
selector: 'my-app',
template: `
<button #firstButton>Focusable Button</button>
<br/>
<button (click)="skipLink()">Click here to set focus on first button</button>
`,
...
})
export class App {
@ViewChild("firstButton") private firstButton: ElementRef;
private skipLink() {
this.firstButton.nativeElement.focus();
}
}
Это происходит потому, что DOM еще не загружен в ngOnInit
, Обновите ваш код, чтобы он выглядел так, реализуя AfterViewInit
:
export class AppComponent implements AfterViewInit{
constructor(
@Inject(DOCUMENT) private document: any
) { }
}
ngAfterViewInit() {
this.document.getElementById('skipLink').onclick = skipLink;
this.document.getElementById('skipLink').onkeypress = function (e) {
if (e.keyCode == 13) {
skipLink();
}
}
function skipLink() {
let content: HTMLElement = this.document.querySelector("#content-start"); // ?? document is null!!
if (content) {
let control: HTMLElement = this.document.querySelector('input, button, a');
console.log(control);
if (control) {
// control.focus(); // first only
}
}
}
}
ngAfterViewInit
делает именно так, как это звучит; он запускается только после начальной загрузки представления.
Отредактируйте в ответ на правку вашего вопроса: Вы ищете angular.element. Документация по этому вопросу действительно полезна и является лучшей практикой программирования для манипулирования элементом в Angular.
Это довольно далеко от первоначальной реализации; если я обновлю вступительный пост, комментарии не будут иметь смысла.
Следуя совету Кевина по реализации ViewChild в Angular для доступа к дочернему компоненту, директиве или элементу DOM(если только я не неправильно понял):
import { Component, ViewChild, AfterViewInit, ElementRef } from '@angular/core';
export class AppComponent {
@ViewChild('firstControl') firstControl: ElementRef;
skipLink() {
console.log(this.firstControl);
//if (this.firstControl) { this.firstControl.focus(); }
};
,
<a href="#content-start" id="skipLink" (click)="skipLink()">Skip to main content</a>
К сожалению, это не лучше. this.firstControl не определен.