elementref - viewchild angular 6 example
@viewChild no funciona: no se puede leer la propiedad nativeElement de undefined (3)
Estoy tratando de acceder a un elemento nativo para centrarme en él cuando se hace clic en otro elemento (como el atributo html "para", ya que no se puede usar en elementos de este tipo.
Sin embargo me sale el error:
TypeError: no se puede leer la propiedad ''nativeElement'' de undefined
Intento console.log el nativeElement en ngAfterViewInit()
para que se cargue pero todavía arroja el error.
También accedo a nativeElement en el controlador de eventos de clic, para poder enfocar el elemento cuando se hace clic en otro elemento. ¿Es esto posiblemente lo que lo está jodiendo, porque se compila antes de que se cargue la vista?
p.ej:
ngAfterViewInit() {
console.log(this.keywordsInput.nativeElement); // throws an error
}
focusKeywordsInput(){
this.keywordsInput.nativeElement.focus();
}
Código completo:
parte relevante de la plantilla html utilizada:
<div id="keywords-button" class="form-group" (click)="focusKeywordsInput()">
<input formControlName="keywords" id="keywords-input" placeholder="KEYWORDS (optional)"/>
<div class="form-control-icon" id="keywords-icon"></div>
</div>
componente.ts:
import { Component, OnInit, AfterViewInit, ViewChild, ElementRef } from ''@angular/core'';
import { REACTIVE_FORM_DIRECTIVES,
FormGroup,
FormBuilder,
Validators,
ControlValueAccessor
} from ''@angular/forms'';
import { NumberPickerComponent } from ''./number-picker.component'';
import { DistanceUnitsComponent } from ''./distance-units.component'';
import { MapDemoComponent } from ''../shared/map-demo.component'';
import { AreaComponent } from ''./area-picker.component'';
import { GoComponent } from ''./go.component'';
import { HighlightDirective } from ''../highlight.directive'';
@Component({
selector: ''find-form'',
templateUrl: ''app/find-page/find-form.component.html'',
styleUrls: [''app/find-page/find-form.component.css''],
directives: [REACTIVE_FORM_DIRECTIVES,
NumberPickerComponent,
DistanceUnitsComponent,
MapDemoComponent,
AreaComponent,
GoComponent]
})
export class FindFormComponent implements OnInit, AfterViewInit {
findForm: FormGroup;
submitted: boolean; // keep track on whether form is submitted
events: any[] = []; // use later to display form changes
@ViewChild(''keywords-input'') keywordsInput;
//comment
constructor(private formBuilder: FormBuilder, el: ElementRef) {}
ngOnInit() {
this.findForm = this.formBuilder.group({
firstname: ['''', [ Validators.required, Validators.minLength(5) ] ],
lastname: ['''', Validators.required],
keywords: [],
area: ['''', Validators.required],
address: this.formBuilder.group({
street: [],
zip: [],
city: []
})
});
this.findForm.valueChanges.subscribe(data => console.log(''form changes'', data));
}
ngAfterViewInit() {
console.log(this.keywordsInput.nativeElement); // throws an error
}
focusKeywordsInput(){
this.keywordsInput.nativeElement.focus();
}
save(isValid: boolean) {
this.submitted = true;
// check if model is valid
// if valid, call API to save customer
console.log(isValid);
}
}
plantilla html completa (probablemente irrelevante):
<form class="text-uppercase" [formGroup]="findForm" (ngSubmit)="save(findForm.value, findForm.valid)">
<div class="row is-heading">
<div class="col-sm-8 offset-sm-2 col-md-6 offset-md-3 col-lg-4 offset-lg-4 input-group">
<h2 class="search-filter-heading heading m-x-auto">find vegan</h2>
</div>
</div>
<div class="row has-error-text">
<div class="col-sm-8 offset-sm-2 col-md-6 offset-md-3 col-lg-4 offset-lg-4 input-group btn-group" style="height:64px;">
<div style="position: relative; display: inline-block; width: 100%;">
<multiselect #multiselect></multiselect>
</div>
</div>
</div>
<div class="row error-text" [style.display]="multiselect.selectedCategories.length < 1 && submitted ? ''block'' : ''none''">
<div class="col-sm-8 offset-sm-2 col-md-6 offset-md-3 col-lg-4 offset-lg-4 form-group input-group btn-group">
<small>Please select at least 1 category.</small>
</div>
</div>
<div class="row is-heading">
<div class="col-sm-8 offset-sm-2 col-md-6 offset-md-3 col-lg-4 offset-lg-4 input-group">
<h2 class="search-filter-heading heading m-x-auto">within</h2>
</div>
</div>
<div class="row">
<div class="col-sm-8 offset-sm-2 col-md-6 offset-md-3 col-lg-4 offset-lg-4 input-group btn-group" style="height:64px;">
<div style="position: relative; display: inline-block;">
<number-picker #numberPicker></number-picker>
</div>
<distance-units></distance-units>
</div>
</div>
<div class="row is-heading">
<div class="col-sm-8 offset-sm-2 col-md-6 offset-md-3 col-lg-4 offset-lg-4 input-group">
<h2 class="search-filter-heading heading m-x-auto">of</h2>
</div>
</div>
<div class="row has-error-text">
<div class="col-sm-8 offset-sm-2 col-md-6 offset-md-3 col-lg-4 offset-lg-4 input-group btn-group" style="height:64px;">
<div style="position: relative; display: inline-block; width: 100%;">
<my-area></my-area>
</div>
</div>
</div>
<div class="row error-text" [style.display]="multiselect.selectedCategories.length < 1 && submitted ? ''block'' : ''none''">
<div class="col-sm-8 offset-sm-2 col-md-6 offset-md-3 col-lg-4 offset-lg-4 form-group input-group btn-group">
<small [hidden]="findForm.controls.firstname.valid || (findForm.controls.firstname.pristine && !submitted)">Please enter an area.</small>
</div>
</div>
<div class="row is-heading">
<div class="col-sm-8 offset-sm-2 col-md-6 offset-md-3 col-lg-4 offset-lg-4 input-group">
<h2 class="search-filter-heading heading m-x-auto">keywords</h2>
</div>
</div>
<div class="row form-group">
<div class="col-sm-8 offset-sm-2 col-md-6 offset-md-3 col-lg-4 offset-lg-4 input-group btn-group" style="height:64px;">
<div style="position: relative; display: inline-block; width: 100%;">
<div id="keywords-button" class="form-group" (click)="focusKeywordsInput()">
<input formControlName="keywords" id="keywords-input" placeholder="KEYWORDS (optional)"/>
<div class="form-control-icon" id="keywords-icon"></div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-8 offset-sm-2 col-md-6 offset-md-3 col-lg-4 offset-lg-4 input-group btn-group" style="height:64px;">
<div style="position: relative; display: inline-block; width: 100%;">
<go></go>
</div>
</div>
</div>
</form>
También obtendrá este error si su elemento de destino está dentro de un elemento oculto. Si este es tu HTML:
<div *ngIf="false">
<span #sp>Hello World</span>
</div>
Tu @ViewChild(''sp'') sp
no estará definido.
Solución
En tal caso, entonces no use *ngIf
.
En su lugar, use una clase para mostrar / ocultar su elemento que se oculta.
<div [class.show]="shouldShow">...</div>
es simple: importa este directorio
import {Component, Directive, Input, ViewChild} from ''@angular/core'';
@ViewChild(''keywords-input'') keywordsInput;
no coincide con id="keywords-input"
id="keywords-input"
Debería ser en su lugar una variable de plantilla:
#keywordsInput
Tenga en cuenta que se debe usar la funda de camello, ya que no está permitido en los nombres de referencia de la plantilla.
@ViewChild()
admite nombres de variables de plantilla como cadena:
@ViewChild(''keywordsInput'') keywordsInput;
o tipo de componente o directiva:
@ViewChild(MyKeywordsInputComponent) keywordsInput;
Consulte también https://.com/a/35209681/217408
Insinuación:
keywordsInput
no se establece antes de ngAfterViewInit()