Skip to content

Commit f60cab5

Browse files
authored
Create property grid on demand (#6610)
* Create property grid on demand * Make sure survey in PropertyGridViewModel is not undefined * Fix unit test * Delay creating property grid survey * Fix theme survey root css classes
1 parent 86a2889 commit f60cab5

File tree

7 files changed

+90
-57
lines changed

7 files changed

+90
-57
lines changed

packages/survey-creator-core/src/components/tabs/designer-plugin.ts

+18-16
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,6 @@ export class TabDesignerPlugin implements ICreatorPlugin {
5959
}
6060
private updateTabControl() {
6161
if (this.showOneCategoryInPropertyGrid) {
62-
this.updateTabControlActions();
6362
this.creator.sidebar.sideAreaComponentName = "svc-tab-control";
6463
this.creator.sidebar.sideAreaComponentData = this.tabControlModel;
6564
} else {
@@ -136,11 +135,6 @@ export class TabDesignerPlugin implements ICreatorPlugin {
136135
if (this.creator.showCreatorThemeSettings) {
137136
this.themeModel.loadTheme(this.creator.creatorTheme);
138137
this.themePropertyGrid.obj = this.themeModel;
139-
this.themePropertyGrid.survey.onUpdatePanelCssClasses.add((_, options) => {
140-
options.cssClasses.panel.container += " spg-panel--group";
141-
});
142-
this.updateThemeChooserChoices();
143-
this.updatePredefinedColorChoices();
144138
}
145139
}
146140
setTheme() {
@@ -149,20 +143,15 @@ export class TabDesignerPlugin implements ICreatorPlugin {
149143
}
150144
}
151145

152-
private updateThemeChooserChoices(): void {
153-
const themeChooser = this.themePropertyGrid.survey.getQuestionByName("themeName") as QuestionDropdownModel;
154-
if (!!themeChooser) {
155-
themeChooser.choices = PredefinedCreatorThemes.map(theme => ({ value: theme, text: getLocString("creatortheme.names." + theme) }));
156-
}
157-
this.themePropertyGrid.survey.runExpressions();
158-
}
159146
private createCreatorThemeSettingsPage(creator: SurveyCreatorModel) {
160147
this.themeModel = new CreatorThemeModel();
161148
this.themePropertyGrid = new PropertyGridModel(undefined, creator, creatorThemeModelPropertyGridDefinition);
162-
this.themePropertyGrid.survey.css.root += "svc-creator-theme-settings";
163149
this.themePropertyGrid.showOneCategoryInPropertyGrid = true;
164150
this.themePropertyGrid.surveyInstanceCreatedArea = "designer-tab:creator-settings";
165151
const themePropertyGridViewModel = new PropertyGridViewModel(this.themePropertyGrid, creator);
152+
themePropertyGridViewModel.onNewSurveyCreatedCallback = () => {
153+
this.onThemePropertyGridSurveyCreated();
154+
};
166155
themePropertyGridViewModel.searchEnabled = false;
167156
this.themePropertyGridTab = this.creator.sidebar.addPage("creatorTheme", "svc-property-grid", themePropertyGridViewModel);
168157
this.themePropertyGridTab.caption = editorLocalization.getString("ed.creatorSettingTitle");
@@ -200,6 +189,19 @@ export class TabDesignerPlugin implements ICreatorPlugin {
200189
});
201190
this.tabControlModel.bottomToolbar.setItems([settingsAction]);
202191
}
192+
private onThemePropertyGridSurveyCreated() {
193+
const survey = this.themePropertyGrid.survey;
194+
survey.css.root += " svc-creator-theme-settings";
195+
survey.onUpdatePanelCssClasses.add((_, options) => {
196+
options.cssClasses.panel.container += " spg-panel--group";
197+
});
198+
const themeChooser = survey.getQuestionByName("themeName") as QuestionDropdownModel;
199+
if (!!themeChooser) {
200+
themeChooser.choices = PredefinedCreatorThemes.map(theme => ({ value: theme, text: getLocString("creatortheme.names." + theme) }));
201+
}
202+
survey.runExpressions();
203+
this.updatePredefinedColorChoices();
204+
}
203205

204206
constructor(private creator: SurveyCreatorModel) {
205207
creator.addTab({ name: "designer", plugin: this, iconName: "icon-config" });
@@ -208,10 +210,10 @@ export class TabDesignerPlugin implements ICreatorPlugin {
208210
this.showOneCategoryInPropertyGrid = creator.showOneCategoryInPropertyGrid;
209211
this.propertyGrid.showOneCategoryInPropertyGrid = this.showOneCategoryInPropertyGrid;
210212
this.propertyGrid.obj = creator.survey;
211-
this.propertyGrid.onSetNewObjectCallback = () => {
213+
this.propertyGridViewModel = new PropertyGridViewModel(this.propertyGrid, creator);
214+
this.propertyGridViewModel.onNewSurveyCreatedCallback = () => {
212215
this.updateTabControlActions();
213216
};
214-
this.propertyGridViewModel = new PropertyGridViewModel(this.propertyGrid, creator);
215217
this.propertyGridPlaceholderPage = this.creator.sidebar.addPage("propertyGridPlaceholder", "svc-property-grid-placeholder", this.propertyGridViewModel);
216218
this.propertyGridPlaceholderPage.caption = editorLocalization.getString("ed.surveySettings");
217219

packages/survey-creator-core/src/property-grid/index.ts

+28-20
Original file line numberDiff line numberDiff line change
@@ -819,8 +819,7 @@ export class PropertyGridModel {
819819
currentlySelectedPanel: PanelModel;
820820
currentlySelectedPage: PageModel;
821821
public onSetNewObjectCallback: () => void;
822-
823-
public objValueChangedCallback: () => void;
822+
public onNewSurveyCreatedCallback: () => void;
824823
public changedFromActionCallback: (obj: Base, propertyName: string) => void;
825824
public refresh(): void {
826825
this.setObj(this.objValue);
@@ -883,6 +882,9 @@ export class PropertyGridModel {
883882
}
884883
private setObj(value: Base) {
885884
this.objValue = value;
885+
if(this.onSetNewObjectCallback) {
886+
this.onSetNewObjectCallback();
887+
}
886888
this.classNameProperty = !!this.obj
887889
? PropertyJSONGenerator.getClassNameProperty(this.obj)
888890
: "";
@@ -893,24 +895,32 @@ export class PropertyGridModel {
893895
this.titleActionsCreator = !!this.obj
894896
? new PropertyGridTitleActionsCreator(this.obj, this.options)
895897
: undefined;
896-
var json = this.getSurveyJSON();
898+
if(!this.surveyValue) return;
899+
this.clearSurveyValue();
900+
this.createSurveyValue();
901+
}
902+
private clearSurveyValue() {
903+
this.surveyValue.onValidateQuestion.clear();
904+
this.surveyValue.onValueChanging.clear();
905+
this.surveyValue.onValueChanged.clear();
906+
this.surveyValue.onMatrixCellValueChanging.clear();
907+
this.surveyValue.onMatrixCellValidate.clear();
908+
this.surveyValue.onMatrixCellValueChanged.clear();
909+
this.surveyValue.editingObj = undefined;
910+
this.surveyValue.data = {};
911+
this.surveyValue.dispose();
912+
}
913+
private createSurveyValue(): void {
914+
const json = this.getSurveyJSON();
897915
if (this.options.readOnly) {
898916
json.mode = "display";
899917
}
900-
if (!!this.surveyValue) {
901-
this.surveyValue.onValidateQuestion.clear();
902-
this.surveyValue.onValueChanging.clear();
903-
this.surveyValue.onValueChanged.clear();
904-
this.surveyValue.onMatrixCellValueChanging.clear();
905-
this.surveyValue.onMatrixCellValidate.clear();
906-
this.surveyValue.onMatrixCellValueChanged.clear();
907-
this.surveyValue.editingObj = undefined;
908-
this.surveyValue.data = {};
909-
this.surveyValue.dispose();
910-
}
911918
this.surveyValue = this.createSurvey(json, (survey: SurveyModel): void => {
912919
this.onCreateSurvey(survey);
913920
});
921+
if (this.onNewSurveyCreatedCallback) {
922+
this.onNewSurveyCreatedCallback();
923+
}
914924
if (!this.obj) return;
915925
this.survey.onValueChanged.add((sender, options) => {
916926
this.onValueChanged(options);
@@ -975,9 +985,6 @@ export class PropertyGridModel {
975985
}
976986
});
977987
this.survey.editingObj = this.obj;
978-
if (this.objValueChangedCallback) {
979-
this.objValueChangedCallback();
980-
}
981988
this.updateDependedPropertiesEditors();
982989

983990
if (this.showOneCategoryInPropertyGrid) {
@@ -1082,6 +1089,9 @@ export class PropertyGridModel {
10821089
this.optionsValue = !!val ? val : new EmptySurveyCreatorOptions();
10831090
}
10841091
public get survey() {
1092+
if(!this.surveyValue) {
1093+
this.createSurveyValue();
1094+
}
10851095
return this.surveyValue;
10861096
}
10871097
public showOneCategoryInPropertyGrid: boolean = false;
@@ -1124,6 +1134,7 @@ export class PropertyGridModel {
11241134
});
11251135
}
11261136
public expandCategoryIfNeeded(): void {
1137+
if(!this.surveyValue) return;
11271138
const expandedTabName = creatorSettings.propertyGrid.defaultExpandedTabName;
11281139
if (!!expandedTabName && !this.getPropertyGridExpandedCategory()) {
11291140
const panel = <PanelModel>this.survey.getPanelByName(expandedTabName);
@@ -1218,9 +1229,6 @@ export class PropertyGridModel {
12181229
this.classNameValue !== options.value
12191230
) {
12201231
this.setObj(this.obj);
1221-
if(this.onSetNewObjectCallback) {
1222-
this.onSetNewObjectCallback();
1223-
}
12241232
if (!!this.survey) {
12251233
const question = this.survey.getQuestionByName(options.name);
12261234
if (!!question) {

packages/survey-creator-core/src/property-grid/property-grid-view-model.ts

+23-10
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ export class PropertyGridViewModel extends Base {
1414
public prevSelectionAction: Action;
1515
public objectSelectionAction: MenuButton;
1616
public searchManager = new SearchManagerPropertyGrid();
17+
public onNewSurveyCreatedCallback: () => void;
1718
private selectorPopupModel: PopupModel;
1819

1920
@property() hasPrev: boolean;
2021
@property() hasNext: boolean;
21-
@property() survey: SurveyModel;
2222
@property() selectedElementName: string;
2323
@property({
2424
onSet: (newValue: boolean, target: PropertyGridViewModel) => {
@@ -31,8 +31,11 @@ export class PropertyGridViewModel extends Base {
3131
super();
3232
this.searchEnabled = settings.propertyGrid.enableSearch;
3333
this.selectedElementName = this.getTitle();
34-
this.propertyGridModel.objValueChangedCallback = () => {
35-
this.onSurveyChanged();
34+
this.propertyGridModel.onSetNewObjectCallback = () => {
35+
this.onSurveyObjChanged();
36+
};
37+
this.propertyGridModel.onNewSurveyCreatedCallback = () => {
38+
this.onNewSurveyCreated();
3639
};
3740
this.propertyGridModel.changedFromActionCallback = (obj: Base, propertyName: string) => {
3841
if (!!this.selectionController) {
@@ -46,9 +49,14 @@ export class PropertyGridViewModel extends Base {
4649
this.selectorPopupModel.horizontalPosition = this.creator.sidebarLocation == "right" ? "left" : "right";
4750
}
4851
});
49-
this.onSurveyChanged();
52+
this.onSurveyObjChanged();
53+
}
54+
public get survey(): SurveyModel {
55+
return this.getPropertyValue("survey", undefined, () => this.propertyGridModel.survey);
56+
}
57+
public set survey(val: SurveyModel) {
58+
this.setPropertyValue("survey", val);
5059
}
51-
5260
public get rootCss(): string {
5361
return new CssClassBuilder()
5462
.append("spg-container")
@@ -71,7 +79,14 @@ export class PropertyGridViewModel extends Base {
7179
return this.creator.selectionHistoryController;
7280
}
7381

74-
private onSurveyChanged() {
82+
private onSurveyObjChanged() {
83+
this.updateTitle();
84+
if (this.selectionController) {
85+
this.hasPrev = this.selectionController.hasPrev;
86+
this.hasNext = this.selectionController.hasNext;
87+
}
88+
}
89+
private onNewSurveyCreated() {
7590
this.survey = this.propertyGridModel.survey;
7691
this.searchManager.setSurvey(this.survey);
7792
if (!!this.survey) {
@@ -81,10 +96,8 @@ export class PropertyGridViewModel extends Base {
8196
}
8297
});
8398
}
84-
this.updateTitle();
85-
if (this.selectionController) {
86-
this.hasPrev = this.selectionController.hasPrev;
87-
this.hasNext = this.selectionController.hasNext;
99+
if(this.onNewSurveyCreatedCallback) {
100+
this.onNewSurveyCreatedCallback();
88101
}
89102
}
90103
private updateTitle() {

packages/survey-creator-core/tests/creator-base-1.tests.ts

+1
Original file line numberDiff line numberDiff line change
@@ -4088,6 +4088,7 @@ test("Initial Property Grid category expanded state", (): any => {
40884088
const defaultJSON = settings.defaultNewSurveyJSON;
40894089
settings.defaultNewSurveyJSON = {};
40904090
creator.JSON = {};
4091+
expect(creator.propertyGrid).toBeTruthy();
40914092
expect(getCategoryName()).toBeFalsy();
40924093
creator.survey.addNewPage("page1");
40934094
creator.selectElement(creator.survey.getPageByName("page1"));

packages/survey-creator-core/tests/property-grid/property-grid-viewmodel.tests.ts

+7
Original file line numberDiff line numberDiff line change
@@ -184,4 +184,11 @@ test("Check object selector popup's display mode", () => {
184184
model = new PropertyGridViewModel(propertyGrid, creator);
185185
expect(model.objectSelectionAction.popupModel.displayMode).toEqual("overlay");
186186
_setIsTouch(false);
187+
});
188+
test("Create the property grid survey on request", () => {
189+
const creator = new CreatorTester();
190+
const propertyGrid = creator["designerPropertyGrid"];
191+
const model = new PropertyGridViewModel(propertyGrid, creator);
192+
expect(model.getPropertyValue("survey")).toBeFalsy();
193+
expect(model.survey).toBeTruthy();
187194
});

packages/survey-creator-core/tests/property-grid/property-grid.tests.ts

+12-11
Original file line numberDiff line numberDiff line change
@@ -612,22 +612,23 @@ test("Change editingObj of the property grid", () => {
612612
propertyGrid.obj = question2;
613613
expect(propertyGrid.survey.getValue("name")).toEqual("q2"); //"name property value is set for the second editingObj"
614614
});
615-
test("Check objValueChangedCallback", () => {
616-
var count = 0;
617-
var objValueChangedCallback = () => {
615+
test("Check onNewSurveyCreatedCallback", () => {
616+
let count = 0;
617+
const onNewSurveyCreatedCallback = () => {
618618
count++;
619619
};
620-
var question = new QuestionTextModel("q1");
621-
var question2 = new QuestionTextModel("q2");
622-
var propertyGrid = new PropertyGridModelTester(question);
623-
propertyGrid.objValueChangedCallback = objValueChangedCallback;
624-
expect(count).toEqual(0); //"objValueChangedCallback isn't called");
620+
const question = new QuestionTextModel("q1");
621+
const question2 = new QuestionTextModel("q2");
622+
const propertyGrid = new PropertyGridModelTester(question);
623+
propertyGrid.onNewSurveyCreatedCallback = onNewSurveyCreatedCallback;
624+
expect(count).toEqual(0); //"onNewSurveyCreatedCallback isn't called");
625625
propertyGrid.obj = question2;
626-
expect(count).toEqual(1); //"objValueChangedCallback is called after changing obj value"
626+
expect(propertyGrid.survey).toBeTruthy();
627+
expect(count).toEqual(1); //"onNewSurveyCreatedCallback is called after changing obj value"
627628
propertyGrid.obj = question2;
628-
expect(count).toEqual(1); //"objValueChangedCallback isn't called after setting same obj value"
629+
expect(count).toEqual(1); //"onNewSurveyCreatedCallback isn't called after setting same obj value"
629630
propertyGrid.obj = question;
630-
expect(count).toEqual(2); //"objValueChangedCallback is called after changing obj value"
631+
expect(count).toEqual(2); //"onNewSurveyCreatedCallback is called after changing obj value"
631632
});
632633
test("Support property visibleIf attribute", () => {
633634
var question = new QuestionCheckboxModel("q1");

packages/survey-creator-core/tests/side-bar.test.ts

+1
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ test("showOneCategoryInPropertyGrid: showPlaceholder into property grid if surve
6969
expect(creator.sidebar.header.componentName).toEqual("svc-side-bar-header");
7070
expect(creator.sidebar.header.componentData).toEqual(creator.sidebar.header);
7171

72+
expect(creator.propertyGrid).toBeTruthy();
7273
let tabs = designerPlugin["tabControlModel"].topToolbar.actions;
7374
expect(tabs.length).toBe(10);
7475
expect(tabs.map(t => t.id).join(",")).toBe("general,logo,navigation,question,pages,logic,data,validation,showOnCompleted,timer");

0 commit comments

Comments
 (0)