diff --git a/src/question_paneldynamic.ts b/src/question_paneldynamic.ts index 68ec2c0700..bad63aef77 100644 --- a/src/question_paneldynamic.ts +++ b/src/question_paneldynamic.ts @@ -284,6 +284,7 @@ export class QuestionPanelDynamicModel extends Question this.createLocalizableString("panelNextText", this, false, "pageNextText"); this.createLocalizableString("noEntriesText", this, false, "noEntriesText"); this.createLocalizableString("templateTabTitle", this, true, "panelDynamicTabTextFormat"); + this.createLocalizableString("tabTitlePlaceholder", this, true); this.registerPropertyChangedHandlers(["panelsState"], () => { this.setPanelsState(); }); @@ -426,6 +427,15 @@ export class QuestionPanelDynamicModel extends Question get locTemplateTabTitle(): LocalizableString { return this.getLocalizableString("templateTabTitle"); } + public get tabTitlePlaceholder(): string { + return this.locTabTitlePlaceholder.text; + } + public set tabTitlePlaceholder(newValue: string) { + this.locTabTitlePlaceholder.text = newValue; + } + get locTabTitlePlaceholder(): LocalizableString { + return this.getLocalizableString("tabTitlePlaceholder"); + } /** * A template for panel descriptions. * @see template @@ -2394,6 +2404,9 @@ export class QuestionPanelDynamicModel extends Question const locTitle = new LocalizableString(panel, true); locTitle.onGetTextCallback = (str: string): string => { + if(!str) { + str = this.locTabTitlePlaceholder.renderedHtml; + } if(!this.survey) return str; const options = { title: str, @@ -2502,6 +2515,8 @@ Serializer.addClass( { name: "templateTitle:text", serializationProperty: "locTemplateTitle" }, { name: "templateTabTitle", serializationProperty: "locTemplateTabTitle", visibleIf: (obj: any) => { return obj.renderMode === "tab"; } }, + { name: "tabTitlePlaceholder", serializationProperty: "locTabTitlePlaceholder", + visibleIf: (obj: any) => { return obj.renderMode === "tab"; } }, { name: "templateDescription:text", serializationProperty: "locTemplateDescription", diff --git a/tests/question_paneldynamic_tests.ts b/tests/question_paneldynamic_tests.ts index 07b28c3e34..67070ce41b 100644 --- a/tests/question_paneldynamic_tests.ts +++ b/tests/question_paneldynamic_tests.ts @@ -6161,6 +6161,36 @@ QUnit.test("templateVisibleIf & renderMode: tab, additionalTitleToolbar&template assert.equal(panelTabToolbar.actions[1].locTitle.textOrHtml, "#2-2 a"); assert.equal(panelTabToolbar.actions[2].locTitle.textOrHtml, "#3-3 a"); }); +QUnit.test("templateVisibleIf & renderMode: tab, templateTabTitle&tabTitlePlaceholder in JSON", function (assert) { + const survey = new SurveyModel({ + elements: [ + { type: "paneldynamic", + name: "panel", + templateElements: [ + { type: "text", name: "q1" }, + { type: "text", name: "q2" } + ], + panelCount: 2, + renderMode: "tab", + tabTitlePlaceholder: "Empty value", + templateTabTitle: "{panel.q1}" + }], + }); + const panel = survey.getQuestionByName("panel"); + const panelTabToolbar = panel.additionalTitleToolbar; + assert.equal(panelTabToolbar.actions.length, 2, "There are two panels"); + assert.equal(panelTabToolbar.actions[0].locTitle.textOrHtml, "Empty value", "#1"); + assert.equal(panelTabToolbar.actions[1].locTitle.textOrHtml, "Empty value", "#2"); + panel.panels[1].getQuestionByName("q1").value = "item2"; + assert.equal(panelTabToolbar.actions[0].locTitle.textOrHtml, "Empty value", "#3"); + assert.equal(panelTabToolbar.actions[1].locTitle.textOrHtml, "item2", "#4"); + panel.panels[0].getQuestionByName("q1").value = "item1"; + assert.equal(panelTabToolbar.actions[0].locTitle.textOrHtml, "item1", "#5"); + assert.equal(panelTabToolbar.actions[1].locTitle.textOrHtml, "item2", "#6"); + panel.panels[1].getQuestionByName("q1").clearValue(); + assert.equal(panelTabToolbar.actions[0].locTitle.textOrHtml, "item1", "#7"); + assert.equal(panelTabToolbar.actions[1].locTitle.textOrHtml, "Empty value", "#8"); +}); QUnit.test("templateVisibleIf & additionalTitleToolbar", function (assert) { const survey = new SurveyModel({ elements: [