Skip to content

Commit 4da19c5

Browse files
marker-daomarker dao ®
andauthored
DateBox: Update time list items when value is changed while popup is closed (T1325614) (#33153)
Co-authored-by: marker dao ® <youdontknow@marker-dao.eth>
1 parent 6f617ea commit 4da19c5

2 files changed

Lines changed: 78 additions & 7 deletions

File tree

packages/devextreme/js/__internal/ui/date_box/m_date_box.strategy.list.ts

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -72,10 +72,12 @@ class ListStrategy extends DateBoxStrategy {
7272

7373
if (selectedIndex === -1) {
7474
const { value } = this.dateBox.option();
75+
7576
return value as Date;
7677
}
7778

7879
const itemData = this._widgetItems[selectedIndex];
80+
7981
return this._getDateByItemData(itemData);
8082
}
8183

@@ -103,12 +105,12 @@ class ListStrategy extends DateBoxStrategy {
103105
_getWidgetOptions(): Record<string, unknown> {
104106
return {
105107
itemTemplate: this._timeListItemTemplate.bind(this),
106-
onItemClick: this._listItemClickHandler.bind(this),
108+
selectionMode: 'single',
107109
tabIndex: -1,
110+
onItemClick: this._listItemClickHandler.bind(this),
108111
onFocusedItemChanged: (
109112
e: DxEvent & { actionValue: string },
110113
) => this._refreshActiveDescendant(e),
111-
selectionMode: 'single',
112114
};
113115
}
114116

@@ -128,9 +130,10 @@ class ListStrategy extends DateBoxStrategy {
128130
}
129131

130132
this._widget.option('focusedElement', null);
131-
132133
this._setSelectedItemsByValue();
134+
133135
const { templatesRenderAsynchronously } = this.getWidget().option();
136+
134137
if (templatesRenderAsynchronously) {
135138
// eslint-disable-next-line no-restricted-globals
136139
this._asyncScrollTimeout = setTimeout(this._scrollToSelectedItem.bind(this));
@@ -141,18 +144,27 @@ class ListStrategy extends DateBoxStrategy {
141144

142145
dispose(): void {
143146
super.dispose();
147+
144148
clearTimeout(this._asyncScrollTimeout);
145149
}
146150

151+
renderValue(): void {
152+
this._updateValue();
153+
}
154+
147155
_updateValue(): void {
148156
if (!this._widget) {
149157
return;
150158
}
151159

152160
this._refreshItems();
153161

154-
this._setSelectedItemsByValue();
155-
this._scrollToSelectedItem();
162+
const { opened } = this.dateBox.option();
163+
164+
if (opened) {
165+
this._setSelectedItemsByValue();
166+
this._scrollToSelectedItem();
167+
}
156168
}
157169

158170
_setSelectedItemsByValue(): void {
@@ -192,10 +204,13 @@ class ListStrategy extends DateBoxStrategy {
192204

193205
_getTimeListItems(): Date[] {
194206
let min = this.dateBox.getDateOption('min') ?? this._getBoundaryDate('min');
207+
195208
const max = this.dateBox.getDateOption('max') ?? this._getBoundaryDate('max');
196209
const value = this.dateBox.getDateOption('value') ?? null;
210+
197211
// @ts-expect-error ts-error
198212
let delta = max - min;
213+
199214
const { interval = 30 } = this.dateBox.option();
200215
const minutes = min.getMinutes() % interval;
201216

@@ -206,6 +221,7 @@ class ListStrategy extends DateBoxStrategy {
206221
if (delta > dateUtils.ONE_DAY) {
207222
delta = dateUtils.ONE_DAY;
208223
}
224+
209225
// @ts-expect-error ts-error
210226
if (value - min < dateUtils.ONE_DAY) {
211227
return this._getRangeItems(min, new Date(min), delta);
@@ -237,7 +253,11 @@ class ListStrategy extends DateBoxStrategy {
237253

238254
_getBoundaryDate(boundary: 'min' | 'max'): Date {
239255
const boundaryValue = BOUNDARY_VALUES[boundary];
240-
const currentValue = new Date(ensureDefined(this.dateBox.getDateOption('value'), new Date(0)));
256+
const dateBoxDate = this.dateBox.getDateOption('value');
257+
const newDate = new Date(0);
258+
const definedValue = ensureDefined(dateBoxDate, newDate);
259+
260+
const currentValue = new Date(definedValue);
241261

242262
return new Date(
243263
currentValue.getFullYear(),
@@ -267,6 +287,7 @@ class ListStrategy extends DateBoxStrategy {
267287

268288
_getDateByItemData(itemData: Date): Date {
269289
let { value: date } = this.dateBox.option();
290+
270291
const hours = itemData.getHours();
271292
const minutes = itemData.getMinutes();
272293
const seconds = itemData.getSeconds();
@@ -276,6 +297,7 @@ class ListStrategy extends DateBoxStrategy {
276297

277298
if (date) {
278299
const { dateSerializationFormat } = this.dateBox.option();
300+
279301
if (dateSerializationFormat) {
280302
date = dateSerialization.deserializeDate(date) as Date;
281303
} else {
@@ -301,10 +323,13 @@ class ListStrategy extends DateBoxStrategy {
301323

302324
_updatePopupHeight(): void {
303325
const dropDownOptionsHeight = getSizeValue(this.dateBox.option('dropDownOptions.height'));
326+
304327
if (dropDownOptionsHeight === undefined || dropDownOptionsHeight === 'auto') {
305328
this.dateBox._setPopupOption('height', 'auto');
329+
306330
const popupHeight = getOuterHeight(this.getWidget().$element());
307331
const maxHeight = getHeight(window) * 0.45;
332+
308333
this.dateBox._setPopupOption('height', Math.min(popupHeight, maxHeight));
309334
}
310335
}

packages/devextreme/testing/tests/DevExpress.ui.widgets.editors/datebox.integration.tests.js

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2205,6 +2205,51 @@ QUnit.module('datebox w/ time list', {
22052205
assert.deepEqual(this.dateBox.option('value'), new Date(2020, 4, 13, 1, 30), 'date is correct');
22062206
});
22072207

2208+
QUnit.test('time selection should use updated date after external value change while popup is closed (T1325614)', function(assert) {
2209+
this.dateBox.option({
2210+
type: 'time',
2211+
pickerType: 'list',
2212+
value: new Date(1995, 11, 25, 12, 0),
2213+
opened: true
2214+
});
2215+
2216+
const $list = $(this.dateBox.content()).find(LIST_ITEM_SELECTOR);
2217+
2218+
$($list.eq(3)).trigger('dxclick');
2219+
2220+
this.dateBox.option('value', new Date(1995, 11, 12, 12, 0));
2221+
this.dateBox.open();
2222+
2223+
const $updatedList = $(this.dateBox.content()).find(LIST_ITEM_SELECTOR);
2224+
2225+
$($updatedList.eq(5)).trigger('dxclick');
2226+
2227+
const result = this.dateBox.option('value');
2228+
2229+
assert.strictEqual(result.getDate(), 12, 'date part is preserved after time selection');
2230+
assert.strictEqual(result.getMonth(), 11, 'month part is preserved after time selection');
2231+
assert.strictEqual(result.getFullYear(), 1995, 'year part is preserved after time selection');
2232+
});
2233+
2234+
QUnit.test('list items should be refreshed after value is changed while popup is closed (T1325614)', function(assert) {
2235+
this.dateBox.option({
2236+
type: 'time',
2237+
pickerType: 'list',
2238+
value: new Date(2020, 4, 13, 10, 0),
2239+
opened: true
2240+
});
2241+
2242+
this.dateBox.option('opened', false);
2243+
this.dateBox.option('value', new Date(2020, 8, 20, 10, 0));
2244+
this.dateBox.option('opened', true);
2245+
2246+
const itemData = this.dateBox._strategy._widgetItems[0];
2247+
2248+
assert.strictEqual(itemData.getFullYear(), 2020, 'item year is updated');
2249+
assert.strictEqual(itemData.getMonth(), 8, 'item month is updated');
2250+
assert.strictEqual(itemData.getDate(), 20, 'item day is updated');
2251+
});
2252+
22082253
QUnit.test('the date should be in range after the selection', function(assert) {
22092254
this.dateBox.option({
22102255
type: 'time',
@@ -2498,12 +2543,13 @@ QUnit.module('datebox w/ time list', {
24982543
dateSerializationFormat: 'yyyy-MM-ddTHH:mm:ssx',
24992544
});
25002545
const $input = $(this.dateBox.element()).find(`.${TEXTEDITOR_INPUT_CLASS}`);
2501-
const $items = $(this.dateBox.content()).find(LIST_ITEM_SELECTOR);
2546+
let $items = $(this.dateBox.content()).find(LIST_ITEM_SELECTOR);
25022547

25032548
$items.eq(1).trigger('dxclick');
25042549
assert.strictEqual($input.val(), $items.eq(1).text(), 'time is applied');
25052550

25062551
this.dateBox.open();
2552+
$items = $(this.dateBox.content()).find(LIST_ITEM_SELECTOR);
25072553
$items.eq(3).trigger('dxclick');
25082554
assert.strictEqual($input.val(), $items.eq(3).text(), 'new time is applied');
25092555
});

0 commit comments

Comments
 (0)