Adding on change event in editable dropdowns when value is changes through code. (#14952)

* Adding onChange events in editable dropdowns for values changed through code.

* moved event generation from angular wrapper to core component

* Moving event firing to value setter

* converting back updateSelection to private method

* Removing extra check

* Fixing broken tests by mocking used stuff

* Fixing onTextChange event

* Adding some tests

* Adding necessary tests

* small test name edit

* Fix an assert message
This commit is contained in:
Aasim Khan
2021-04-14 07:48:33 -07:00
committed by GitHub
parent b6bdb68596
commit 5e8ac017a6
4 changed files with 97 additions and 9 deletions

View File

@@ -75,6 +75,7 @@ export class Dropdown extends Disposable implements IListVirtualDelegate<string>
private _options: IDropdownOptions;
private _dataSource = new DropdownDataSource();
public fireOnTextChange?: boolean;
private _previousValue: string;
private _onBlur = this._register(new Emitter<void>());
public onBlur: Event<void> = this._onBlur.event;
@@ -228,7 +229,6 @@ export class Dropdown extends Disposable implements IListVirtualDelegate<string>
}
if (this.fireOnTextChange) {
this.value = e;
this._onValueChange.fire(e);
}
});
@@ -253,7 +253,7 @@ export class Dropdown extends Disposable implements IListVirtualDelegate<string>
return this._selectListContainer.classList.contains('visible');
}
private _setDropdownVisibility(visible: boolean): void {
public setDropdownVisibility(visible: boolean): void {
if (visible) {
this._selectListContainer.classList.add('visible');
} else {
@@ -264,7 +264,6 @@ export class Dropdown extends Disposable implements IListVirtualDelegate<string>
private _updateSelection(newValue: string): void {
this.value = newValue;
this._onValueChange.fire(newValue);
this._input.focus();
this._hideList();
}
@@ -277,12 +276,12 @@ export class Dropdown extends Disposable implements IListVirtualDelegate<string>
this.contextViewService.showContextView({
getAnchor: () => this._inputContainer,
render: container => {
this._setDropdownVisibility(true);
this.setDropdownVisibility(true);
DOM.append(container, this._selectListContainer);
this._updateDropDownList();
return {
dispose: () => {
this._setDropdownVisibility(false);
this.setDropdownVisibility(false);
}
};
}
@@ -332,7 +331,11 @@ export class Dropdown extends Disposable implements IListVirtualDelegate<string>
}
public set value(val: string) {
this._input.value = val;
if (this._previousValue !== val) {
this._input.value = val;
this._previousValue = val;
this._onValueChange.fire(val);
}
}
public get inputElement(): HTMLInputElement {
@@ -384,4 +387,12 @@ export class Dropdown extends Disposable implements IListVirtualDelegate<string>
public set ariaLabel(val: string) {
this._input.setAriaLabel(val);
}
public get input(): InputBox {
return this._input;
}
public get selectList(): List<IDropdownListItem> {
return this._selectList;
}
}

View File

@@ -0,0 +1,71 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import { Dropdown, IDropdownOptions } from 'sql/base/parts/editableDropdown/browser/dropdown';
const options: IDropdownOptions = {
values: [
'foo1',
'foo2',
'foobar3',
'foobar4'
]
};
suite('Editable dropdown tests', () => {
let container: HTMLElement;
setup(() => {
container = document.createElement('div');
container.style.position = 'absolute';
container.style.width = `${200}px`;
container.style.height = `${200}px`;
});
test('default value for editable dropdown is empty', () => {
const dropdown = new Dropdown(container, undefined, options);
assert(dropdown.value === '');
});
test('changing value through code fires onValueChange event', () => {
const dropdown = new Dropdown(container, undefined, options);
let count = 0;
dropdown.onValueChange((e) => {
count++;
});
dropdown.value = options.values[0];
assert(count === 1, 'onValueChange event was not fired');
dropdown.value = options.values[0];
assert(count === 1, 'onValueChange event should not be fired for setting the same value again');
dropdown.value = options.values[1];
assert(count === 2, 'onValueChange event was not fired for setting a new value of the dropdown');
});
test('changing value through input text fires onValue Change event', () => {
const dropdown = new Dropdown(container, undefined, options);
let count = 0;
dropdown.onValueChange((e) => {
count++;
});
dropdown.fireOnTextChange = true;
dropdown.setDropdownVisibility(true);
dropdown.input.value = options.values[0];
assert(count === 1, 'onValueChange event was not fired for an option from the dropdown list');
dropdown.input.value = 'foo';
assert(count === 2, 'onValueChange event was not fired for a value not in dropdown list');
assert(dropdown.selectList.length === 4, 'list does not have all the values that are matching the input box text');
assert(dropdown.value = 'foo');
dropdown.input.value = 'foobar';
assert(count === 3, 'onValueChange event was not fired for a value not in dropdown list');
assert(dropdown.selectList.length === 2, 'list does not have all the values that are matching the input box text');
assert(dropdown.value = 'foobar');
dropdown.fireOnTextChange = false;
dropdown.input.value = options.values[0];
assert(count === 3, 'onValueChange event was fired with input box value change even after setting the fireOnTextChange to false');
});
});