Home > Software design >  How to focus on the newly added HTML element
How to focus on the newly added HTML element

Time:12-08

This my HTML Template.

<div
        cdkDropList
        class="document-columns__list list"
        (cdkDropListDropped)="dragDrop($event)"
    >
        <div
            cdkDrag
            class="list__box"
            *ngFor="let column of columns; let i = index"
            (click)="selectColumn(column)"
            [class.list__box_selected]="column === selectedColumn"
        >
            <div class="list__placeholder" *cdkDragPlaceholder></div>
            <div class="list__content">
                <div class="list__name">
                    {{column.col_num}}. {{column.title}}
                </div>
                <div class="list__type">
                    {{getType(column)?.title}}
                </div>
            </div>
            <p-button
                class="list__button"
                icon="pi pi-trash"
                styleClass="p-button-danger p-button-outlined"
                [disabled]="columns.length === 1"
                (click)="deleteColumn(column)"
            ></p-button>
        </div>
    </div>
    <div class="document-columns__button">
        <p-button
            styleClass="p-button-secondary p-button-outlined"
            (click)="addNewColumn()"
            label="Add column"
            icon="pi pi-plus"
            iconPos="left"
        >
        </p-button>
    </div>

This my TS code.

 public addNewColumn(): void {
    const arrayLength: number = this.columns.length   1;
    this.columns.push({
        col_num: arrayLength,
        type_id: TypeId.Number,
        title: 'New Column',
    });
    this.columnsChanged.emit(this.columns);
    this.recalculateColumnNumbers();
}

When I click the add column button. A new element is created in the array. The template is redrawn with a new element. I want to focus on it after that. How to do it? I've tried this code, but it doesn't work.

document.querySelectorAll('.document-columns__list:last-child').focus();

CodePudding user response:

You could just focus the last element you added in your addNewColumn method. You just need to wait until the element in rendered in the dom. So in my example below I just postponed the focus action using setTimeout It is always recommended to use the angular way to query an html element. So I just used ViewChildren decorator.

@ViewChildren('element', { read: ElementRef }) elements: QueryList<ElementRef>;

 public addNewColumn(): void {
....
  setTimeout(() => 
    this.elements.last.nativeElement.focus()
    );
}

In your template you should just put a template variable #element on the element you want to focus to allow the component class to get access to it.

<div #element></div>

Here is a working example https://stackblitz.com/edit/angular-ivy-nszzdt

CodePudding user response:

@ViewChildren('element', { read: ElementRef }) public elements!: QueryList<ElementRef>;

public addNewColumn(): void {
    const arrayLength: number = this.columns.length   1;
    this.columns.push({
        col_num: arrayLength,
        type_id: TypeId.Number,
        title: 'Add column',
    });
    this.columnsChanged.emit(this.columns);
    this.recalculateColumnNumbers();
    setTimeout(() => this.elements.last.nativeElement.click());
}
  • Related