tablas reactivos pasar parametros formularios entre comunicacion componentes angular

reactivos - pasar parametros entre componentes angular 4



¿Por qué las variables locales de la plantilla angular2 no se pueden usar en las plantillas cuando se usa*ngIf? (1)

En cuanto a una solución al problema de enfoque, puede crear una directiva de atributos, focusMe :

import {Component, Directive, ElementRef} from ''angular2/core''; @Directive({ selector: ''[focusMe]'' }) export class FocusDirective { constructor(private el: ElementRef) {} ngAfterViewInit() { this.el.nativeElement.focus(); } } @Component({ selector: ''my-app'', directives: [FocusDirective], template: `<h1>My First Angular 2 App</h1> <button (click)="toggle()">toggle</button> <input focusMe *ngIf="isVisible"> ` }) export class AppComponent { constructor() { console.clear(); } private isVisible = false; toggle() { this.isVisible = !this.isVisible; } }

Plunker

Actualización 1 : Agregar la solución para la función de reenfoque:

import {Component, Directive, ElementRef, Input} from ''angular2/core''; @Directive({ selector: ''[focusMe]'' }) export class FocusMe { @Input(''focusMe'') hasFocus: boolean; constructor(private elementRef: ElementRef) {} ngAfterViewInit() { this.elementRef.nativeElement.focus(); } ngOnChanges(changes) { //console.log(changes); if(changes.hasFocus && changes.hasFocus.currentValue === true) { this.elementRef.nativeElement.focus(); } } } @Component({ selector: ''my-app'', template: `<h1>My First Angular 2 App</h1> <button (click)="showInput()">Make it visible</button> <input *ngIf="inputIsVisible" [focusMe]="inputHasFocus"> <button (click)="focusInput()" *ngIf="inputIsVisible">Focus it</button> `, directives:[FocusMe] }) export class AppComponent { private inputIsVisible = false; private inputHasFocus = false; constructor() { console.clear(); } showInput() { this.inputIsVisible = true; } focusInput() { this.inputHasFocus = true; setTimeout(() => this.inputHasFocus = false, 50); } }

Plunker

Una alternativa al uso de setTimeout() para restablecer la propiedad de foco a false sería crear una propiedad de evento / salida en FocusDirective, y emit() un evento cuando se llama a focus() . El AppComponent entonces escucharía ese evento y restablecería la propiedad de enfoque.

Actualización 2 : Aquí hay una forma alternativa / mejor de agregar la función de reenfoque, usando ViewChild. No necesitamos rastrear el estado de enfoque de esta manera, ni necesitamos una propiedad de entrada en la directiva FocusMe.

import {Component, Directive, ElementRef, Input, ViewChild} from ''angular2/core''; @Directive({ selector: ''[focusMe]'' }) export class FocusMe { constructor(private elementRef: ElementRef) {} ngAfterViewInit() { // set focus when element first appears this.setFocus(); } setFocus() { this.elementRef.nativeElement.focus(); } } @Component({ selector: ''my-app'', template: `<h1>My First Angular 2 App</h1> <button (click)="showInput()">Make it visible</button> <input *ngIf="inputIsVisible" focusMe> <button (click)="focusInput()" *ngIf="inputIsVisible">Focus it</button> `, directives:[FocusMe] }) export class AppComponent { @ViewChild(FocusMe) child; private inputIsVisible = false; constructor() { console.clear(); } showInput() { this.inputIsVisible = true; } focusInput() { this.child.setFocus(); } }

Plunker

Actualización 3 : Aquí hay otra alternativa que no requiere una directiva, que aún usa ViewChild, pero accedemos al niño a través de una variable de plantilla local en lugar de una directiva de atributos (gracias a @alexpods por la sugerencia ):

import {Component, ViewChild, NgZone} from ''angular2/core''; @Component({ selector: ''my-app'', template: `<h1>Focus test</h1> <button (click)="showInput()">Make it visible</button> <input #input1 *ngIf="input1IsVisible"> <button (click)="focusInput1()" *ngIf="input1IsVisible">Focus it</button> `, }) export class AppComponent { @ViewChild(''input1'') input1ElementRef; private input1IsVisible = false; constructor(private _ngZone: NgZone) { console.clear(); } showInput() { this.input1IsVisible = true; // Give ngIf a chance to render the <input>. // Then set the focus, but do this outside the Angualar zone to be efficient. // There is no need to run change detection after setTimeout() runs, // since we''re only focusing an element. this._ngZone.runOutsideAngular(() => { setTimeout(() => this.focusInput1(), 0); }); } setFocus(elementRef) { elementRef.nativeElement.focus(); } ngDoCheck() { // if you remove the ngZone stuff above, you''ll see // this log 3 times instead of 1 when you click the // "Make it visible" button. console.log(''doCheck''); } focusInput1() { this.setFocus(this.input1ElementRef); } }

Plunker

Actualización 4 : Actualicé el código en la Actualización 3 para usar NgZone para que no cause que el algoritmo de detección de cambios de Angular se ejecute después de que setTimeout() . (Para más información sobre la detección de cambios, vea esta respuesta ).

Actualización 5 : Actualicé el código en el plunker anterior para usar Renderer para que sea seguro para el trabajador web. nativeElement se nativeElement acceder a focus() directamente en nativeElement .

focusInput1() { this._renderer.invokeElementMethod( this.input1ElementRef.nativeElement, ''focus'', []); }

Aprendí mucho de esta pregunta.

La parte 1 "#test" no está definida cuando se usa * ngIf

Al hacer referencia a una entrada que puede ocultarse / "destruirse" (porque se usa * ngIf y algunos de los elementos se destruyen), la variable local creada por la sintaxis hashtag # (#test en el ejemplo a continuación) de angular2 no funciona , incluso cuando el elemento existe en la página.

El código era:

@Component({ selector: ''my-app'', template: `<h1>My First Angular 2 App</h1> <button (click)="focusOther(test)">test</button> <input #test *ngIf="boolValue" > ` }) export class AppComponent { private isVisible = false; focusOther(testElement){ this.isVisible = true; alert(testElement); testElement.focus(); } }

La alerta muestra "indefinido", porque no se pasa nada a esa función.

¿Hay una solución para que funcione? Mi objetivo es enfocar un elemento que será creado.

Solución dada por Mark Rajcok: haga una directiva con afterViewInit que use elementRef y llame a .focus () en el elemento.

Ver este plunker para una versión de trabajo de la parte 1: http://plnkr.co/edit/JmBBHMo1hXLe4jrbpVdv?p=preview

Parte 2: cómo reenfocar ese elemento después de la creación inicial

Una vez que se solucione este problema de "enfoque después de la creación", necesito una manera de volver a enfocar () un componente, como en "test.focus ()" (donde #test es el nombre de la variable local para la entrada, pero no puede ser utilizado así como lo demostré antes).

Múltiples soluciones dadas por Mark Rajcok