Skip to content

Commit

Permalink
fix(kit): support updateOn of blur and submit types for `multi-…
Browse files Browse the repository at this point in the history
…select` component
  • Loading branch information
splincode committed Jan 12, 2023
1 parent e30040a commit 5ba5679
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 29 deletions.
9 changes: 7 additions & 2 deletions projects/core/interfaces/data-list-host.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import {TuiIdentityMatcher} from '@taiga-ui/cdk';
import {
AbstractTuiControl,
AbstractTuiInteractive,
TuiIdentityMatcher,
} from '@taiga-ui/cdk';

// TODO: Consider refactoring checkOption, it is only needed in ComboBox
export interface TuiDataListHost<T> {
export interface TuiDataListHost<T, K = AbstractTuiControl<T> | AbstractTuiInteractive> {
hostControl?: K;
handleOption(option: T): void;
checkOption?(option: T): void;
readonly identityMatcher?: TuiIdentityMatcher<T>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,27 +51,106 @@ describe(`MultiSelect`, () => {
});

describe(`API page`, () => {
beforeEach(() => cy.viewport(400, 812));
describe(`sizes`, () => {
beforeEach(() => cy.viewport(400, 812));

[`s`, `m`, `l`].forEach(size => {
it(`tuiTextfieldSize=${size}`, () => {
cy.tuiVisit(
`components/multi-select/API?tuiMode=null&tuiTextfieldCleaner=true&tuiTextfieldSize=${size}`,
);

cy.getByAutomationId(`tui-multi-select__arrow`).click({force: true});

[0, 1, 2, 3, 4].forEach(index => {
cy.get(`tui-data-list-wrapper`)
.findByAutomationId(`tui-data-list-wrapper__option`)
.eq(index)
.click({force: true});
});

cy.wait(DEFAULT_TIMEOUT_BEFORE_ACTION).matchImageSnapshot(
`02-multi-select-size-${size}`,
{capture: `viewport`},
);
});
});
});

[`s`, `m`, `l`].forEach(size => {
it(`tuiTextfieldSize=${size}`, () => {
cy.tuiVisit(
`components/multi-select/API?tuiMode=null&tuiTextfieldCleaner=true&tuiTextfieldSize=${size}`,
);
describe(`Form changes by updateOn`, () => {
[`submit`, `blur`, `change`].forEach(type => {
it(`updateOn: ${type}`, () => {
cy.tuiVisit(`components/multi-select/API`);

cy.getByAutomationId(`tui-multi-select__arrow`).click({force: true});
cy.getByAutomationId(`tui-demo-button__toggle-details`)
.click()
.wait(100);

[0, 1, 2, 3, 4].forEach(index => {
cy.get(`tui-data-list-wrapper`)
.findByAutomationId(`tui-data-list-wrapper__option`)
.eq(index)
cy.getByAutomationId(`tui-demo-select__expand-update-on`)
.click()
.wait(100);

cy.get(`tui-data-list[role=listbox]`)
.find(`button`)
.contains(type)
.click({force: true});
});

cy.wait(DEFAULT_TIMEOUT_BEFORE_ACTION).matchImageSnapshot(
`02-multi-select-size-${size}`,
{capture: `viewport`},
);
cy.get(`#demo-content`)
.wait(DEFAULT_TIMEOUT_BEFORE_ACTION)
.matchImageSnapshot(
// initial
`multi-select-update-on-${type}__1`,
);
cy.getByAutomationId(`tui-multi-select__arrow`).click();

[0, 1, 2].forEach(index =>
cy
.get(`tui-data-list-wrapper`)
.findByAutomationId(`tui-data-list-wrapper__option`)
.eq(index)
.click({force: true}),
);
cy.get(`tui-data-list-wrapper`).matchImageSnapshot(
// selected-values
`multi-select-update-on-${type}__2`,
);

cy.getByAutomationId(`tui-multi-select__arrow`).click({force: true});
cy.get(`#demo-content`)
.wait(DEFAULT_TIMEOUT_BEFORE_ACTION)
.matchImageSnapshot(
// hide-dropdown
`multi-select-update-on-${type}__3`,
);

cy.get(`#demo-content`).click({force: true});
cy.get(`#demo-content`)
.wait(DEFAULT_TIMEOUT_BEFORE_ACTION)
.matchImageSnapshot(
// blur event
`multi-select-update-on-${type}__4`,
);

cy.getByAutomationId(`tui-demo-button__submit-state`).click({
force: true,
});
cy.get(`#demo-content`)
.wait(DEFAULT_TIMEOUT_BEFORE_ACTION)
.matchImageSnapshot(
// submit event
`multi-select-update-on-${type}__5`,
);

cy.getByAutomationId(`tui-demo-button__reset-state`).click({
force: true,
});
cy.get(`#demo-content`)
.wait(DEFAULT_TIMEOUT_BEFORE_ACTION)
.matchImageSnapshot(
// reset
`multi-select-update-on-${type}__6`,
);
});
});
});
});
Expand Down
4 changes: 2 additions & 2 deletions projects/kit/components/combo-box/combo-box.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export class TuiComboBoxComponent<T>
private readonly hostedDropdown?: TuiHostedDropdownComponent;

@ViewChild(TuiPrimitiveTextfieldComponent)
private readonly textfield?: TuiPrimitiveTextfieldComponent;
readonly hostControl?: TuiPrimitiveTextfieldComponent;

@Input()
@tuiDefaultProp()
Expand Down Expand Up @@ -128,7 +128,7 @@ export class TuiComboBoxComponent<T>
}

get nativeFocusableElement(): HTMLInputElement | null {
return this.textfield ? this.textfield.nativeFocusableElement : null;
return this.hostControl?.nativeFocusableElement ?? null;
}

get focused(): boolean {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {ChangeDetectionStrategy, Component} from '@angular/core';
import {tuiIsPresent} from '@taiga-ui/cdk';
import {TuiSizeL} from '@taiga-ui/core';
import type {TuiStringifiableItem} from '@taiga-ui/kit/classes';
import {TuiSelectOptionComponent} from '@taiga-ui/kit/components/select-option';

@Component({
Expand All @@ -22,8 +23,15 @@ export class TuiMultiSelectOptionComponent<T> extends TuiSelectOptionComponent<T

return (
tuiIsPresent(value) &&
tuiIsPresent(this.control.value) &&
this.control.value.some((item: T) => this.matcher(item, value))
((this.control.value ?? []).some((item: T) => this.matcher(item, value)) ||
/**
* @description:
* if host has updateOn type in form by values as 'blur' | 'submit'
* then we can't listen changes directly in this.control.value
*/
(this.host.hostControl?.control?.value ?? []).some(
({item}: TuiStringifiableItem<T>) => this.matcher(item, value),
))
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export class TuiMultiSelectComponent<T>
private readonly hostedDropdown?: TuiHostedDropdownComponent;

@ViewChild(TuiInputTagComponent)
private readonly input?: TuiInputTagComponent;
readonly hostControl?: TuiInputTagComponent;

@Input()
@tuiDefaultProp()
Expand Down Expand Up @@ -158,14 +158,11 @@ export class TuiMultiSelectComponent<T>
}

get nativeFocusableElement(): HTMLInputElement | null {
return this.input ? this.input.nativeFocusableElement : null;
return this.hostControl?.nativeFocusableElement ?? null;
}

get focused(): boolean {
return (
(!!this.input && this.input.focused) ||
(!!this.hostedDropdown && this.hostedDropdown.focused)
);
return !!this.hostControl?.focused || !!this.hostedDropdown?.focused;
}

get computedValue(): readonly T[] {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
} from '@angular/core';
import {NgControl} from '@angular/forms';
import {
AbstractTuiMultipleControl,
TUI_DEFAULT_IDENTITY_MATCHER,
TuiContextWithImplicit,
TuiIdentityMatcher,
Expand All @@ -34,6 +35,7 @@ import {distinctUntilChanged, map, startWith} from 'rxjs/operators';
export class TuiSelectOptionComponent<T> implements OnInit {
readonly selected$ = merge(
this.control.valueChanges || EMPTY,
this.host?.hostControl?.control?.valueChanges ?? EMPTY,
tuiTypedFromEvent(this.elementRef.nativeElement, 'animationstart'),
).pipe(
startWith(null),
Expand All @@ -45,7 +47,7 @@ export class TuiSelectOptionComponent<T> implements OnInit {
@Inject(POLYMORPHEUS_CONTEXT)
readonly context: TuiContextWithImplicit<TemplateRef<Record<string, unknown>>>,
@Inject(TUI_DATA_LIST_HOST)
private readonly host: TuiDataListHost<T>,
protected readonly host: TuiDataListHost<T, AbstractTuiMultipleControl<string>>,
@Inject(ElementRef) private readonly elementRef: ElementRef<HTMLElement>,
@Inject(TuiOptionComponent) protected readonly option: TuiOptionComponent<T>,
@Optional()
Expand Down

0 comments on commit 5ba5679

Please sign in to comment.