page change angular

change - page title angular 4



Centrarse en el elemento de entrada reciƩn agregado (5)

Tengo una nueva aplicación Angular 2 con una lista de cuadros de input . Cuando el usuario presiona la tecla de retorno, agrego un nuevo cuadro de input inmediatamente después del que está editando actualmente. O, mejor dicho, agrego (asincrónicamente) una nueva entrada a la matriz en el modelo, lo que hace que Angular 2 genere automáticamente un nuevo cuadro de input en un futuro próximo.

¿Cómo puedo hacer que input foco de input cambie automáticamente al elemento recién agregado?

EDITAR 1:
Alternativamente, obtengo una referencia al objeto modelo que está causando que se genere el DOM. Desde el código del componente, ¿hay alguna forma de buscar un elemento DOM que represente un objeto modelo en particular?

EDITAR 2:
Aquí está mi código para que esto funcione. Esperemos que esto sea lo suficientemente ofensivo para algunos desarrolladores de Angular 2 para alentar una respuesta :-)

app.WordComponent = ng.core .Component({ selector: ''word-editor'', template:''<input type="text" [value]="word.word" (input)="word.update($event.target.value)" (keydown)="keydown($event)"/>'', styles:[ '''' ], properties:[ ''list:list'', ''word:word'' ] }) .Class({ constructor:[ function() { } ], keydown:function(e) { if(e.which == 13) { var ul = e.target.parentNode.parentNode.parentNode; var childCount = ul.childNodes.length; this.list.addWord("").then(function(word) { var interval = setInterval(function() { if(childCount < ul.childNodes.length) { ul.lastChild.querySelector(''input'').focus(); clearInterval(interval); } }, 1); }); } } });


Con código angular en línea, enfoque después de la pintura condicional:

<span *ngIf="editId==item.id"> <input #taskEditText type="text" [(ngModel)]="editTask" (keydown.enter)="save()" (keydown.esc)="saveCancel()"/> <button (click)="save()">Save</button> <button (click)="saveCancel()">Cancel</button> {{taskEditText.focus()}} </span>


Eche un vistazo a ViewChild , aquí hay un example . Esto podría ser lo que estás buscando:

import {Component, ViewChild} from ''angular2/core'' @Component({ selector: ''my-app'', providers: [], template: ` <div> <input #name> </div> `, directives: [] }) export class App { @ViewChild(''name'') vc: ElementRef; ngAfterViewInit() { this.vc.nativeElement.focus(); } }


Para priorizar qué elemento se enfocará al inicializar varias directivas en el mismo ciclo, use:

Directiva:

@Directive({ selector: ''[focusOnInit]'' }) export class FocusOnInitDirective implements OnInit, AfterViewInit { @Input(''focusOnInit'') priority: number = 0; static instances: FocusOnInitDirective[] = []; constructor(public renderer: Renderer, public elementRef: ElementRef) { } ngOnInit(): void { FocusOnInitDirective.instances.push(this) } ngAfterViewInit(): void { setTimeout(() => { FocusOnInitDirective.instances.splice(FocusOnInitDirective.instances.indexOf(this), 1); }); if (FocusOnInitDirective.instances.every((i) => this.priority >= i.priority)) { this.renderer.invokeElementMethod( this.elementRef.nativeElement, ''focus'', []); } } }

Uso:

<input type="text" focusOnInit="9">

https://plnkr.co/edit/T9VDPIWrVSZ6MpXCdlXF


Puede implementar una directiva de texto de entrada simple, para que cada vez que se cree una nueva entrada, se enfoque automáticamente. El método focus() se llama dentro del gancho del ciclo de vida del componente ngAfterViewInit() después de que la vista se haya inicializado completamente.

@Directive({ selector: ''input[type=text]'' }) export class FocusInput implements AfterViewInit { private firstTime: bool = true; constructor(public elem: ElementRef) { } ngAfterViewInit() { if (this.firstTime) { this.elem.nativeElement.focus(); this.firstTime = false; } } }

Use la directiva FocusInput en su componente:

@Component({ selector: ''app'', directives: [FocusInput], template: `<input type="text" (keyup.enter)="last ? addNewWord():0" *ngFor="#word of words; #last = last" [value]="word.word" #txt (input)="word.word = txt.value" />{{words |json}}` }) export class AppComponent { words: Word[] = []; constructor() { this.addNewWord(); } addNewWord() { this.words.push(new Word()); } }

Tenga en cuenta lo siguiente:

  1. El evento (keyup.enter) se usa para detectar cuándo se presiona la tecla <enter>
  2. ngFor se usa para repetir el elemento de entrada para cada palabra del conjunto de words
  3. last es un booleano vinculado a una variable local que es verdadera cuando la entrada es la última
  4. ¿El evento keyup está vinculado a la last ? addNewWord() : 0 expresión last ? addNewWord() : 0 last ? addNewWord() : 0 . Esto garantiza que solo se agregue un nuevo campo de entrada cuando se presiona la tecla <enter> desde la última entrada

Demo Plnkr


Si se me permite hacerlo, tomaré parte de la respuesta de @Sasxa y la modificaré para que se parezca más a lo que estás buscando.

Algunos cambios

  • ngFor un ngFor para que angular2 agregue la nueva entrada en lugar de hacerlo yo mismo. El objetivo principal es simplemente hacer angular2 para iterar sobre él.
  • En lugar de ViewChild , voy a usar ViewChildren que devuelve una QueryList que tiene una propiedad de changes . Esta propiedad es un Observable y devuelve los elementos una vez que han cambiado.

Como en ES5 no tenemos decoradores, tenemos que usar la propiedad de queries para usar ViewChildren

Componente

Component({ selector: ''cmp'', template : ` <div> // We use a variable so we can query the items with it <input #input (keydown)="add($event)" *ngFor="#input of inputs"> </div> `, queries : { vc : new ng.core.ViewChildren(''input'') } })

Centrarse en el último elemento.

ngAfterViewInit: function() { this.vc.changes.subscribe(elements => { elements.last.nativeElement.focus(); }); }

Como dije antes, ViewChildren devuelve una QueryList que contiene propiedades de changes . Cuando nos suscribimos cada vez que cambia, devolverá la lista de elementos. Los elements lista contienen una last propiedad (entre otras) que en este caso devuelve el último elemento, usamos nativeElement en él y finalmente focus()

Agregar elementos de entrada Esto es por pura conveniencia, la matriz de entradas no tiene un propósito real más que volver a dibujar el ngFor .

add: function(key) { if(key.which == 13) { // See plnkr for "this.inputs" usage this.inputs.push(this.inputs.length+1); } }

Empujamos un elemento ficticio en la matriz para que se vuelva a dibujar.

Ejemplo usando ES5: http://plnkr.co/edit/DvtkfiTjmACVhn5tHGex

Ejemplo usando ES6 / TS: http://plnkr.co/edit/93TgbzfPCTxwvgQru2d0?p=preview

Actualización 29/03/2016

El tiempo ha pasado, las cosas se han aclarado y siempre hay mejores prácticas para aprender / enseñar. He simplificado esta respuesta cambiando algunas cosas

  • En lugar de usar @ViewChildren y suscribirme, hice una directiva que se instaurará cada vez que se cree una nueva entrada
  • Estoy usando Renderer para que sea seguro para WebWorker. La respuesta original accede a focus() directamente en nativeElement que se desaconseja.
  • Ahora escucho keydown.enter que simplifica el evento key down, no tengo que verificar which valor.

Al punto. El componente se ve así (código completo simplificado en los plnkrs a continuación)

@Component({ template: `<input (keydown.enter)="add()" *ngFor="#input of inputs">`, }) add() { this.inputs.push(this.inputs.length+1); }

Y la directiva

@Directive({ selector : ''input'' }) class MyInput { constructor(public renderer: Renderer, public elementRef: ElementRef) {} ngOnInit() { this.renderer.invokeElementMethod( this.elementRef.nativeElement, ''focus'', []); } }

Como puede ver, estoy llamando a invokeElementMethod para activar el focus en el elemento en lugar de acceder a él directamente.

Esta versión es mucho más limpia y segura que la original.

plnkrs actualizados a beta 12

Ejemplo usando ES5: http://plnkr.co/edit/EpoJvff8KtwXRnXZJ4Rr

Ejemplo usando ES6 / TS: http://plnkr.co/edit/em18uMUxD84Z3CK53RRe

Actualización 2018

invokeElementMethod está en desuso. Use Renderer2 en lugar de Renderer.

Dele a su elemento una identificación, y puede usar selectRootElement :

this.renderer2.selectRootElement(''#myInput'').focus();