Closed JaneSjs closed 8 months ago
We've fixed some issues in the example code and in the library code. Closing for now.
It appears that some code changes were required. In particular, creatorSettings
was unnecessary.
The updated demo is available at reusable-custom-themes.zip.
survey-creator.component.ts
import { Component, OnInit } from "@angular/core";
import { SurveyCreatorModel } from "survey-creator-core";
import "survey-core/survey.i18n.js";
import "survey-creator-core/survey-creator-core.i18n.js";
import { formJSON } from "./survey_json";
import { customTheme } from "./theme_json";
import { lightTheme, darkTheme } from "./theme_variations";
import { SurveyModel, Action, ComputedUpdater, settings, surveyLocalization, SvgRegistry } from "survey-core";
import { editorLocalization, PredefinedThemes } from "survey-creator-core";
import "survey-core/defaultV2.css";
import "survey-creator-core/survey-creator-core.css";
const enLocale = editorLocalization.getLocale("en");
@Component({
// tslint:disable-next-line:component-selector
selector: "survey-creator-component",
templateUrl: "./survey-creator.component.html",
styleUrls: ["./survey-creator.component.css"]
})
export class SurveyCreatorComponent implements OnInit {
model: SurveyCreatorModel;
ngOnInit() {
const options = {
showThemeTab: true
};
const creator = new SurveyCreatorModel(options);
// Register a custom SVG icon for the Save Theme action
const saveAsIcon = '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d = "M24 11H22V13H20V11H18V9H20V7H22V9H24V11ZM20 14H22V20C22 21.1 21.1 22 20 22H4C2.9 22 2 21.1 2 20V4L4 2H20C21.1 2 22 2.9 22 4V6H20V4H17V8H7V4H4.83L4 4.83V20H6V13H18V20H20V14ZM9 6H15V4H9V6ZM16 15H8V20H16V15Z" fill = "black" fill-opacity="0.45" /></svg>';
SvgRegistry.registerIconFromSvg("icon-saveas", saveAsIcon);
const themeTabPlugin = creator.themeEditor;
function addCustomTheme(theme, userFriendlyThemeName) {
// Add a localized user-friendly theme name
enLocale.theme.names[theme.themeName] = userFriendlyThemeName;
// Add the theme to the theme list
themeTabPlugin.addTheme(theme);
}
// Add a custom theme to the Theme Editor
addCustomTheme(customTheme, "Custom Theme");
// Set the custom theme as an initial survey theme
creator.theme = customTheme;
// Register a custom theme with Dark and Light variations
addCustomTheme(lightTheme, "Custom Theme with Dark/Light Variations");
addCustomTheme(darkTheme, "Custom Theme with Dark/Light Variations");
function askForThemeName(title, text, initialValue, callback) {
const survey = new SurveyModel({
showNavigationButtons: "none",
showQuestionNumbers: "none",
questionErrorLocation: "bottom",
questions: [{
type: "text",
name: "title",
title: text,
defaultValue: initialValue.title,
isRequired: true,
requiredErrorText: "Theme title is required"
}]
});
survey['isCompact'] = true;
const popupContainer: HTMLElement = <HTMLElement>settings.environment.popupMountContainer;
const popupViewModel = settings.showDialog({
componentName: "survey",
data: { model: survey},
onApply: () => {
if (survey.completeLastPage()) {
callback(true, survey.data);
return true;
}
return false;
},
onCancel: () => {
callback(false);
return false;
},
title: title,
displayMode: "popup",
isFocusedContent: true,
cssClass: "my-dialog"
}, popupContainer);
const toolbar = popupViewModel.footerToolbar;
const applyBtn = toolbar.getActionById("apply");
const cancelBtn = toolbar.getActionById("cancel");
cancelBtn.title = surveyLocalization.getString("cancel");
applyBtn.title = surveyLocalization.getString("ok");
}
let themeId = 1;
function saveCustomTheme() {
// Get the current theme
const currentTheme = creator.theme;
// Generate a unique theme name
currentTheme.themeName += "_modified_" + themeId;
// Generate a human-friendly theme name
const themeTitle = "My Custom Theme " + themeId;
askForThemeName("Do you want to save the current theme configuration?", "Enter a theme title", { title: themeTitle }, (confirm, data) => {
if (confirm) {
addCustomTheme(currentTheme, data.title);
// Set the theme as a current theme; update the theme list and theme options
const themeBuilder = themeTabPlugin.model;
themeBuilder.setTheme(currentTheme);
themeId++;
updateCustomActions();
// ...
// (Optional) Save the theme to an external storage here
// ...
}
});
};
function deleteCurrentCustomTheme() {
const currentTheme = creator.theme;
const builtInThemeIndex = PredefinedThemes.indexOf(currentTheme.themeName!);
if (builtInThemeIndex === -1) { // A custom theme
const enLocale = editorLocalization.getLocale("en");
settings.confirmActionAsync("Do you want to delete the following theme: \"" + enLocale.theme.names[currentTheme.themeName!] + "\"?", (confirm) => {
if (confirm) {
themeTabPlugin.removeTheme(currentTheme);
const themeBuilder = themeTabPlugin.model;
themeBuilder.setTheme({ themeName: "default" });
updateCustomActions();
// ...
// (Optional) Delete the theme from an external storage here
// ...
}
});
}
};
// Register custom actions to save and delete a current theme modification
const saveThemeAction = new Action({
id: "svd-save-custom-theme",
title: "Add custom theme to the list",
action: saveCustomTheme,
iconName: "icon-saveas",
showTitle: false
});
creator.toolbar.actions.push(saveThemeAction);
const deleteThemeAction = new Action({
id: "svd-delete-custom-theme",
title: "Delete theme",
action: deleteCurrentCustomTheme,
iconName: "icon-delete",
showTitle: false
});
creator.toolbar.actions.push(deleteThemeAction);
function updateCustomActions() {
const isThemeTab = creator.activeTab === "theme";
saveThemeAction.visible = isThemeTab;
const currentTheme = creator.theme;
const isCustomTheme = PredefinedThemes.indexOf(currentTheme.themeName!) === -1;
deleteThemeAction.visible = isThemeTab && isCustomTheme;
}
// Update the Save and Delete action visibility when a user selects a theme or activates another tab
updateCustomActions();
themeTabPlugin.onThemeSelected.add(updateCustomActions);
creator.onActiveTabChanged.add(updateCustomActions);
// Initialize a survey JSON
creator.JSON = formJSON;
// Activate the Themes Tab
creator.activeTab = "theme";
this.model = creator;
}
}
Regarding the changes we made in our library: with the next release, the survey.isCompact
option will be made public.
T17030 - Add Reusable Custom Themes https://surveyjs.answerdesk.io/internal/ticket/details/T17030
The code of the Add Reusable Custom Themes Demo (Angular) contains TypeScript compilation errors.
creator-angular-demo.zip