Html @viewChild和@ViewChildern给出了未定义的
我正在处理Angular 9,希望在单击按钮后访问输入字段。现在它给了我未定义的。我尝试了Html @viewChild和@ViewChildern给出了未定义的,html,angular,typescript,Html,Angular,Typescript,我正在处理Angular 9,希望在单击按钮后访问输入字段。现在它给了我未定义的。我尝试了@ViewChild和@viewChildern,因为我正在使用ngIf Template.html文件 <div class="search-input" #searchDiv *ngIf="serachActive"> <input #searched autofocus type="text&q
@ViewChild
和@viewChildern
,因为我正在使用ngIf
Template.html文件
<div class="search-input" #searchDiv *ngIf="serachActive">
<input
#searched
autofocus
type="text"
class="serach-term"
placeholder="Search"
[(ngModel)]="searchTerms"
(ngModelChange)="applySearch()"
/>
<button (click)="toggleSearch(!serachActive)">
<span class="material-icons"> search </span>
</button>
<ul class="search-list">
<li *ngFor="let result of results">
<a [routerLink]="['/', 'video', 'details', result._id]">{{
result.title ? result.title : ''
}}</a>
</li>
</ul>
</div>
import { Component, OnInit,AfterViewInit,ElementRef,ViewChild,ViewChildren } from '@angular/core';
import { UserService } from '../../../user.service';
import { VideoService } from '../../../services/video.service';
import { Subject } from 'rxjs';
import { distinctUntilChanged, debounceTime } from 'rxjs/operators';
import { Router } from '@angular/router';
@Component({
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls: ['./header.component.css'],
})
export class HeaderComponent implements OnInit,AfterViewInit{
serachActive: boolean = false;
@ViewChildren('searched') searchElement: ElementRef;
@ViewChildren("searched") input: ElementRef;
user;
subject = new Subject<string>();
results = [];
searchTerms;
loggedIn: Boolean = false;
constructor(
private userService: UserService,
private videoService: VideoService,
private router: Router
) {
this.user = this.userService.getUser();
this.loggedIn = this.userService.isAuthenticated();
}
ngOnInit() {
console.log('on init', this.input); //undefined
this.subject
.pipe(debounceTime(400), distinctUntilChanged())
.subscribe((value) => {
this.router.navigate(['search'], { queryParams: { term: value } });
});
}
ngAfterViewInit() {
console.log('on after', this.input); //undefined
}
toggleSearch(toggledata) {
this.serachActive = toggledata;
this.results = [];
this.searchTerms = '';
console.log(this.input) //undefined
console.log(this.searchElement.nativeElement) //undefined
}
applySearch() {
const searchText = this.searchTerms;
this.subject.next(searchText);
this.searchElement.nativeElement.focus(); //undefined
}
menuButtonClick(button){
if(button === "history"){
this.router.navigate(['history'])
}
}
}
搜寻
-
{{
result.title?result.title:'
}}
Template.ts文件
<div class="search-input" #searchDiv *ngIf="serachActive">
<input
#searched
autofocus
type="text"
class="serach-term"
placeholder="Search"
[(ngModel)]="searchTerms"
(ngModelChange)="applySearch()"
/>
<button (click)="toggleSearch(!serachActive)">
<span class="material-icons"> search </span>
</button>
<ul class="search-list">
<li *ngFor="let result of results">
<a [routerLink]="['/', 'video', 'details', result._id]">{{
result.title ? result.title : ''
}}</a>
</li>
</ul>
</div>
import { Component, OnInit,AfterViewInit,ElementRef,ViewChild,ViewChildren } from '@angular/core';
import { UserService } from '../../../user.service';
import { VideoService } from '../../../services/video.service';
import { Subject } from 'rxjs';
import { distinctUntilChanged, debounceTime } from 'rxjs/operators';
import { Router } from '@angular/router';
@Component({
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls: ['./header.component.css'],
})
export class HeaderComponent implements OnInit,AfterViewInit{
serachActive: boolean = false;
@ViewChildren('searched') searchElement: ElementRef;
@ViewChildren("searched") input: ElementRef;
user;
subject = new Subject<string>();
results = [];
searchTerms;
loggedIn: Boolean = false;
constructor(
private userService: UserService,
private videoService: VideoService,
private router: Router
) {
this.user = this.userService.getUser();
this.loggedIn = this.userService.isAuthenticated();
}
ngOnInit() {
console.log('on init', this.input); //undefined
this.subject
.pipe(debounceTime(400), distinctUntilChanged())
.subscribe((value) => {
this.router.navigate(['search'], { queryParams: { term: value } });
});
}
ngAfterViewInit() {
console.log('on after', this.input); //undefined
}
toggleSearch(toggledata) {
this.serachActive = toggledata;
this.results = [];
this.searchTerms = '';
console.log(this.input) //undefined
console.log(this.searchElement.nativeElement) //undefined
}
applySearch() {
const searchText = this.searchTerms;
this.subject.next(searchText);
this.searchElement.nativeElement.focus(); //undefined
}
menuButtonClick(button){
if(button === "history"){
this.router.navigate(['history'])
}
}
}
从'@angular/core'导入{Component,OnInit,AfterViewInit,ElementRef,ViewChild,ViewChildren};
从“../../../user.service”导入{UserService};
从“../../../services/video.service”导入{VideoService};
从'rxjs'导入{Subject};
从'rxjs/operators'导入{distinctUntilChanged,debounceTime};
从'@angular/Router'导入{Router};
@组成部分({
选择器:“应用程序标题”,
templateUrl:'./header.component.html',
样式URL:['./header.component.css'],
})
导出类HeaderComponent实现OnInit,AfterViewInit{
serachActive:boolean=false;
@ViewChildren('searched')searchElement:ElementRef;
@ViewChildren(“搜索”)输入:ElementRef;
用户;
主题=新主题();
结果=[];
搜索词;
loggedIn:Boolean=false;
建造师(
私有用户服务:用户服务,
私人视频服务:视频服务,
专用路由器
) {
this.user=this.userService.getUser();
this.loggedIn=this.userService.isAuthenticated();
}
恩戈尼尼特(){
console.log('on init',this.input);//未定义
这个主题
.pipe(去BounceTime(400),distinctUntilChanged())
.订阅((值)=>{
这个.router.navigate(['search'],{queryParams:{term:value}});
});
}
ngAfterViewInit(){
console.log('on after',this.input);//未定义
}
切换搜索(切换数据){
this.serachActive=切换数据;
这个结果=[];
此.searchTerms='';
console.log(this.input)//未定义
console.log(this.searchElement.nativeElement)//未定义
}
applySearch(){
const searchText=this.searchTerms;
this.subject.next(searchText);
this.searchElement.nativeElement.focus();//未定义
}
菜单按钮单击(按钮){
如果(按钮==“历史”){
this.router.navigate(['history'])
}
}
}
使用ViewChild
,因为您只搜索1个元素ID
如果在ViewChild
中添加{static:true}
或{static:false}
选项不符合
改用ChangeDetectorRef
:
@Component({...})
export class AppComponent {
@ViewChild('searchInput') input: ElementRef;
isShow: boolean = false;
constructor(private cdr: ChangeDetectorRef) {}
toggle(): void {
this.isShow = !this.isShow;
this.cdr.detectChanges(); // Detects changes which this.isShow is responsible on showing / hiding
// the element you're referencing to in ViewChild
if (this.isShow) // If element is shown, console the referenced element
console.log(this.input);
}
}
已经创建了一个供您参考的使用
ViewChild
,因为您只搜索一个元素ID
如果在ViewChild
中添加{static:true}
或{static:false}
选项不符合
改用ChangeDetectorRef
:
@Component({...})
export class AppComponent {
@ViewChild('searchInput') input: ElementRef;
isShow: boolean = false;
constructor(private cdr: ChangeDetectorRef) {}
toggle(): void {
this.isShow = !this.isShow;
this.cdr.detectChanges(); // Detects changes which this.isShow is responsible on showing / hiding
// the element you're referencing to in ViewChild
if (this.isShow) // If element is shown, console the referenced element
console.log(this.input);
}
}
已经创建了一个供您参考这里有一个参考:-您可能希望尝试
@ViewChild()
和{static:false}
(因为使用了*ngIf
)@Neelavar我已经尝试过,但仍然得到未定义的。这里有一个参考:-您可能希望尝试@ViewChild()
和{static:false}
(因为使用了*ngIf
)@Neelavar我已经试过了,但是仍然得到未定义的。谢谢,它在工作。@akshayTiwari,问题总是一样的,Angular会生成代码的所有指令并“刷新”应用程序。因此,如果您生成这个。isShow=true;console.log(this.input)
此输入不存在。如果您编写this.isShow=true;this.cdr.detetChanges();console.log(this.input)
此输入的存在是因为“cdr.detectchanges”使应用程序刷新。另一个选项是使用this.isShow=true;setTimeout(()=>{console.log(this.input)}
因为setTimeout下的指令是在Angular刷新应用程序后执行的。谢谢,@Eliseo的这个解释实际上我在试图理解ChangeDetectorRef
是如何解决我的问题的。但是这个解释帮了我很多。谢谢,它起作用了。@akshayTiwari,问题总是一样的,Angular使所有的指令解释代码并“刷新”应用程序。因此,如果您使this.isShow=true;console.log(this.input)
此输入不存在。如果您编写this.isShow=true;this.cdr.detetChanges();console.log(this.input)
此输入存在,因为“cdr.detectchanges”使应用程序刷新。另一个选项是使用this.isShow=true;setTimeout(()=>{console.log(this.input)}
因为setTimeout下的指令是在应用程序刷新后执行的。谢谢@Eliseo的解释。实际上,我正在试图理解ChangeDetectorRef
是如何解决我的问题的。但是这个解释对我帮助很大。