Skip to content

feat(cdk-experimental/popover-edit): Support skipping over annotated … #30916

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 23, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/cdk-experimental/popover-edit/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,6 @@ export const EDIT_PANE_CLASS = 'cdk-edit-pane';

/** Selector for finding the edit lens pane. */
export const EDIT_PANE_SELECTOR = `.${EDIT_PANE_CLASS}, .mat-edit-pane`;

/** Selector for table rows that should be skipped when moving focus. */
export const SKIP_ROW_FOCUS_SELECTOR = '.cdk-popover-edit-skip-focus, .mat-popover-edit-skip-focus';
13 changes: 11 additions & 2 deletions src/cdk-experimental/popover-edit/focus-dispatcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,12 @@ import {LEFT_ARROW, UP_ARROW, RIGHT_ARROW, DOWN_ARROW} from '@angular/cdk/keycod
import {Injectable, inject} from '@angular/core';
import {PartialObserver} from 'rxjs';

import {EDITABLE_CELL_SELECTOR, ROW_SELECTOR, TABLE_SELECTOR} from './constants';
import {
EDITABLE_CELL_SELECTOR,
ROW_SELECTOR,
SKIP_ROW_FOCUS_SELECTOR,
TABLE_SELECTOR,
} from './constants';
import {closest} from './polyfill';

/**
Expand Down Expand Up @@ -53,7 +58,11 @@ export class FocusDispatcher {
const currentIndexWithinRow = Array.from(
currentRow.querySelectorAll(EDITABLE_CELL_SELECTOR),
).indexOf(currentCell);
const newRowIndex = currentRowIndex + offset;

let newRowIndex = currentRowIndex + offset;
while (rows[newRowIndex]?.matches(SKIP_ROW_FOCUS_SELECTOR)) {
newRowIndex = newRowIndex + (offset > 0 ? 1 : -1);
}

if (rows[newRowIndex]) {
const rowToFocus = Array.from(
Expand Down
97 changes: 97 additions & 0 deletions src/cdk-experimental/popover-edit/popover-edit.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1044,6 +1044,103 @@ cdkPopoverEditTabOut`, fakeAsync(() => {
}
});

@Component({
template: `
<div #table [dir]="direction">
<table cdk-table editable [dataSource]="dataSource" [multiTemplateDataRows]="true">
<ng-container cdkColumnDef="before">
<td cdk-cell *cdkCellDef="let element">
just a cell
</td>
</ng-container>

<ng-container cdkColumnDef="name">
<td cdk-cell *cdkCellDef="let element"
${POPOVER_EDIT_DIRECTIVE_NAME}>
${CELL_TEMPLATE}

<ng-template #nameEdit>
${NAME_EDIT_TEMPLATE}
</ng-template>

<span *cdkIfRowHovered>
<button cdkEditOpen>Edit</button>
</span>
</td>
</ng-container>

<ng-container cdkColumnDef="weight">
<td cdk-cell *cdkCellDef="let element"
${POPOVER_EDIT_DIRECTIVE_WEIGHT}>
{{element.weight}}

<ng-template #weightEdit>
${WEIGHT_EDIT_TEMPLATE}
</ng-template>
</td>
</ng-container>

<ng-container cdkColumnDef="skip">
<td cdk-cell *cdkCellDef="let element" colspan="3"></td>
</ng-container>

<tr cdk-row *cdkRowDef="let row; columns: displayedColumns;"></tr>
<tr cdk-row *cdkRowDef="let row; columns: ['skip'];"
class="cdk-popover-edit-skip-focus"></tr>
</table>
<div>
`,
standalone: false,
})
class CdkTableWithSkipRows extends BaseTestComponent {
displayedColumns = ['before', 'name', 'weight'];
dataSource: ElementDataSource;

renderData() {
this.dataSource = new ElementDataSource();
this.cdr.markForCheck();
}
}

describe('CDK Popover Edit - with focus ignore rows', () => {
let component: CdkTableWithSkipRows;
let fixture: ComponentFixture<CdkTableWithSkipRows>;

const dispatchKey = (cell: HTMLElement, keyCode: number) =>
dispatchKeyboardEvent(cell, 'keydown', keyCode);

beforeEach(fakeAsync(() => {
TestBed.configureTestingModule({
imports: [CdkTableModule, CdkPopoverEditModule, FormsModule, BidiModule],
declarations: [CdkTableWithSkipRows],
});
fixture = TestBed.createComponent(CdkTableWithSkipRows);
component = fixture.componentInstance;
component.renderData();
fixture.detectChanges();
tick(10);
fixture.detectChanges();
}));

it('skips ignored rows when moving focus up', () => {
const rows = component.getRows();

getCells(rows[4])[1].focus();

dispatchKey(getCells(rows[4])[1], UP_ARROW);
expect(document.activeElement).toBe(getCells(rows[2])[1]);
});

it('skips ignored rows when moving focus down', () => {
const rows = component.getRows();

getCells(rows[0])[1].focus();

dispatchKey(getCells(rows[0])[1], DOWN_ARROW);
expect(document.activeElement).toBe(getCells(rows[2])[1]);
});
});

interface ChemicalElement {
name: string;
weight: number;
Expand Down
Loading