mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-24 01:25:37 -05:00
Add and move editable dropdown (#18589)
* add and move editable dropdown * merge dropdowns * merge dropdown cell factories * add new column and hide in properties * remove editable property
This commit is contained in:
411
src/sql/base/browser/ui/editableDropdown/browser/dropdown.ts
Normal file
411
src/sql/base/browser/ui/editableDropdown/browser/dropdown.ts
Normal file
@@ -0,0 +1,411 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import 'vs/css!./media/dropdownList';
|
||||
import { IInputBoxStyles, InputBox } from 'sql/base/browser/ui/inputBox/inputBox';
|
||||
import { DropdownDataSource, DropdownListRenderer, IDropdownListItem, SELECT_OPTION_ENTRY_TEMPLATE_ID } from 'sql/base/browser/ui/editableDropdown/browser/dropdownList';
|
||||
import * as DOM from 'vs/base/browser/dom';
|
||||
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
import { IContextViewProvider } from 'vs/base/browser/ui/contextview/contextview';
|
||||
import { IMessage, MessageType } from 'vs/base/browser/ui/inputbox/inputBox';
|
||||
import { IListVirtualDelegate } from 'vs/base/browser/ui/list/list';
|
||||
import { IListStyles, List } from 'vs/base/browser/ui/list/listWidget';
|
||||
import { Color } from 'vs/base/common/color';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { KeyCode } from 'vs/base/common/keyCodes';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { clamp } from 'vs/base/common/numbers';
|
||||
import { mixin } from 'vs/base/common/objects';
|
||||
import { ScrollbarVisibility } from 'vs/base/common/scrollable';
|
||||
import * as nls from 'vs/nls';
|
||||
|
||||
|
||||
export interface IDropdownOptions extends IDropdownStyles {
|
||||
/**
|
||||
* Whether or not a options in the list must be selected or a "new" option can be set
|
||||
*/
|
||||
strictSelection?: boolean;
|
||||
/**
|
||||
* Maximum height of the dropdown, defaults to 500
|
||||
*/
|
||||
maxHeight?: number;
|
||||
/**
|
||||
* Initial values for the dropdown, can be set afterwards
|
||||
*/
|
||||
values?: string[];
|
||||
/**
|
||||
* Placeholder to use in the input
|
||||
*/
|
||||
placeholder?: string;
|
||||
/**
|
||||
* Warning message to show when the input is not part of the supplied list, only used if strictSelection = false
|
||||
*/
|
||||
warningMessage?: string;
|
||||
/**
|
||||
* Error Message to show if input is not part of the supplied list, only used if strictSelection = false
|
||||
*/
|
||||
errorMessage?: string;
|
||||
/**
|
||||
* Value to use as aria-label for the input box
|
||||
*/
|
||||
ariaLabel?: string;
|
||||
}
|
||||
|
||||
export interface IDropdownStyles {
|
||||
contextBackground?: Color;
|
||||
contextBorder?: Color;
|
||||
}
|
||||
|
||||
const errorMessage = nls.localize('editableDropdown.errorValidate', "Must be an option from the list");
|
||||
|
||||
const defaults: IDropdownOptions = {
|
||||
strictSelection: true,
|
||||
maxHeight: 300,
|
||||
errorMessage: errorMessage
|
||||
};
|
||||
|
||||
export class Dropdown extends Disposable implements IListVirtualDelegate<string> {
|
||||
private _el: HTMLElement;
|
||||
private _inputContainer: HTMLElement;
|
||||
private _selectListContainer: HTMLElement;
|
||||
private _input: InputBox;
|
||||
private _selectList: List<IDropdownListItem>;
|
||||
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;
|
||||
|
||||
private _onValueChange = this._register(new Emitter<string>());
|
||||
public onValueChange: Event<string> = this._onValueChange.event;
|
||||
|
||||
private _onFocus = this._register(new Emitter<void>());
|
||||
public onFocus: Event<void> = this._onFocus.event;
|
||||
private readonly _widthControlElement: HTMLElement;
|
||||
|
||||
constructor(
|
||||
container: HTMLElement,
|
||||
private readonly contextViewService: IContextViewProvider,
|
||||
opt?: IDropdownOptions
|
||||
) {
|
||||
super();
|
||||
this._options = opt || Object.create(null);
|
||||
mixin(this._options, defaults, false);
|
||||
this._widthControlElement = DOM.append(container, document.createElement('span'));
|
||||
this._widthControlElement.classList.add('monaco-dropdown-width-control-element');
|
||||
this._widthControlElement.setAttribute('aria-hidden', 'true');
|
||||
|
||||
this._el = DOM.append(container, DOM.$('.monaco-dropdown'));
|
||||
this._el.style.width = '100%';
|
||||
|
||||
this._inputContainer = DOM.append(this._el, DOM.$('.dropdown-input.select-container'));
|
||||
this._inputContainer.style.width = '100%';
|
||||
this._selectListContainer = DOM.$('div');
|
||||
|
||||
this._input = new InputBox(this._inputContainer, contextViewService, {
|
||||
validationOptions: {
|
||||
// @SQLTODO
|
||||
// showMessage: false,
|
||||
validation: v => this._inputValidator(v)
|
||||
},
|
||||
placeholder: this._options.placeholder,
|
||||
ariaLabel: this._options.ariaLabel
|
||||
});
|
||||
|
||||
// Clear title from input box element (defaults to placeholder value) since we don't want a tooltip for the selected value
|
||||
// in the text box - we already have tooltips for each item in the dropdown itself.
|
||||
this._input.inputElement.title = '';
|
||||
|
||||
// add the padding to the element show the the text won't overlap with the dropdown arrow
|
||||
this._input.inputElement.style.paddingRight = '22px';
|
||||
|
||||
this._inputContainer.setAttribute('role', 'combobox');
|
||||
|
||||
this._register(DOM.addDisposableListener(this._input.inputElement, DOM.EventType.CLICK, () => {
|
||||
this._showList();
|
||||
}));
|
||||
|
||||
const inputTracker = this._register(DOM.trackFocus(this._input.inputElement));
|
||||
inputTracker.onDidBlur(() => {
|
||||
if (!this._selectList.isDOMFocused()) {
|
||||
this._onBlur.fire();
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
This event listener is intended to close the expanded drop down when the ADS shell window is resized
|
||||
to prevent the list from rendering incorrectly at the top left corner of the window.
|
||||
*/
|
||||
this._register(DOM.addDisposableListener(window, DOM.EventType.RESIZE, () => {
|
||||
if (this._isDropDownVisible) {
|
||||
this._hideList();
|
||||
}
|
||||
}));
|
||||
|
||||
this._register(DOM.addStandardDisposableListener(this._input.inputElement, DOM.EventType.KEY_DOWN, (e: StandardKeyboardEvent) => {
|
||||
switch (e.keyCode) {
|
||||
case KeyCode.Enter:
|
||||
if (this._input.validate() === undefined) {
|
||||
this._onValueChange.fire(this._input.value);
|
||||
}
|
||||
e.stopPropagation();
|
||||
break;
|
||||
case KeyCode.Escape:
|
||||
if (this._isDropDownVisible) {
|
||||
this._input.validate();
|
||||
this._onBlur.fire();
|
||||
this._hideList();
|
||||
e.stopPropagation();
|
||||
}
|
||||
break;
|
||||
case KeyCode.Tab:
|
||||
this._input.validate();
|
||||
this._onBlur.fire();
|
||||
this._hideList();
|
||||
e.stopPropagation();
|
||||
break;
|
||||
case KeyCode.DownArrow:
|
||||
if (!this._isDropDownVisible) {
|
||||
this._showList();
|
||||
}
|
||||
setTimeout(() => {
|
||||
this._selectList.domFocus();
|
||||
this._selectList.focusFirst();
|
||||
}, 0);
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
break;
|
||||
}
|
||||
}));
|
||||
|
||||
this._selectList = new List('EditableDropdown', this._selectListContainer, this, [new DropdownListRenderer()], {
|
||||
useShadows: false,
|
||||
verticalScrollMode: ScrollbarVisibility.Visible,
|
||||
keyboardSupport: true,
|
||||
mouseSupport: true,
|
||||
accessibilityProvider: {
|
||||
getAriaLabel: (element) => element.text,
|
||||
getWidgetAriaLabel: () => nls.localize('selectBox', "Select Box"),
|
||||
getRole: () => 'option',
|
||||
getWidgetRole: () => 'listbox'
|
||||
}
|
||||
});
|
||||
|
||||
this.values = this._options.values;
|
||||
this._register(this._selectList.onDidBlur(() => {
|
||||
this._hideList();
|
||||
}));
|
||||
|
||||
this._register(this._selectList.onKeyDown((e) => {
|
||||
const event = new StandardKeyboardEvent(e);
|
||||
let handled: boolean = false;
|
||||
switch (event.keyCode) {
|
||||
case KeyCode.Escape:
|
||||
this._hideList();
|
||||
setTimeout(() => {
|
||||
this._input.focus();
|
||||
}, 0);
|
||||
handled = true;
|
||||
break;
|
||||
case KeyCode.Enter:
|
||||
case KeyCode.Space:
|
||||
const focusedElements = this._selectList.getFocusedElements();
|
||||
if (focusedElements.length !== 0) {
|
||||
this._updateSelection(focusedElements[0].text);
|
||||
handled = true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
if (handled) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
}));
|
||||
this._register(this._selectList.onMouseClick((e) => {
|
||||
if (e.element) {
|
||||
this._updateSelection(e.element.text);
|
||||
}
|
||||
}));
|
||||
|
||||
this._input.onDidChange(e => {
|
||||
if (this._dataSource.values.length > 0) {
|
||||
this._dataSource.filter = e;
|
||||
if (this._isDropDownVisible) {
|
||||
this._updateDropDownList();
|
||||
}
|
||||
}
|
||||
if (this.fireOnTextChange) {
|
||||
this.value = e;
|
||||
}
|
||||
});
|
||||
|
||||
this.onBlur(() => {
|
||||
this._hideList();
|
||||
this._input.validate();
|
||||
});
|
||||
|
||||
this._register(this._selectList);
|
||||
this._register(this._input);
|
||||
}
|
||||
|
||||
getHeight(): number {
|
||||
return 22;
|
||||
}
|
||||
|
||||
getTemplateId(): string {
|
||||
return SELECT_OPTION_ENTRY_TEMPLATE_ID;
|
||||
}
|
||||
|
||||
private get _isDropDownVisible(): boolean {
|
||||
return this._selectListContainer.classList.contains('visible');
|
||||
}
|
||||
|
||||
public setDropdownVisibility(visible: boolean): void {
|
||||
if (visible) {
|
||||
this._selectListContainer.classList.add('visible');
|
||||
} else {
|
||||
this._selectListContainer.classList.remove('visible');
|
||||
}
|
||||
this._selectListContainer.setAttribute('aria-hidden', `${!visible}`);
|
||||
}
|
||||
|
||||
private _updateSelection(newValue: string): void {
|
||||
this.value = newValue;
|
||||
this._input.focus();
|
||||
this._hideList();
|
||||
}
|
||||
|
||||
private _showList(): void {
|
||||
if (this._input.isEnabled()) {
|
||||
this._inputContainer.setAttribute('aria-expanded', 'true');
|
||||
this._onFocus.fire();
|
||||
this._dataSource.filter = undefined;
|
||||
this.contextViewService.showContextView({
|
||||
getAnchor: () => this._inputContainer,
|
||||
render: container => {
|
||||
this.setDropdownVisibility(true);
|
||||
DOM.append(container, this._selectListContainer);
|
||||
this._updateDropDownList();
|
||||
return {
|
||||
dispose: () => {
|
||||
this.setDropdownVisibility(false);
|
||||
}
|
||||
};
|
||||
}
|
||||
}, this._inputContainer);
|
||||
}
|
||||
}
|
||||
|
||||
private _hideList(): void {
|
||||
this.contextViewService.hideContextView();
|
||||
this._inputContainer.setAttribute('aria-expanded', 'false');
|
||||
}
|
||||
|
||||
private _updateDropDownList(): void {
|
||||
this._selectList.splice(0, this._selectList.length, this._dataSource.filteredValues.map(v => { return { text: v }; }));
|
||||
|
||||
let width = this._inputContainer.clientWidth;
|
||||
|
||||
// Find the longest option in the list and set our width to that (max 500px)
|
||||
const longestOption = this._dataSource.filteredValues.reduce((previous, current) => {
|
||||
return previous.length > current.length ? previous : current;
|
||||
}, '');
|
||||
this._widthControlElement.innerText = longestOption;
|
||||
|
||||
const inputContainerWidth = DOM.getContentWidth(this._inputContainer);
|
||||
const longestOptionWidth = DOM.getTotalWidth(this._widthControlElement);
|
||||
width = clamp(longestOptionWidth, inputContainerWidth, 500);
|
||||
|
||||
const height = Math.min(this._dataSource.filteredValues.length * this.getHeight(), this._options.maxHeight ?? 500);
|
||||
this._selectListContainer.style.width = `${width}px`;
|
||||
this._selectListContainer.style.height = `${height}px`;
|
||||
this._selectList.layout(height, width);
|
||||
}
|
||||
|
||||
public set values(vals: string[] | undefined) {
|
||||
if (vals) {
|
||||
this._dataSource.filter = undefined;
|
||||
this._dataSource.values = vals;
|
||||
if (this._isDropDownVisible) {
|
||||
this._updateDropDownList();
|
||||
}
|
||||
this._input.validate();
|
||||
}
|
||||
}
|
||||
|
||||
public get value(): string {
|
||||
return this._input.value;
|
||||
}
|
||||
|
||||
public set value(val: string) {
|
||||
this._input.value = val;
|
||||
if (this._previousValue !== val) {
|
||||
this._previousValue = val;
|
||||
this._onValueChange.fire(val);
|
||||
}
|
||||
}
|
||||
|
||||
public get inputElement(): HTMLInputElement {
|
||||
return this._input.inputElement;
|
||||
}
|
||||
|
||||
public focus() {
|
||||
this._input.focus();
|
||||
}
|
||||
|
||||
public blur() {
|
||||
this._input.blur();
|
||||
this._hideList();
|
||||
}
|
||||
|
||||
style(style: IListStyles & IInputBoxStyles & IDropdownStyles) {
|
||||
this._selectList.style(style);
|
||||
this._input.style(style);
|
||||
this._selectListContainer.style.backgroundColor = style.contextBackground ? style.contextBackground.toString() : '';
|
||||
this._selectListContainer.style.outline = `1px solid ${style.contextBorder}`;
|
||||
}
|
||||
|
||||
private _inputValidator(value: string): IMessage | null {
|
||||
if (!this._input.hasFocus() && this._input.isEnabled() && !this._selectList.isDOMFocused() && !this._dataSource.values.some(i => i === value)) {
|
||||
if (this._options.strictSelection && this._options.errorMessage) {
|
||||
return {
|
||||
content: this._options.errorMessage,
|
||||
type: MessageType.ERROR
|
||||
};
|
||||
} else if (this._options.warningMessage) {
|
||||
return {
|
||||
content: this._options.warningMessage,
|
||||
type: MessageType.WARNING
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public set enabled(val: boolean) {
|
||||
this._input.setEnabled(val);
|
||||
}
|
||||
|
||||
public get enabled(): boolean {
|
||||
return this._input.isEnabled();
|
||||
}
|
||||
|
||||
public set ariaLabel(val: string) {
|
||||
this._input.setAriaLabel(val);
|
||||
}
|
||||
|
||||
public get input(): InputBox {
|
||||
return this._input;
|
||||
}
|
||||
|
||||
public get selectList(): List<IDropdownListItem> {
|
||||
return this._selectList;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import 'vs/css!./media/dropdownList';
|
||||
import * as DOM from 'vs/base/browser/dom';
|
||||
import { IListRenderer } from 'vs/base/browser/ui/list/list';
|
||||
const $ = DOM.$;
|
||||
|
||||
export const SELECT_OPTION_ENTRY_TEMPLATE_ID = 'editableDropDownOption.entry.template';
|
||||
|
||||
export interface IDropdownListTemplateData {
|
||||
root: HTMLElement;
|
||||
text: HTMLElement;
|
||||
}
|
||||
|
||||
export interface IDropdownListItem {
|
||||
text: string;
|
||||
}
|
||||
|
||||
export class DropdownListRenderer implements IListRenderer<IDropdownListItem, IDropdownListTemplateData> {
|
||||
|
||||
get templateId(): string { return SELECT_OPTION_ENTRY_TEMPLATE_ID; }
|
||||
|
||||
renderTemplate(container: HTMLElement): IDropdownListTemplateData {
|
||||
const data: IDropdownListTemplateData = Object.create(null);
|
||||
data.root = container;
|
||||
data.text = DOM.append(container, $('span.editable-drop-option-text'));
|
||||
return data;
|
||||
}
|
||||
|
||||
renderElement(element: IDropdownListItem, index: number, templateData: IDropdownListTemplateData): void {
|
||||
const data: IDropdownListTemplateData = templateData;
|
||||
const text = element.text;
|
||||
data.text.textContent = text;
|
||||
data.text.title = text;
|
||||
}
|
||||
|
||||
disposeTemplate(templateData: IDropdownListTemplateData): void {
|
||||
}
|
||||
}
|
||||
|
||||
export class DropdownDataSource {
|
||||
public values: string[] = [];
|
||||
|
||||
public filter: string | undefined = undefined;
|
||||
|
||||
public get filteredValues(): string[] {
|
||||
if (this.filter) {
|
||||
return this.values.filter(v => {
|
||||
return v.toLocaleLowerCase().indexOf(this.filter.toLocaleLowerCase()) !== -1;
|
||||
});
|
||||
}
|
||||
return this.values;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
.monaco-dropdown-width-control-element {
|
||||
position: absolute;
|
||||
left: -10000px;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.editable-drop-option-text {
|
||||
padding-left: 6px;
|
||||
padding-right: 4px;
|
||||
text-overflow: ellipsis;
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
@@ -9,12 +9,13 @@ import { getCodeForKeyCode } from 'vs/base/browser/keyboardEvent';
|
||||
import { IContextViewProvider } from 'vs/base/browser/ui/contextview/contextview';
|
||||
import { KeyCode } from 'vs/base/common/keyCodes';
|
||||
import * as DOM from 'vs/base/browser/dom';
|
||||
import { Dropdown } from 'sql/base/browser/ui/editableDropdown/browser/dropdown';
|
||||
|
||||
export interface ITableCellEditorOptions {
|
||||
valueGetter?: (item: Slick.SlickData, column: Slick.Column<Slick.SlickData>) => string,
|
||||
valueSetter?: (context: any, row: number, item: Slick.SlickData, column: Slick.Column<Slick.SlickData>, value: string) => void,
|
||||
optionsGetter?: (item: Slick.SlickData, column: Slick.Column<Slick.SlickData>) => string[],
|
||||
editorStyler: (component: InputBox | SelectBox) => void
|
||||
editorStyler: (component: InputBox | SelectBox | Dropdown) => void
|
||||
}
|
||||
|
||||
export class TableCellEditorFactory {
|
||||
@@ -101,11 +102,12 @@ export class TableCellEditorFactory {
|
||||
return TextEditor;
|
||||
}
|
||||
|
||||
public getSelectBoxEditorClass(context: any, defaultOptions: string[]): any {
|
||||
public getDropdownEditorClass(context: any, defaultOptions: string[], isEditable?: boolean): any {
|
||||
const self = this;
|
||||
class TextEditor {
|
||||
private _originalValue: string;
|
||||
private _selectBox: SelectBox;
|
||||
private _dropdown: Dropdown;
|
||||
private _keyCaptureList: number[];
|
||||
|
||||
constructor(private _args: Slick.Editors.EditorOptions<Slick.SlickData>) {
|
||||
@@ -124,21 +126,37 @@ export class TableCellEditorFactory {
|
||||
public init(): void {
|
||||
const container = DOM.$('');
|
||||
this._args.container.appendChild(container);
|
||||
this._selectBox = new SelectBox([], undefined, self._contextViewProvider);
|
||||
container.style.height = '100%';
|
||||
container.style.width = '100%';
|
||||
this._selectBox.render(container);
|
||||
this._selectBox.selectElem.style.height = '100%';
|
||||
self._options.editorStyler(this._selectBox);
|
||||
this._selectBox.focus();
|
||||
if (isEditable) {
|
||||
this._dropdown = new Dropdown(container, self._contextViewProvider);
|
||||
container.style.height = '100%';
|
||||
container.style.width = '100%';
|
||||
self._options.editorStyler(this._dropdown);
|
||||
this._dropdown.focus();
|
||||
} else {
|
||||
this._selectBox = new SelectBox([], undefined, self._contextViewProvider);
|
||||
container.style.height = '100%';
|
||||
container.style.width = '100%';
|
||||
this._selectBox.render(container);
|
||||
this._selectBox.selectElem.style.height = '100%';
|
||||
self._options.editorStyler(this._selectBox);
|
||||
this._selectBox.focus();
|
||||
}
|
||||
}
|
||||
|
||||
public destroy(): void {
|
||||
this._selectBox.dispose();
|
||||
if (isEditable) {
|
||||
this._dropdown.dispose();
|
||||
} else {
|
||||
this._selectBox.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
public focus(): void {
|
||||
this._selectBox.focus();
|
||||
if (isEditable) {
|
||||
this._dropdown.focus();
|
||||
} else {
|
||||
this._selectBox.focus();
|
||||
}
|
||||
}
|
||||
|
||||
public loadValue(item: Slick.SlickData): void {
|
||||
@@ -146,8 +164,13 @@ export class TableCellEditorFactory {
|
||||
const options = self._options.optionsGetter(item, this._args.column) ?? defaultOptions;
|
||||
const idx = options?.indexOf(this._originalValue);
|
||||
if (idx > -1) {
|
||||
this._selectBox.setOptions(options);
|
||||
this._selectBox.select(idx);
|
||||
if (isEditable) {
|
||||
this._dropdown.values = options;
|
||||
this._dropdown.value = options[idx];
|
||||
} else {
|
||||
this._selectBox.setOptions(options);
|
||||
this._selectBox.select(idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,12 +180,19 @@ export class TableCellEditorFactory {
|
||||
}
|
||||
|
||||
public isValueChanged(): boolean {
|
||||
return this._selectBox.value !== this._originalValue.toString();
|
||||
|
||||
if (isEditable) {
|
||||
return this._dropdown.value !== this._originalValue.toString();
|
||||
} else {
|
||||
return this._selectBox.value !== this._originalValue.toString();
|
||||
}
|
||||
}
|
||||
|
||||
public serializeValue(): any {
|
||||
return this._selectBox.value;
|
||||
if (isEditable) {
|
||||
return this._dropdown.value;
|
||||
} else {
|
||||
return this._selectBox.value;
|
||||
}
|
||||
}
|
||||
|
||||
public validate(): Slick.ValidateResults {
|
||||
|
||||
Reference in New Issue
Block a user