이 샘플은 templatesConfig 옵션을 사용하여 SpreadJS 디자이너 컴포넌트의 템플릿 갤러리를 구성하는 방법을 보여 줍니다.
디자이너 컴포넌트 구성에서 templatesConfig 속성을 설정하면 템플릿 구성 JSON 파일을 가리키는 URL을 지정할 수 있습니다. 디자이너 컴포넌트는 초기화 중과 사용자가 "새로 만들기"(Reset) 작업을 수행할 때 기본 템플릿(목록의 첫 번째 템플릿)을 로드합니다. 썸네일이 있는 여러 템플릿은 파일 메뉴의 "새로 만들기" 탭에 표시되며, 사용자는 미리 정의된 템플릿에서 통합 문서를 빠르게 만들 수 있습니다.
구성 파일에는 다음 구조의 ITemplateConfig 개체 배열이 포함됩니다.
name: 템플릿 표시 이름입니다.
data(선택 사항): string URL(디자이너 컴포넌트가 가져온 후 확장자명으로 형식을 자동 감지) 또는 Object(미리 로드된 통합 문서 JSON으로 처리)입니다. 생략하면 빈 템플릿으로 간주됩니다.
thumbnail(선택 사항): 이미지 URL 또는 base64 문자열입니다. 생략하면 기본 빈 템플릿 썸네일이 사용됩니다.
지원되는 템플릿 형식에는 .ssjson, .sjs, .xlsx, .xltx, .xlsm, .xltm이 포함됩니다.
templatesConfig.json 예제:
기본 템플릿은 디자이너 컴포넌트가 생성된 후 비동기적으로 로드되므로, new Designer() 직후 수행한 통합 문서 작업은 템플릿 로드가 완료될 때 덮어써질 수 있습니다. 통합 문서에서 작업하기 전에 템플릿이 완전히 적용되었는지 확인하려면 designer.waitForDefaultTemplateLoaded() 메서드를 사용하세요.
const resources = {
tips: 'Please click the "File" button in the upper-left corner to access the File menu, then select the "New" tab to view templates gallery.',
}
window.onload = async function () {
let designer = new GC.Spread.Sheets.Designer.Designer("dss", { templatesConfig: '$DEMOROOT$/spread/source/data/templates.json' });
await designer.waitForDefaultTemplateLoaded();
let spread = designer.getWorkbook();
spread.getActiveSheet().setValue(1, 1, resources.tips);
}
<!doctype html>
<html style="height:100%;font-size:14px;">
<head>
<meta charset="utf-8" />
<meta name="spreadjs culture" content="ko-kr"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" type="text/css" href="$DEMOROOT$/ko/purejs/node_modules/@mescius/spread-sheets/styles/gc.spread.sheets.excel2013white.css">
<link rel="stylesheet" type="text/css" href="$DEMOROOT$/ko/purejs/node_modules/@mescius/spread-sheets-designer/styles/gc.spread.sheets.designer.light.min.css">
<script src="$DEMOROOT$/ko/purejs/node_modules/@mescius/spread-sheets/dist/gc.spread.sheets.all.min.js" type="text/javascript"></script>
<script src="$DEMOROOT$/ko/purejs/node_modules/@mescius/spread-sheets-shapes/dist/gc.spread.sheets.shapes.min.js" type="text/javascript"></script>
<script src="$DEMOROOT$/ko/purejs/node_modules/@mescius/spread-sheets-charts/dist/gc.spread.sheets.charts.min.js" type="text/javascript"></script>
<script src="$DEMOROOT$/ko/purejs/node_modules/@mescius/spread-sheets-print/dist/gc.spread.sheets.print.min.js" type="text/javascript"></script>
<script src="$DEMOROOT$/ko/purejs/node_modules/@mescius/spread-sheets-barcode/dist/gc.spread.sheets.barcode.min.js" type="text/javascript"></script>
<script src="$DEMOROOT$/ko/purejs/node_modules/@mescius/spread-sheets-pdf/dist/gc.spread.sheets.pdf.min.js" type="text/javascript"></script>
<script src="$DEMOROOT$/ko/purejs/node_modules/@mescius/spread-sheets-pivot-addon/dist/gc.spread.pivot.pivottables.min.js" type="text/javascript"></script>
<script src="$DEMOROOT$/ko/purejs/node_modules/@mescius/spread-sheets-slicers/dist/gc.spread.sheets.slicers.min.js" type="text/javascript"></script>
<script src="$DEMOROOT$/ko/purejs/node_modules/@mescius/spread-sheets-tablesheet/dist/gc.spread.sheets.tablesheet.min.js" type="text/javascript"></script>
<script src="$DEMOROOT$/ko/purejs/node_modules/@mescius/spread-sheets-formula-panel/dist/gc.spread.sheets.formulapanel.min.js" type="text/javascript"></script>
<script src="$DEMOROOT$/ko/purejs/node_modules/@mescius/spread-sheets-io/dist/gc.spread.sheets.io.min.js" type="text/javascript"></script>
<script src="$DEMOROOT$/ko/purejs/node_modules/@mescius/spread-sheets-designer-resources-ko/dist/gc.spread.sheets.designer.resource.ko.min.js" type="text/javascript"></script>
<script src="$DEMOROOT$/ko/purejs/node_modules/@mescius/spread-sheets-designer/dist/gc.spread.sheets.designer.all.min.js" type="text/javascript"></script>
<script src="$DEMOROOT$/ko/purejs/node_modules/@mescius/spread-sheets-resources-ko/dist/gc.spread.sheets.resources.ko.min.js" type="text/javascript"></script>
<script src="$DEMOROOT$/spread/source/js/license.js" type="text/javascript"></script>
<script src="$DEMOROOT$/spread/source/js/designer/license.js" type="text/javascript"></script>
<script src="app.js" type="text/javascript"></script>
<link href="./styles.css" rel="stylesheet" type="text/css" />
</head>
<body style="margin:0;padding:0">
<div id="dss" style="width:100vw;border:1px solid darkgray"></div>
</body>
</html>
body {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
#dss {
height: 100%;
}
function FileTemplateSelector() {
GC.Spread.Sheets.Designer.AtomicComponentBase.call(this, ...arguments);
this.selectedTemplate = null;
};
FileTemplateSelector.prototype = new GC.Spread.Sheets.Designer.AtomicComponentBase();
FileTemplateSelector.prototype.getTemplate = function () {
return `
<div class="template-selector">
<div class="templates-grid">
</div>
</div>`;
}
FileTemplateSelector.prototype._generateTemplateItem = function (template) {
let div = document.createElement("div");
div.setAttribute("key", template.id);
div.className = "template-card";
div.innerHTML = `
<div class="template-preview">
<div class="template-image-placeholder">
<div class="preview-content">
<div class="simple-preview" style="background: url(${template.image}) no-repeat center center; background-size: cover;">
<div class="preview-icon"></div>
</div>
</div>
</div>
</div>
<div class="template-info">
<h3 class="template-title">${template.title}</h3>
</div>
`;
return div;
}
FileTemplateSelector.prototype.handleTemplateClick = function (e) {
const templateCard = e.target.closest(".template-card");
if (templateCard) {
this.selectedTemplate = templateCard.getAttribute("key");
this.raiseValueChanged()
}
}
FileTemplateSelector.prototype.onMounted = function (host) {
host.querySelector(".templates-grid").addEventListener("click", this.handleTemplateClick.bind(this));
}
FileTemplateSelector.prototype.onRaiseValueChanged = function () {
this.onRaiseValueChanged();
}
FileTemplateSelector.prototype.onValueChanged = function (prevValue, nextValue, host) {
let templates = nextValue;
if (templates && Array.isArray(templates) && templates.length > 0) {
host.querySelector(".templates-grid").innerHTML = "";
templates.forEach(template => {
let templateItem = this._generateTemplateItem(template);
host.querySelector(".templates-grid").appendChild(templateItem);
})
}
}
FileTemplateSelector.prototype.updateValue = function (host) {
//return the select template;
return this.selectedTemplate;
}
FileTemplateSelector.prototype.onDestroy = function (host) {
host.querySelector(".templates-grid").removeEventListener("click", this.handleTemplateClick.bind(this));
}
// Register Custom Component to Designer
GC.Spread.Sheets.Designer.Designer.RegisterComponent("FileTemplateSelector", FileTemplateSelector);
var fileMenuTemplate = GC.Spread.Sheets.Designer.getTemplate(
GC.Spread.Sheets.Designer.TemplateNames.FileMenuPanelTemplate
);
addCustomItem(fileMenuTemplate);
GC.Spread.Sheets.Designer.registerTemplate(
GC.Spread.Sheets.Designer.TemplateNames.FileMenuPanelTemplate,
fileMenuTemplate
);
function addCustomItem(template) {
//add Template to the left menu list;
template.content[0].children[0].children[0].children[0].children[1].items.push({ text: "Template", value: "Template" });
//add Template page to the right container;
var listDisplayContainer = template.content[0].children[0].children[1];
listDisplayContainer.children.push({
type: "Container",
visibleWhen: "activeCategory_main=Template",
children: [
{
type: 'TextBlock',
margin: '50px 0 15px 50px',
style: 'font-size:36px;',
text: '템플릿'
},
{
type: "FileTemplateSelector",
bindingPath:"customTemplates"
}
],
attributes:[
{key: 'data-activeCategory_main', value: 'Template'}
]
});
}