Skip to content

Commit 1452035

Browse files
ksercsmarker-dao
andauthored
TagBox: fix async fieldTemplate rendering in React 18 (T1283948) (DevExpress#29490)
Signed-off-by: Anton Kuznetsov <[email protected]> Co-authored-by: marker dao ® <[email protected]>
1 parent daf126d commit 1452035

File tree

4 files changed

+211
-81
lines changed

4 files changed

+211
-81
lines changed

apps/react/examples/Examples.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import ValidationExample from './validation-example';
2626
import SelectBoxTemplatesExample from './selectbox-templates-example';
2727
import SelectBoxFieldTemplateExample from './selectbox-fieldtemplate-example';
2828
import SelectBoxParallelTemplateRenderExample from './selectbox-parallel-template-render-example';
29+
import TagBoxFieldTemplateCheckBoxesExample from './tagbox-fieldtemplate-checkboxes-example';
2930

3031
const Examples = () => {
3132
return (
@@ -92,6 +93,10 @@ const Examples = () => {
9293
<SelectBoxTemplatesExample />
9394
</Example>
9495

96+
<Example title="TagBox with field template and showSelectionControls=true">
97+
<TagBoxFieldTemplateCheckBoxesExample />
98+
</Example>
99+
95100
<Example title="SelectBox example with field template (controlled mode)">
96101
<SelectBoxFieldTemplateExample />
97102
</Example>
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import * as React from 'react';
2+
import { TagBox } from 'devextreme-react/tag-box';
3+
import { TextBox } from 'devextreme-react/text-box';
4+
5+
function Field() {
6+
return (<TextBox placeholder="test" />);
7+
}
8+
9+
const items = ['Item 1', 'Item 2', 'Item 3'];
10+
11+
export default (): React.ReactElement | null => {
12+
return (
13+
<TagBox
14+
items={items}
15+
showSelectionControls={true}
16+
fieldRender={Field}
17+
/>
18+
);
19+
};

packages/devextreme/js/__internal/ui/m_tag_box.ts

Lines changed: 23 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,6 @@ class TagBox<
7171

7272
_filteredGroupedItemsLoadPromise?: DeferredObj<unknown>;
7373

74-
_isInputReady?: DeferredObj<unknown>;
75-
7674
_selectAllValueChangeAction?: (event?: Record<string, unknown>) => void;
7775

7876
_multiTagPreparingAction?: (event?: Record<string, unknown>) => void;
@@ -95,6 +93,8 @@ class TagBox<
9593

9694
_selectedItems?: any[];
9795

96+
_tagsToRender?: any[];
97+
9898
_supportedKeys(): Record<
9999
// eslint-disable-next-line @typescript-eslint/no-invalid-void-type
100100
string, (e: KeyboardEvent, options?: Record<string, unknown>) => boolean | void
@@ -731,10 +731,7 @@ class TagBox<
731731
this._renderInputSize();
732732
this._renderTags()
733733
// @ts-expect-error ts-error
734-
.done(() => {
735-
this._popup?.refreshPosition();
736-
d.resolve();
737-
})
734+
.done(d.resolve)
738735
.fail(d.reject);
739736
// @ts-expect-error ts-error
740737
return d.promise();
@@ -1045,7 +1042,8 @@ class TagBox<
10451042
this._selectedItems = this._getItemsFromPlain(this._valuesToUpdate);
10461043

10471044
if (this._selectedItems.length === this._valuesToUpdate.length) {
1048-
this._renderTagsImpl(this._selectedItems);
1045+
this._tagsToRender = this._selectedItems;
1046+
this._renderTagsImpl();
10491047
isPlainDataUsed = true;
10501048
d.resolve();
10511049
}
@@ -1060,7 +1058,8 @@ class TagBox<
10601058
return;
10611059
}
10621060

1063-
this._renderTagsImpl(items);
1061+
this._tagsToRender = items;
1062+
this._renderTagsImpl();
10641063
d.resolve();
10651064
})
10661065
.fail(d.reject);
@@ -1069,12 +1068,15 @@ class TagBox<
10691068
return d.promise();
10701069
}
10711070

1072-
_renderTagsImpl(items): void {
1073-
this._renderTagsCore(items);
1074-
this._renderEmptyState();
1071+
_renderTagsImpl(): void {
1072+
this._renderField();
1073+
// @ts-expect-error ts-error
1074+
this.option('selectedItems', this._selectedItems.slice());
1075+
this._cleanTags();
10751076

1076-
if (!this._preserveFocusedTag) {
1077-
this._clearTagFocus();
1077+
const fieldTemplate = this._getFieldTemplate();
1078+
if (!fieldTemplate) {
1079+
this._renderTagsCore();
10781080
}
10791081
}
10801082

@@ -1134,32 +1136,24 @@ class TagBox<
11341136
}
11351137

11361138
_integrateInput(): void {
1137-
// @ts-expect-error ts-error
1138-
this._isInputReady.resolve();
11391139
super._integrateInput();
11401140

11411141
const tagsContainer = this.$element().find(`.${TEXTEDITOR_INPUT_CONTAINER_CLASS}`);
11421142

11431143
this._updateTagsContainer(tagsContainer);
11441144
this._renderTagRemoveAction();
1145+
this._renderTagsCore();
11451146
}
11461147

1147-
_renderTagsCore(items): void {
1148-
this._isInputReady?.reject();
1149-
1150-
this._isInputReady = Deferred();
1151-
this._renderField();
1152-
// @ts-expect-error ts-error
1153-
this.option('selectedItems', this._selectedItems.slice());
1154-
this._cleanTags();
1148+
_renderTagsCore(): void {
1149+
this._renderTagsElements(this._tagsToRender);
1150+
this._renderEmptyState();
11551151

1156-
if (this._input().length > 0) {
1157-
this._isInputReady.resolve();
1152+
if (!this._preserveFocusedTag) {
1153+
this._clearTagFocus();
11581154
}
11591155

1160-
when(this._isInputReady).done(() => {
1161-
this._renderTagsElements(items);
1162-
});
1156+
this._popup?.refreshPosition();
11631157
}
11641158

11651159
_renderTagsElements(items): void {
@@ -1661,6 +1655,7 @@ class TagBox<
16611655
super._clean();
16621656
delete this._valuesToUpdate;
16631657
delete this._tagTemplate;
1658+
delete this._tagsToRender;
16641659
}
16651660

16661661
_getSelectedItemsDifference(newItems, previousItems) {

0 commit comments

Comments
 (0)