Keyboard Navigation

By default, the keyboard navigation of the Kendo UI TreeList for Angular is disabled. To enable keyboard navigation, set the navigable attribute to true.

The TreeList supports the following keyboard shortcuts:

SHORTCUT DESCRIPTION
Right Arrow Moves the focus one cell to the right. If the focus is on the right-most cell in the row, the focus does not move.
Left Arrow Moves the focus one cell to the left. If the focus is on the left-most cell in the row, the focus does not move.
Down Arrow Moves the focus one cell down. If the focus is on the bottom-most cell in the column, the focus does not move.
Up Arrow Moves the focus one cell up. If the focus is on the top-most cell in the column, the focus does not move.
Page Down Scrolls to the next page of data. If paging is configured, loads the next page of data, if any.
Page Up Scrolls to the previous page of data. If paging is configured, loads the previous page of data, if any.
Home Moves the focus to the first focusable cell in the row.
End Moves the focus to the last focusable cell in the row.
Ctrl & Home Moves the focus to the first cell in the first row.
Ctrl & End Moves the focus to the last cell in the last row.
Alt & Right Arrow Expands the current row, if applicable.
Alt & Left Arrow Collapses the current row, if applicable.
Enter Expands or collapses the current row, if pressed on an expandable, non-editable column; triggers the cell click action.

When Selection is enabled, the TreeList supports the following shortcuts:

SHORTCUT DESCRIPTION
Space Selects the current row or cell.
Ctrl & Space Toggles the selection of the current row or cell.
Shift & Space Selects a range of rows or cells.
Ctrl & A Selects all rows or cells.

When a TreeList cell contains focusable components, the TreeList supports the following shortcuts:

SHORTCUT DESCRIPTION
Enter Disables the keyboard navigation of the TreeList and places the focus on the first widget.
Escape Restores the keyboard navigation of the TreeList. If the content was in the process of editing, the unsaved edits are removed.
Tab Moves the focus to the next focusable component in the current row.
Shift & Tab Moves the focus to the previous focusable component in the current row.
Alphanumeric keys If the cell contains editable content, places the focus in an input field—for example, a textbox.
import { Component } from '@angular/core';
import { SelectableSettings } from '@progress/kendo-angular-treelist';
import { Employee, employees } from './employees';

@Component({
    selector: 'my-app',
    template: `
        <kendo-treelist [kendoTreeListFlatBinding]="data" idField="id" parentIdField="managerId"
                        kendoTreeListSelectable [selectable]="settings" [(selectedItems)]="selected"
                        kendoTreeListExpandable [initiallyExpanded]="true"
                        [navigable]="true"
                        [height]="410">
            <kendo-treelist-checkbox-column [width]="35" [checkChildren]="true">
            </kendo-treelist-checkbox-column>
            <kendo-treelist-column [expandable]="true" field="name" title="Name" [width]="250">
            </kendo-treelist-column>
            <kendo-treelist-column field="title" title="Title" [width]="180"></kendo-treelist-column>
            <kendo-treelist-column field="phone" title="Phone" [width]="180"></kendo-treelist-column>
        </kendo-treelist>
    `
})
export class AppComponent {
    public data: Employee[] = employees;

    public settings: SelectableSettings = {
        mode: 'row',
        multiple: true
    };

    public selected: any[] = [];
}
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { TreeListModule } from '@progress/kendo-angular-treelist';
import { IntlModule } from '@progress/kendo-angular-intl';
import { AppComponent } from './app.component';

@NgModule({
    imports: [
        BrowserModule,
        BrowserAnimationsModule,
        FormsModule,
        TreeListModule,
        IntlModule
    ],
    declarations: [
        AppComponent
    ],
    bootstrap: [
        AppComponent
    ]
})

export class AppModule { }
import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app.module';

enableProdMode();

const platform = platformBrowserDynamic();
platform.bootstrapModule(AppModule);

export interface Employee {
    id: number;
    managerId?: number;
    name: string;
    title: string;
    phone: string;
    hireDate?: Date;
}

export const employees: Employee[] = [
    {
        id: 1,
        name: 'Daryl Sweeney',
        title: 'Chief Executive Officer',
        phone: '(555) 924-9726',
        managerId: null,
        hireDate: new Date('2019-01-15')
    },
    {
        id: 2,
        name: 'Guy Wooten',
        title: 'Chief Technical Officer',
        phone: '(438) 738-4935',
        managerId: 1,
        hireDate: new Date('2019-02-19')
    },
    {
        id: 32,
        name: 'Buffy Weber',
        title: 'VP, Engineering',
        phone: '(699) 838-6121',
        managerId: 2,
        hireDate: new Date('2019-04-13')
    },
    {
        id: 11,
        name: 'Hyacinth Hood',
        title: 'Team Lead',
        phone: '(889) 345-2438',
        managerId: 32,
        hireDate: new Date('2018-01-17')
    },
    {
        id: 60,
        name: 'Akeem Carr',
        title: 'Junior Software Developer',
        phone: '(738) 136-2814',
        managerId: 11,
        hireDate: new Date('2018-01-18')
    },
    {
        id: 78,
        name: 'Rinah Simon',
        title: 'Software Developer',
        phone: '(285) 912-5271',
        managerId: 11,
        hireDate: new Date('2018-03-17')
    },
    {
        id: 42,
        name: 'Gage Daniels',
        title: 'Software Architect',
        phone: '(107) 290-6260',
        managerId: 32,
        hireDate: new Date('2019-03-14')
    },
    {
        id: 43,
        name: 'Constance Vazquez',
        title: 'Director, Engineering',
        phone: '(800) 301-1978',
        managerId: 32,
        hireDate: new Date('2018-03-18')
    },
    {
        id: 46,
        name: 'Darrel Solis',
        title: 'Team Lead',
        phone: '(327) 977-0216',
        managerId: 43,
        hireDate: new Date('2019-04-15')
    },
    {
        id: 47,
        name: 'Brian Yang',
        title: 'Senior Software Developer',
        phone: '(565) 146-5435',
        managerId: 46,
        hireDate: new Date('2019-02-21')
    },
    {
        id: 50,
        name: 'Lillian Bradshaw',
        title: 'Software Developer',
        phone: '(323) 509-3479',
        managerId: 46,
        hireDate: new Date('2019-05-23')
    },
    {
        id: 51,
        name: 'Christian Palmer',
        title: 'Technical Lead',
        phone: '(490) 421-8718',
        managerId: 46,
        hireDate: new Date('2019-04-16')
    },
    {
        id: 55,
        name: 'Summer Mosley',
        title: 'QA Engineer',
        phone: '(784) 962-2301',
        managerId: 46,
        hireDate: new Date('2019-09-21')
    },
    {
        id: 56,
        name: 'Barry Ayers',
        title: 'Software Developer',
        phone: '(452) 373-9227',
        managerId: 46,
        hireDate: new Date('2018-04-16')
    },
    {
        id: 59,
        name: 'Keiko Espinoza',
        title: 'Junior QA Engineer',
        phone: '(226) 600-5305',
        managerId: 46,
        hireDate: new Date('2018-01-22')
    },
    {
        id: 61,
        name: 'Candace Pickett',
        title: 'Support Officer',
        phone: '(120) 117-7475',
        managerId: 46,
        hireDate: new Date('2018-09-18')
    },
    {
        id: 63,
        name: 'Mia Caldwell',
        title: 'Team Lead',
        phone: '(848) 636-6470',
        managerId: 43,
        hireDate: new Date('2018-07-17')
    },
    {
        id: 65,
        name: 'Thomas Terry',
        title: 'Senior Enterprise Support Officer',
        phone: '(764) 831-4248',
        managerId: 63,
        hireDate: new Date('2018-07-14')
    },
    {
        id: 67,
        name: 'Ruth Downs',
        title: 'Senior Software Developer',
        phone: '(138) 991-1440',
        managerId: 63,
        hireDate: new Date('2018-08-14')
    },
    {
        id: 70,
        name: 'Yasir Wilder',
        title: 'Senior QA Engineer',
        phone: '(759) 701-8665',
        managerId: 63,
        hireDate: new Date('2019-08-17')
    },
    {
        id: 71,
        name: 'Flavia Short',
        title: 'Support Officer',
        phone: '(370) 133-9238',
        managerId: 63,
        hireDate: new Date('2018-06-15')
    },
    {
        id: 74,
        name: 'Aaron Roach',
        title: 'Junior Software Developer',
        phone: '(958) 717-9230',
        managerId: 63,
        hireDate: new Date('2018-09-18')
    },
    {
        id: 75,
        name: 'Eric Russell',
        title: 'Software Developer',
        phone: '(516) 575-8505',
        managerId: 63,
        hireDate: new Date('2019-09-13')
    },
    {
        id: 76,
        name: 'Cheyenne Olson',
        title: 'Software Developer',
        phone: '(241) 645-0257',
        managerId: 63,
        hireDate: new Date('2018-09-18')
    },
    {
        id: 77,
        name: 'Shaine Avila',
        title: 'UI Designer',
        phone: '(844) 435-1360',
        managerId: 63,
        hireDate: new Date('2018-01-22')
    },
    {
        id: 81,
        name: 'Chantale Long',
        title: 'Senior QA Engineer',
        phone: '(252) 419-6891',
        managerId: 63,
        hireDate: new Date('2018-09-14')
    },
    {
        id: 83,
        name: 'Dane Cruz',
        title: 'Junior Software Developer',
        phone: '(946) 701-6165',
        managerId: 63,
        hireDate: new Date('2019-03-15')
    },
    {
        id: 84,
        name: 'Regan Patterson',
        title: 'Technical Writer',
        phone: '(265) 946-1765',
        managerId: 63,
        hireDate: new Date('2019-05-17')
    },
    {
        id: 85,
        name: 'Drew Mckay',
        title: 'Senior Software Developer',
        phone: '(327) 293-0162',
        managerId: 63,
        hireDate: new Date('2019-05-21')
    },
    {
        id: 88,
        name: 'Bevis Miller',
        title: 'Senior Software Developer',
        phone: '(525) 557-0169',
        managerId: 63,
        hireDate: new Date('2018-08-15')
    },
    {
        id: 89,
        name: 'Bruce Mccarty',
        title: 'Support Officer',
        phone: '(936) 777-8730',
        managerId: 63,
        hireDate: new Date('2019-10-21')
    },
    {
        id: 90,
        name: 'Ocean Blair',
        title: 'Team Lead',
        phone: '(343) 586-6614',
        managerId: 43,
        hireDate: new Date('2018-06-20')
    },
    {
        id: 91,
        name: 'Guinevere Osborn',
        title: 'Software Developer',
        phone: '(424) 741-0006',
        managerId: 90,
        hireDate: new Date('2019-06-17')
    },
    {
        id: 92,
        name: 'Olga Strong',
        title: 'Graphic Designer',
        phone: '(949) 417-1168',
        managerId: 90,
        hireDate: new Date('2018-06-15')
    },
    {
        id: 93,
        name: 'Robert Orr',
        title: 'Support Officer',
        phone: '(977) 341-3721',
        managerId: 90,
        hireDate: new Date('2018-06-22')
    },
    {
        id: 95,
        name: 'Odette Sears',
        title: 'Senior Software Developer',
        phone: '(264) 818-6576',
        managerId: 90,
        hireDate: new Date('2019-05-20')
    },
    {
        id: 45,
        name: 'Zelda Medina',
        title: 'QA Architect',
        phone: '(563) 359-6023',
        managerId: 32,
        hireDate: new Date('2018-08-16')
    },
    {
        id: 3,
        name: 'Priscilla Frank',
        title: 'Chief Product Officer',
        phone: '(217) 280-5300',
        managerId: 1,
        hireDate: new Date('2019-04-22')
    },
    {
        id: 4,
        name: 'Ursula Holmes',
        title: 'EVP, Product Strategy',
        phone: '(370) 983-8796',
        managerId: 3,
        hireDate: new Date('2018-01-15')
    },
    {
        id: 24,
        name: 'Melvin Carrillo',
        title: 'Director, Developer Relations',
        phone: '(344) 496-9555',
        managerId: 3,
        hireDate: new Date('2018-01-17')
    },
    {
        id: 29,
        name: 'Martha Chavez',
        title: 'Developer Advocate',
        phone: '(140) 772-7509',
        managerId: 24,
        hireDate: new Date('2018-05-14')
    },
    {
        id: 30,
        name: 'Oren Fox',
        title: 'Developer Advocate',
        phone: '(714) 284-2408',
        managerId: 24,
        hireDate: new Date('2018-07-19')
    },
    {
        id: 41,
        name: 'Amos Barr',
        title: 'Developer Advocate',
        phone: '(996) 587-8405',
        managerId: 24,
        hireDate: new Date('2019-01-16')
    }
  ];

Basic Concepts

According to the accessibility guidelines, only one of the focusable elements which are contained by the TreeList has to be included in the Tab sequence of the page.

To control which elements will be accessible through the Tab key, the TreeList implements a roving tabindex. All other focusable elements receive a tabindex of "-1" and get excluded from the Tab sequence.

To implement this requirement, all elements which can receive focus either through the Tab sequence or through direct interaction must be decorated with the kendoTreeListFocusable directive. It registers the focusable elements with the TreeList and provides an interface for controlling their focused state and tabindex. The directive can be applied to both regular input elements, such as inputs and buttons, and composite components, such as drop-down lists. Based on the user actions, the TreeList will include the focused (selected) element in the Tab sequence. Typically, this element is one single cell at a time but when the TreeList is in editing mode, it can also be an entire row.

The user can move the focus from cell to cell by using the available shortcut keys. If a cell contains a single focusable element, such as a button or a checkbox, the focus will be applied directly to the element. This behavior allows the user to interact with it without having to enter the cell first.

The following example demonstrates how to decorate a button inside a template by using kendoTreeListFocusable. The button will be excluded from the page Tab sequence, but can still be focused by using the Arrow keys inside the TreeList.

import { Component } from '@angular/core';
import { SelectableSettings } from '@progress/kendo-angular-treelist';
import { Employee, employees } from './employees';

@Component({
    selector: 'my-app',
    template: `
        <kendo-treelist [kendoTreeListFlatBinding]="data" idField="id" parentIdField="managerId"
                        kendoTreeListSelectable [selectable]="settings" [(selectedItems)]="selected"
                        kendoTreeListExpandable [initiallyExpanded]="true"
                        [navigable]="true"
                        [height]="410">
            <kendo-treelist-checkbox-column [width]="35" [checkChildren]="true">
            </kendo-treelist-checkbox-column>
            <kendo-treelist-column [expandable]="true" field="name" title="Name" [width]="250">
            </kendo-treelist-column>
            <kendo-treelist-column field="title" title="Title" [width]="180"></kendo-treelist-column>
            <kendo-treelist-column field="phone" title="Phone" [width]="180"></kendo-treelist-column>
            <kendo-treelist-column width="100">
                <ng-template kendoTreeListCellTemplate let-cellContext="cellContext">
                    <input type="button" class="k-button" [kendoTreeListFocusable]="cellContext" value="Button" />
                </ng-template>
            </kendo-treelist-column>
        </kendo-treelist>
    `
})
export class AppComponent {
    public data: Employee[] = employees;

    public settings: SelectableSettings = {
        mode: 'row',
        multiple: true
    };

    public selected: any[] = [];
}
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { TreeListModule } from '@progress/kendo-angular-treelist';
import { IntlModule } from '@progress/kendo-angular-intl';
import { AppComponent } from './app.component';

@NgModule({
    imports: [
        BrowserModule,
        BrowserAnimationsModule,
        FormsModule,
        TreeListModule,
        IntlModule
    ],
    declarations: [
        AppComponent
    ],
    bootstrap: [
        AppComponent
    ]
})

export class AppModule { }
import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app.module';

enableProdMode();

const platform = platformBrowserDynamic();
platform.bootstrapModule(AppModule);

export interface Employee {
    id: number;
    managerId?: number;
    name: string;
    title: string;
    phone: string;
    hireDate?: Date;
}

export const employees: Employee[] = [
    {
        id: 1,
        name: 'Daryl Sweeney',
        title: 'Chief Executive Officer',
        phone: '(555) 924-9726',
        managerId: null,
        hireDate: new Date('2019-01-15')
    },
    {
        id: 2,
        name: 'Guy Wooten',
        title: 'Chief Technical Officer',
        phone: '(438) 738-4935',
        managerId: 1,
        hireDate: new Date('2019-02-19')
    },
    {
        id: 32,
        name: 'Buffy Weber',
        title: 'VP, Engineering',
        phone: '(699) 838-6121',
        managerId: 2,
        hireDate: new Date('2019-04-13')
    },
    {
        id: 11,
        name: 'Hyacinth Hood',
        title: 'Team Lead',
        phone: '(889) 345-2438',
        managerId: 32,
        hireDate: new Date('2018-01-17')
    },
    {
        id: 60,
        name: 'Akeem Carr',
        title: 'Junior Software Developer',
        phone: '(738) 136-2814',
        managerId: 11,
        hireDate: new Date('2018-01-18')
    },
    {
        id: 78,
        name: 'Rinah Simon',
        title: 'Software Developer',
        phone: '(285) 912-5271',
        managerId: 11,
        hireDate: new Date('2018-03-17')
    },
    {
        id: 42,
        name: 'Gage Daniels',
        title: 'Software Architect',
        phone: '(107) 290-6260',
        managerId: 32,
        hireDate: new Date('2019-03-14')
    },
    {
        id: 43,
        name: 'Constance Vazquez',
        title: 'Director, Engineering',
        phone: '(800) 301-1978',
        managerId: 32,
        hireDate: new Date('2018-03-18')
    },
    {
        id: 46,
        name: 'Darrel Solis',
        title: 'Team Lead',
        phone: '(327) 977-0216',
        managerId: 43,
        hireDate: new Date('2019-04-15')
    },
    {
        id: 47,
        name: 'Brian Yang',
        title: 'Senior Software Developer',
        phone: '(565) 146-5435',
        managerId: 46,
        hireDate: new Date('2019-02-21')
    },
    {
        id: 50,
        name: 'Lillian Bradshaw',
        title: 'Software Developer',
        phone: '(323) 509-3479',
        managerId: 46,
        hireDate: new Date('2019-05-23')
    },
    {
        id: 51,
        name: 'Christian Palmer',
        title: 'Technical Lead',
        phone: '(490) 421-8718',
        managerId: 46,
        hireDate: new Date('2019-04-16')
    },
    {
        id: 55,
        name: 'Summer Mosley',
        title: 'QA Engineer',
        phone: '(784) 962-2301',
        managerId: 46,
        hireDate: new Date('2019-09-21')
    },
    {
        id: 56,
        name: 'Barry Ayers',
        title: 'Software Developer',
        phone: '(452) 373-9227',
        managerId: 46,
        hireDate: new Date('2018-04-16')
    },
    {
        id: 59,
        name: 'Keiko Espinoza',
        title: 'Junior QA Engineer',
        phone: '(226) 600-5305',
        managerId: 46,
        hireDate: new Date('2018-01-22')
    },
    {
        id: 61,
        name: 'Candace Pickett',
        title: 'Support Officer',
        phone: '(120) 117-7475',
        managerId: 46,
        hireDate: new Date('2018-09-18')
    },
    {
        id: 63,
        name: 'Mia Caldwell',
        title: 'Team Lead',
        phone: '(848) 636-6470',
        managerId: 43,
        hireDate: new Date('2018-07-17')
    },
    {
        id: 65,
        name: 'Thomas Terry',
        title: 'Senior Enterprise Support Officer',
        phone: '(764) 831-4248',
        managerId: 63,
        hireDate: new Date('2018-07-14')
    },
    {
        id: 67,
        name: 'Ruth Downs',
        title: 'Senior Software Developer',
        phone: '(138) 991-1440',
        managerId: 63,
        hireDate: new Date('2018-08-14')
    },
    {
        id: 70,
        name: 'Yasir Wilder',
        title: 'Senior QA Engineer',
        phone: '(759) 701-8665',
        managerId: 63,
        hireDate: new Date('2019-08-17')
    },
    {
        id: 71,
        name: 'Flavia Short',
        title: 'Support Officer',
        phone: '(370) 133-9238',
        managerId: 63,
        hireDate: new Date('2018-06-15')
    },
    {
        id: 74,
        name: 'Aaron Roach',
        title: 'Junior Software Developer',
        phone: '(958) 717-9230',
        managerId: 63,
        hireDate: new Date('2018-09-18')
    },
    {
        id: 75,
        name: 'Eric Russell',
        title: 'Software Developer',
        phone: '(516) 575-8505',
        managerId: 63,
        hireDate: new Date('2019-09-13')
    },
    {
        id: 76,
        name: 'Cheyenne Olson',
        title: 'Software Developer',
        phone: '(241) 645-0257',
        managerId: 63,
        hireDate: new Date('2018-09-18')
    },
    {
        id: 77,
        name: 'Shaine Avila',
        title: 'UI Designer',
        phone: '(844) 435-1360',
        managerId: 63,
        hireDate: new Date('2018-01-22')
    },
    {
        id: 81,
        name: 'Chantale Long',
        title: 'Senior QA Engineer',
        phone: '(252) 419-6891',
        managerId: 63,
        hireDate: new Date('2018-09-14')
    },
    {
        id: 83,
        name: 'Dane Cruz',
        title: 'Junior Software Developer',
        phone: '(946) 701-6165',
        managerId: 63,
        hireDate: new Date('2019-03-15')
    },
    {
        id: 84,
        name: 'Regan Patterson',
        title: 'Technical Writer',
        phone: '(265) 946-1765',
        managerId: 63,
        hireDate: new Date('2019-05-17')
    },
    {
        id: 85,
        name: 'Drew Mckay',
        title: 'Senior Software Developer',
        phone: '(327) 293-0162',
        managerId: 63,
        hireDate: new Date('2019-05-21')
    },
    {
        id: 88,
        name: 'Bevis Miller',
        title: 'Senior Software Developer',
        phone: '(525) 557-0169',
        managerId: 63,
        hireDate: new Date('2018-08-15')
    },
    {
        id: 89,
        name: 'Bruce Mccarty',
        title: 'Support Officer',
        phone: '(936) 777-8730',
        managerId: 63,
        hireDate: new Date('2019-10-21')
    },
    {
        id: 90,
        name: 'Ocean Blair',
        title: 'Team Lead',
        phone: '(343) 586-6614',
        managerId: 43,
        hireDate: new Date('2018-06-20')
    },
    {
        id: 91,
        name: 'Guinevere Osborn',
        title: 'Software Developer',
        phone: '(424) 741-0006',
        managerId: 90,
        hireDate: new Date('2019-06-17')
    },
    {
        id: 92,
        name: 'Olga Strong',
        title: 'Graphic Designer',
        phone: '(949) 417-1168',
        managerId: 90,
        hireDate: new Date('2018-06-15')
    },
    {
        id: 93,
        name: 'Robert Orr',
        title: 'Support Officer',
        phone: '(977) 341-3721',
        managerId: 90,
        hireDate: new Date('2018-06-22')
    },
    {
        id: 95,
        name: 'Odette Sears',
        title: 'Senior Software Developer',
        phone: '(264) 818-6576',
        managerId: 90,
        hireDate: new Date('2019-05-20')
    },
    {
        id: 45,
        name: 'Zelda Medina',
        title: 'QA Architect',
        phone: '(563) 359-6023',
        managerId: 32,
        hireDate: new Date('2018-08-16')
    },
    {
        id: 3,
        name: 'Priscilla Frank',
        title: 'Chief Product Officer',
        phone: '(217) 280-5300',
        managerId: 1,
        hireDate: new Date('2019-04-22')
    },
    {
        id: 4,
        name: 'Ursula Holmes',
        title: 'EVP, Product Strategy',
        phone: '(370) 983-8796',
        managerId: 3,
        hireDate: new Date('2018-01-15')
    },
    {
        id: 24,
        name: 'Melvin Carrillo',
        title: 'Director, Developer Relations',
        phone: '(344) 496-9555',
        managerId: 3,
        hireDate: new Date('2018-01-17')
    },
    {
        id: 29,
        name: 'Martha Chavez',
        title: 'Developer Advocate',
        phone: '(140) 772-7509',
        managerId: 24,
        hireDate: new Date('2018-05-14')
    },
    {
        id: 30,
        name: 'Oren Fox',
        title: 'Developer Advocate',
        phone: '(714) 284-2408',
        managerId: 24,
        hireDate: new Date('2018-07-19')
    },
    {
        id: 41,
        name: 'Amos Barr',
        title: 'Developer Advocate',
        phone: '(996) 587-8405',
        managerId: 24,
        hireDate: new Date('2019-01-16')
    }
  ];

Controlling the Focus

To control the focus in the TreeList, use any of the following methods:

You can query the cell and row which are currently focused by using the activeCell and activeRow properties. When the TreeList has no focused elements, these properties are undefined.

The following example demonstrates how to use the focus methods to implement the Tab key navigation with in-cell editing.

import { Component } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';

import { CreateFormGroupArgs } from '@progress/kendo-angular-treelist';
import { Employee, employees } from './employees';

@Component({
  selector: 'my-app',
  template: `
    <kendo-treelist
        [inCellTab]="createFormGroup"
        kendoTreeListExpandable
            [initiallyExpanded]="true"
        [kendoTreeListFlatBinding]="data"
            idField="id" parentIdField="managerId"
        [kendoTreeListInCellEditing]="createFormGroup"
        [height]="500"
        [pageSize]="10"
        [pageable]="true"
        [sortable]="true"
        [navigable]="true"
    >
        <ng-template kendoTreeListToolbarTemplate>
            <button kendoTreeListAddCommand type="button">Add new</button>
        </ng-template>
        <kendo-treelist-column [expandable]="true" field="name" title="Name">
        </kendo-treelist-column>
        <kendo-treelist-column field="title" title="Title">
        </kendo-treelist-column>
        <kendo-treelist-column field="phone" title="Phone">
        </kendo-treelist-column>
        <kendo-treelist-command-column width="60">
            <ng-template kendoTreeListCellTemplate let-isNew="isNew" let-cellContext="cellContext">
                <!-- "Add Child" command directive, will not be visible in edit mode -->
                <button [kendoTreeListAddCommand]="cellContext"
                        icon="filter-add-expression" title="Add Child">
                </button>

                <!-- "Save" command directive, will be visible only in edit mode -->
                <button [kendoTreeListSaveCommand]="cellContext"
                        [disabled]="formGroup?.invalid"
                        icon="save" title="{{ isNew ? 'Add' : 'Update' }}">
                </button>
            </ng-template>
        </kendo-treelist-command-column>
        <kendo-treelist-command-column width="60">
            <ng-template kendoTreeListCellTemplate let-isNew="isNew" let-cellContext="cellContext">
                <!-- "Remove" command directive, will not be visible in edit mode -->
                <button [kendoTreeListRemoveCommand]="cellContext"
                        icon="delete" title="Remove">
                </button>

                <!-- "Cancel" command directive, will be visible only in edit mode -->
                <button [kendoTreeListCancelCommand]="cellContext"
                        icon="cancel" title="{{ isNew ? 'Discard changes' : 'Cancel' }}">
                </button>
            </ng-template>
        </kendo-treelist-command-column>
    </kendo-treelist>
  `
})
export class AppComponent {
    public data: Employee[] = employees;
    public formGroup: FormGroup;

    constructor() {
        this.createFormGroup = this.createFormGroup.bind(this);
    }

    public createFormGroup({ isNew, dataItem }: CreateFormGroupArgs): any {
        const item = isNew ? {} : dataItem;

        this.formGroup = new FormGroup({
            'id': new FormControl(item.id),
            'parentId': new FormControl(item.parentId),
            'name': new FormControl(item.name, Validators.required),
            'title': new FormControl(item.title),
            'phone': new FormControl(item.phone, Validators.required)
        });

        return this.formGroup;
    }
}
import { OnInit, Input, OnDestroy, Directive, ElementRef, Renderer2 } from '@angular/core';
import { FormGroup } from '@angular/forms';

import { CreateFormGroupArgs, TreeListComponent } from '@progress/kendo-angular-treelist';

@Directive({
    selector: '[inCellTab]'
})
export class InCellTabDirective implements OnInit, OnDestroy {
    /* tslint:disable-next-line:no-input-rename */
    @Input('inCellTab')
    public createFormGroup: (args: CreateFormGroupArgs) => FormGroup;

    @Input()
    public wrap = true;

    private unsubscribe: () => void;

    constructor(
        private treelist: TreeListComponent,
        private el: ElementRef,
        private renderer: Renderer2) {
    }

    public ngOnInit(): void {
        this.unsubscribe = this.renderer.listen(
            this.el.nativeElement, 'keydown', (e) => this.onKeydown(e)
        );
    }

    public ngOnDestroy(): void {
        this.unsubscribe();
    }

    public onKeydown(e: KeyboardEvent): void {
        if (e.key !== 'Tab') {
            // Handle just tabs
            return;
        }

        let activeRow = this.treelist.activeRow;
        if (!activeRow || !activeRow.dataItem) {
            // Not on an editable row
            return;
        }

        if (this.treelist.isEditingCell() && !this.treelist.closeCell()) {
            // Content validation failed, keep focus in cell
            e.preventDefault();
            return;
        }

        const nav = e.shiftKey ?
            this.treelist.focusPrevCell(this.wrap) :
            this.treelist.focusNextCell(this.wrap);

        if (!nav) {
            // No next cell to navigate to
            return;
        }

        // Prevent the focus from moving to the next element
        e.preventDefault();

        if (nav.column.isEditable) {
            activeRow = this.treelist.activeRow;
            const dataItem = activeRow.dataItem;
            if (dataItem) {
                if (activeRow.isNew) {
                    // Focus new item
                    this.treelist.activeCell.focusContent();
                } else {
                    // Edit focused cell
                    const formGroup = this.createFormGroup({ dataItem });
                    this.treelist.editCell(dataItem, nav.colIndex, formGroup);
                }
            }
        }
    }
}
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { ReactiveFormsModule } from '@angular/forms';

import { TreeListModule } from '@progress/kendo-angular-treelist';

import { AppComponent } from './app.component';
import { InCellTabDirective } from './incell-tab.directive';

@NgModule({
    declarations: [
        AppComponent,
        InCellTabDirective
    ],
    imports: [
        BrowserModule,
        BrowserAnimationsModule,
        ReactiveFormsModule,
        TreeListModule
    ],
    bootstrap: [AppComponent]
})
export class AppModule {}
import { Injectable } from '@angular/core';
import { HttpClient, HttpParams } from '@angular/common/http';
import { Observable, BehaviorSubject } from 'rxjs';
import { tap, take } from 'rxjs/operators';

import { Employee } from './employee';

const CREATE_ACTION = 'Create';
const UPDATE_ACTION = 'Update';
const REMOVE_ACTION = 'Destroy';

function noop() { /* */ }

@Injectable()
export class EmployeeEditService extends BehaviorSubject<Employee[]> {
    constructor(private http: HttpClient) {
        super(null);
    }

    public read(): void {
        this.fetch('')
            .pipe(take(1))
            .subscribe(data => this.next(data));
    }

    public fetchChildren(reportsTo: number = null): Observable<Employee[]> {
        return this.fetch('', null, reportsTo);
    }

    public update(item: Employee): void {
        this.save(item, null, false)
            .pipe(take(1))
            .subscribe(noop);
    }

    public save(item: Employee, parent: Employee, isNew: boolean): Observable<Employee[]> {
        const action = isNew ? CREATE_ACTION : UPDATE_ACTION;

        return this.fetch(action, item).pipe(tap(() => {
            if (!parent && isNew) {
                this.read();
            }
        }));
    }

    public remove(item: any, parent?: Employee): Observable<Employee[]> {
        return this.fetch(REMOVE_ACTION, item).pipe(tap(() => {
            if (!parent) {
                this.read();
            }
        }));
    }

    private fetch(action: string = '', data?: any, id?: any): Observable<Employee[]> {
        let params = new HttpParams();

        if (typeof id !== 'undefined') {
            params = params.set('id', id);
        }

        if (data) {
            params = params.set('models', JSON.stringify([data]));
        }

        return this.http.jsonp<Employee[]>(
            `https://demos.telerik.com/kendo-ui/service/EmployeeDirectory/${action}?${params.toString()}`,
            'callback'
        );
    }
}

export interface Employee {
    id: number;
    managerId?: number;
    name: string;
    title: string;
    phone: string;
    hireDate?: Date;
}

export const employees: Employee[] = [
    {
        id: 1,
        name: 'Daryl Sweeney',
        title: 'Chief Executive Officer',
        phone: '(555) 924-9726',
        managerId: null,
        hireDate: new Date('2019-01-15')
    },
    {
        id: 2,
        name: 'Guy Wooten',
        title: 'Chief Technical Officer',
        phone: '(438) 738-4935',
        managerId: 1,
        hireDate: new Date('2019-02-19')
    },
    {
        id: 32,
        name: 'Buffy Weber',
        title: 'VP, Engineering',
        phone: '(699) 838-6121',
        managerId: 2,
        hireDate: new Date('2019-04-13')
    },
    {
        id: 11,
        name: 'Hyacinth Hood',
        title: 'Team Lead',
        phone: '(889) 345-2438',
        managerId: 32,
        hireDate: new Date('2018-01-17')
    },
    {
        id: 60,
        name: 'Akeem Carr',
        title: 'Junior Software Developer',
        phone: '(738) 136-2814',
        managerId: 11,
        hireDate: new Date('2018-01-18')
    },
    {
        id: 78,
        name: 'Rinah Simon',
        title: 'Software Developer',
        phone: '(285) 912-5271',
        managerId: 11,
        hireDate: new Date('2018-03-17')
    },
    {
        id: 42,
        name: 'Gage Daniels',
        title: 'Software Architect',
        phone: '(107) 290-6260',
        managerId: 32,
        hireDate: new Date('2019-03-14')
    },
    {
        id: 43,
        name: 'Constance Vazquez',
        title: 'Director, Engineering',
        phone: '(800) 301-1978',
        managerId: 32,
        hireDate: new Date('2018-03-18')
    },
    {
        id: 46,
        name: 'Darrel Solis',
        title: 'Team Lead',
        phone: '(327) 977-0216',
        managerId: 43,
        hireDate: new Date('2019-04-15')
    },
    {
        id: 47,
        name: 'Brian Yang',
        title: 'Senior Software Developer',
        phone: '(565) 146-5435',
        managerId: 46,
        hireDate: new Date('2019-02-21')
    },
    {
        id: 50,
        name: 'Lillian Bradshaw',
        title: 'Software Developer',
        phone: '(323) 509-3479',
        managerId: 46,
        hireDate: new Date('2019-05-23')
    },
    {
        id: 51,
        name: 'Christian Palmer',
        title: 'Technical Lead',
        phone: '(490) 421-8718',
        managerId: 46,
        hireDate: new Date('2019-04-16')
    },
    {
        id: 55,
        name: 'Summer Mosley',
        title: 'QA Engineer',
        phone: '(784) 962-2301',
        managerId: 46,
        hireDate: new Date('2019-09-21')
    },
    {
        id: 56,
        name: 'Barry Ayers',
        title: 'Software Developer',
        phone: '(452) 373-9227',
        managerId: 46,
        hireDate: new Date('2018-04-16')
    },
    {
        id: 59,
        name: 'Keiko Espinoza',
        title: 'Junior QA Engineer',
        phone: '(226) 600-5305',
        managerId: 46,
        hireDate: new Date('2018-01-22')
    },
    {
        id: 61,
        name: 'Candace Pickett',
        title: 'Support Officer',
        phone: '(120) 117-7475',
        managerId: 46,
        hireDate: new Date('2018-09-18')
    },
    {
        id: 63,
        name: 'Mia Caldwell',
        title: 'Team Lead',
        phone: '(848) 636-6470',
        managerId: 43,
        hireDate: new Date('2018-07-17')
    },
    {
        id: 65,
        name: 'Thomas Terry',
        title: 'Senior Enterprise Support Officer',
        phone: '(764) 831-4248',
        managerId: 63,
        hireDate: new Date('2018-07-14')
    },
    {
        id: 67,
        name: 'Ruth Downs',
        title: 'Senior Software Developer',
        phone: '(138) 991-1440',
        managerId: 63,
        hireDate: new Date('2018-08-14')
    },
    {
        id: 70,
        name: 'Yasir Wilder',
        title: 'Senior QA Engineer',
        phone: '(759) 701-8665',
        managerId: 63,
        hireDate: new Date('2019-08-17')
    },
    {
        id: 71,
        name: 'Flavia Short',
        title: 'Support Officer',
        phone: '(370) 133-9238',
        managerId: 63,
        hireDate: new Date('2018-06-15')
    },
    {
        id: 74,
        name: 'Aaron Roach',
        title: 'Junior Software Developer',
        phone: '(958) 717-9230',
        managerId: 63,
        hireDate: new Date('2018-09-18')
    },
    {
        id: 75,
        name: 'Eric Russell',
        title: 'Software Developer',
        phone: '(516) 575-8505',
        managerId: 63,
        hireDate: new Date('2019-09-13')
    },
    {
        id: 76,
        name: 'Cheyenne Olson',
        title: 'Software Developer',
        phone: '(241) 645-0257',
        managerId: 63,
        hireDate: new Date('2018-09-18')
    },
    {
        id: 77,
        name: 'Shaine Avila',
        title: 'UI Designer',
        phone: '(844) 435-1360',
        managerId: 63,
        hireDate: new Date('2018-01-22')
    },
    {
        id: 81,
        name: 'Chantale Long',
        title: 'Senior QA Engineer',
        phone: '(252) 419-6891',
        managerId: 63,
        hireDate: new Date('2018-09-14')
    },
    {
        id: 83,
        name: 'Dane Cruz',
        title: 'Junior Software Developer',
        phone: '(946) 701-6165',
        managerId: 63,
        hireDate: new Date('2019-03-15')
    },
    {
        id: 84,
        name: 'Regan Patterson',
        title: 'Technical Writer',
        phone: '(265) 946-1765',
        managerId: 63,
        hireDate: new Date('2019-05-17')
    },
    {
        id: 85,
        name: 'Drew Mckay',
        title: 'Senior Software Developer',
        phone: '(327) 293-0162',
        managerId: 63,
        hireDate: new Date('2019-05-21')
    },
    {
        id: 88,
        name: 'Bevis Miller',
        title: 'Senior Software Developer',
        phone: '(525) 557-0169',
        managerId: 63,
        hireDate: new Date('2018-08-15')
    },
    {
        id: 89,
        name: 'Bruce Mccarty',
        title: 'Support Officer',
        phone: '(936) 777-8730',
        managerId: 63,
        hireDate: new Date('2019-10-21')
    },
    {
        id: 90,
        name: 'Ocean Blair',
        title: 'Team Lead',
        phone: '(343) 586-6614',
        managerId: 43,
        hireDate: new Date('2018-06-20')
    },
    {
        id: 91,
        name: 'Guinevere Osborn',
        title: 'Software Developer',
        phone: '(424) 741-0006',
        managerId: 90,
        hireDate: new Date('2019-06-17')
    },
    {
        id: 92,
        name: 'Olga Strong',
        title: 'Graphic Designer',
        phone: '(949) 417-1168',
        managerId: 90,
        hireDate: new Date('2018-06-15')
    },
    {
        id: 93,
        name: 'Robert Orr',
        title: 'Support Officer',
        phone: '(977) 341-3721',
        managerId: 90,
        hireDate: new Date('2018-06-22')
    },
    {
        id: 95,
        name: 'Odette Sears',
        title: 'Senior Software Developer',
        phone: '(264) 818-6576',
        managerId: 90,
        hireDate: new Date('2019-05-20')
    },
    {
        id: 45,
        name: 'Zelda Medina',
        title: 'QA Architect',
        phone: '(563) 359-6023',
        managerId: 32,
        hireDate: new Date('2018-08-16')
    },
    {
        id: 3,
        name: 'Priscilla Frank',
        title: 'Chief Product Officer',
        phone: '(217) 280-5300',
        managerId: 1,
        hireDate: new Date('2019-04-22')
    },
    {
        id: 4,
        name: 'Ursula Holmes',
        title: 'EVP, Product Strategy',
        phone: '(370) 983-8796',
        managerId: 3,
        hireDate: new Date('2018-01-15')
    },
    {
        id: 24,
        name: 'Melvin Carrillo',
        title: 'Director, Developer Relations',
        phone: '(344) 496-9555',
        managerId: 3,
        hireDate: new Date('2018-01-17')
    },
    {
        id: 29,
        name: 'Martha Chavez',
        title: 'Developer Advocate',
        phone: '(140) 772-7509',
        managerId: 24,
        hireDate: new Date('2018-05-14')
    },
    {
        id: 30,
        name: 'Oren Fox',
        title: 'Developer Advocate',
        phone: '(714) 284-2408',
        managerId: 24,
        hireDate: new Date('2018-07-19')
    },
    {
        id: 41,
        name: 'Amos Barr',
        title: 'Developer Advocate',
        phone: '(996) 587-8405',
        managerId: 24,
        hireDate: new Date('2019-01-16')
    }
  ];
import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app.module';

enableProdMode();

const platform = platformBrowserDynamic();
platform.bootstrapModule(AppModule);

In this article