mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
feat(list-key-manager): accept item references in setActiveItem (#10029)
* Adds an overload to `setActiveItem` to allow for an item to be set as active, rather than its index. This avoids awkward conversions in certain cases (see the chips and select changes). * Deprecates the `updateActiveItemIndex` method in favor of `updateActiveItem` which accepts both an index and an item. * Fixes the active item not being updated when it is set via `updateActiveItemIndex`.
This commit is contained in:
committed by
tinayuangao
parent
dd082cbdd6
commit
92ed9c8c63
@@ -24,11 +24,22 @@ export interface Highlightable extends ListKeyManagerOption {
|
||||
export class ActiveDescendantKeyManager<T> extends ListKeyManager<Highlightable & T> {
|
||||
|
||||
/**
|
||||
* This method sets the active item to the item at the specified index.
|
||||
* It also adds active styles to the newly active item and removes active
|
||||
* styles from the previously active item.
|
||||
* Sets the active item to the item at the specified index and adds the
|
||||
* active styles to the newly active item. Also removes active styles
|
||||
* from the previously active item.
|
||||
* @param index Index of the item to be set as active.
|
||||
*/
|
||||
setActiveItem(index: number): void {
|
||||
setActiveItem(index: number): void;
|
||||
|
||||
/**
|
||||
* Sets the active item to the item to the specified one and adds the
|
||||
* active styles to the it. Also removes active styles from the
|
||||
* previously active item.
|
||||
* @param item Item to be set as active.
|
||||
*/
|
||||
setActiveItem(item: T): void;
|
||||
|
||||
setActiveItem(index: any): void {
|
||||
if (this.activeItem) {
|
||||
this.activeItem.setInactiveStyles();
|
||||
}
|
||||
|
||||
@@ -32,11 +32,20 @@ export class FocusKeyManager<T> extends ListKeyManager<FocusableOption & T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* This method sets the active item to the item at the specified index.
|
||||
* It also adds focuses the newly active item.
|
||||
* Sets the active item to the item at the specified
|
||||
* index and focuses the newly active item.
|
||||
* @param index Index of the item to be set as active.
|
||||
*/
|
||||
setActiveItem(index: number): void {
|
||||
super.setActiveItem(index);
|
||||
setActiveItem(index: number): void;
|
||||
|
||||
/**
|
||||
* Sets the active item to the item that is specified and focuses it.
|
||||
* @param item Item to be set as active.
|
||||
*/
|
||||
setActiveItem(item: T): void;
|
||||
|
||||
setActiveItem(item: any): void {
|
||||
super.setActiveItem(item);
|
||||
|
||||
if (this.activeItem) {
|
||||
this.activeItem.focus(this._origin);
|
||||
|
||||
@@ -349,6 +349,29 @@ describe('Key managers', () => {
|
||||
.toBe(1, `Expected activeItemIndex to be updated when setActiveItem() was called.`);
|
||||
});
|
||||
|
||||
it('should be able to set the active item by reference', () => {
|
||||
expect(keyManager.activeItemIndex)
|
||||
.toBe(0, `Expected first item of the list to be active.`);
|
||||
|
||||
keyManager.setActiveItem(itemList.items[2]);
|
||||
expect(keyManager.activeItemIndex)
|
||||
.toBe(2, `Expected activeItemIndex to be updated.`);
|
||||
});
|
||||
|
||||
it('should be able to set the active item without emitting an event', () => {
|
||||
const spy = jasmine.createSpy('change spy');
|
||||
const subscription = keyManager.change.subscribe(spy);
|
||||
|
||||
expect(keyManager.activeItemIndex).toBe(0);
|
||||
|
||||
keyManager.updateActiveItem(2);
|
||||
|
||||
expect(keyManager.activeItemIndex).toBe(2);
|
||||
expect(spy).not.toHaveBeenCalled();
|
||||
|
||||
subscription.unsubscribe();
|
||||
});
|
||||
|
||||
it('should expose the active item correctly', () => {
|
||||
keyManager.onKeydown(fakeKeyEvents.downArrow);
|
||||
|
||||
|
||||
@@ -162,14 +162,21 @@ export class ListKeyManager<T extends ListKeyManagerOption> {
|
||||
* Sets the active item to the item at the index specified.
|
||||
* @param index The index of the item to be set as active.
|
||||
*/
|
||||
setActiveItem(index: number): void {
|
||||
setActiveItem(index: number): void;
|
||||
|
||||
/**
|
||||
* Sets the active item to the specified item.
|
||||
* @param item The item to be set as active.
|
||||
*/
|
||||
setActiveItem(item: T): void;
|
||||
|
||||
setActiveItem(item: any): void {
|
||||
const previousIndex = this._activeItemIndex;
|
||||
|
||||
this._activeItemIndex = index;
|
||||
this._activeItem = this._items.toArray()[index];
|
||||
this.updateActiveItem(item);
|
||||
|
||||
if (this._activeItemIndex !== previousIndex) {
|
||||
this.change.next(index);
|
||||
this.change.next(this._activeItemIndex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -272,12 +279,34 @@ export class ListKeyManager<T extends ListKeyManagerOption> {
|
||||
: this._setActiveItemByDelta(-1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows setting the active without any other effects.
|
||||
* @param index Index of the item to be set as active.
|
||||
*/
|
||||
updateActiveItem(index: number): void;
|
||||
|
||||
/**
|
||||
* Allows setting the active item without any other effects.
|
||||
* @param item Item to be set as active.
|
||||
*/
|
||||
updateActiveItem(item: T): void;
|
||||
|
||||
updateActiveItem(item: any): void {
|
||||
const itemArray = this._items.toArray();
|
||||
const index = typeof item === 'number' ? item : itemArray.indexOf(item);
|
||||
|
||||
this._activeItemIndex = index;
|
||||
this._activeItem = itemArray[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows setting of the activeItemIndex without any other effects.
|
||||
* @param index The new activeItemIndex.
|
||||
* @deprecated Use `updateActiveItem` instead.
|
||||
* @deletion-target 7.0.0
|
||||
*/
|
||||
updateActiveItemIndex(index: number) {
|
||||
this._activeItemIndex = index;
|
||||
updateActiveItemIndex(index: number): void {
|
||||
this.updateActiveItem(index);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -567,14 +567,11 @@ export class MatChipList extends _MatChipListMixinBase implements MatFormFieldCo
|
||||
// Shift focus to the active item. Note that we shouldn't do this in multiple
|
||||
// mode, because we don't know what chip the user interacted with last.
|
||||
if (correspondingChip) {
|
||||
const correspondingChipIndex = this.chips.toArray().indexOf(correspondingChip);
|
||||
|
||||
if (isUserInput) {
|
||||
this._keyManager.setActiveItem(correspondingChipIndex);
|
||||
this._keyManager.setActiveItem(correspondingChip);
|
||||
} else {
|
||||
this._keyManager.updateActiveItemIndex(correspondingChipIndex);
|
||||
this._keyManager.updateActiveItem(correspondingChip);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -808,7 +808,7 @@ export class MatSelect extends _MatSelectMixinBase implements AfterContentInit,
|
||||
// Shift focus to the active item. Note that we shouldn't do this in multiple
|
||||
// mode, because we don't know what option the user interacted with last.
|
||||
if (correspondingOption) {
|
||||
this._keyManager.setActiveItem(this.options.toArray().indexOf(correspondingOption));
|
||||
this._keyManager.setActiveItem(correspondingOption);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -910,7 +910,7 @@ export class MatSelect extends _MatSelectMixinBase implements AfterContentInit,
|
||||
this._selectionModel.toggle(option);
|
||||
this.stateChanges.next();
|
||||
wasSelected ? option.deselect() : option.select();
|
||||
this._keyManager.setActiveItem(this._getOptionIndex(option)!);
|
||||
this._keyManager.setActiveItem(option);
|
||||
this._sortValues();
|
||||
} else {
|
||||
this._clearSelection(option.value == null ? undefined : option);
|
||||
@@ -976,7 +976,7 @@ export class MatSelect extends _MatSelectMixinBase implements AfterContentInit,
|
||||
if (this.empty) {
|
||||
this._keyManager.setFirstItemActive();
|
||||
} else {
|
||||
this._keyManager.setActiveItem(this._getOptionIndex(this._selectionModel.selected[0])!);
|
||||
this._keyManager.setActiveItem(this._selectionModel.selected[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user