2019년 3월 22일 금요일

API를 사용하여 Datasource를 생성하고 페이지 레이아웃 업데이트하기 [Part 2]

이전 포스트의 API를 사용하여 데이타소스(DS) 아이템을 만드는 방법에 이어서 이번에는 어떻게 API를 컴포넌트에 적용시키는지 알아보도록 하자. 필자는 아주 심플한 RichText Editor 컴포넌트를 만들었고, 컴포넌트 내에 API를 XMLHttpRequest를 통하여 Ajax Call을 실행하였다.

페이지 아이템의 xEditor에서 API를 이용하여 DS를 생성할시 아이템은 아래의 스크린샷처럼 하위경로의 DS폴더안에 생성된다.


해당 DS를 다른 페이지에서 재사용 할 경우 페이지 구조상으로 문제가 될수 있지만, 필자는 API를 컴포넌트에서 쉽게 사용하는 방법의 목적의 예제이므로 컨턴츠 구조 문제는 다루지 않겠다. 아래는 Controller Rendering의 RichText Editor 컴포넌트이다.

CustomComponentController.cs (Controller)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
using Sitecore.Mvc.Controllers;
using Sitecore.Mvc.Presentation;
using System;
using System.Web.Mvc;
using Sitecore.Data;

namespace Sitecore.Custom.Component.RichTextEditor
{
    public class CustomComponentController : SitecoreController
    {
        /// <summary>
        /// RichText Editor의 Action Method
        /// </summary>
        /// <returns>ActionResult</returns>
        public ActionResult RichTextEditor()
        {
            Models.RichTextEditor rte = new Models.RichTextEditor();
            rte.PageItem = PageContext.Current.Item;
            rte.Rendering = RenderingContext.CurrentOrNull.Rendering;
            rte.RenderingDatasource = rte.Rendering.DataSource;

            // 레이아웃에 적용되어진 RTE 컨트롤에 데이타소스가 적용되었는지 확인한다.
            rte.IsDatasourceSet = (!String.IsNullOrEmpty(rte.RenderingDatasource) ? true : false);

            // 새로운 데이타소스 아이템의 이름을 선업한다.
            rte.NewItemName = rte.PageItem.Name + "_" + rte.DatasourceItemSuffix;

            // RTE DS의 템플릿을 선언한다.
            rte.RteTemplate = rte.PageItem.Database.GetTemplate(new ID("{0B57D07C-F406-4700-9CAC-D4C4B84D1B78}"));

            return PartialView(rte);
        }
    }
}

RichTextEditor.cs (Model)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
using Sitecore.Data.Items;
using Sitecore.Mvc.Presentation;

namespace Sitecore.Custom.Component.Models
{
    public class RichTextEditor
    {
        // Initialize component's rendering info
        public Item Item { get; set; }
        public Item ResourceFolder { get; set; }
        public Rendering Rendering { get; set; }
        public TemplateItem RteTemplate { get; set; }
        public string NewItemName { get; set; }
        public string DatasourceItemSuffix { get { return "RTE"; } }
        public string RenderingDatasource { get; set; }
        public Item PageItem { get; set; }
        public bool IsDatasourceSet { get; set; }
    }
}

RichTextEditor.cshtml (Views)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
@model Sitecore.Custom.Component.Models.RichTextEditor
@if (!Model.IsDatasourceSet && Sitecore.Context.PageMode.IsExperienceEditor)
{
    <div style="padding:20px 0;" class="border border-success">
        <h4>RichText Editor Added</h4>
        <button type="button" class="btn btn-success" onclick="SendAjaxPOST(); return false;">Create Rich Text Editor Datasource</button>
        <script>
            function SendAjaxPOST() {
                // 현재 페이지에서 다른 아이템 및 필드가 수정되었는지 확인한다.
                if (Sitecore.PageModes.PageEditor.isModified()) {
                    alert("There are unsaved items on this page.\rPlease save the page, then create a new datasource.");
                    return false;
                }

                // XHR 시작
                var xhr = new XMLHttpRequest();
                xhr.open("POST", "http://sc910.sc/customapi/createitem/@Model.PageItem.ID.Guid.ToString()");
                xhr.setRequestHeader("Content-Type", "application/json");
                xhr.send("{\"itemName\": \"@Model.NewItemName\", \"templateGuid\": \"@Model.RteTemplate.ID.Guid.ToString()\", \"isDatasourceItem\": \"1\", \"renderingUid\": \"@Model.Rendering.UniqueId.ToString()\"}");
                xhr.onreadystatechange = function () {
                    if (this.readyState == 4) {
                        if (this.status === 200) {
                            window.onbeforeunload = null;
                            this.returnValue = true;

                            setTimeout(function () { location.reload() }, 500);
                        } else {
                            console.log('Error Status: ' + this.status + '\nHeaders: ' + JSON.stringify(this.getAllResponseHeaders()) + '\nBody: ' + this.responseText);
                        }
                    }
                };
            }
        </script>
    </div>
}
else
{
    <div>@Html.Sitecore().Field("Content")</div>
}

해당 컴포넌트를 사이트코어 페이지에 적용하고 실행하면 ContentEditor 와 xEditor의 페이지 이동 및 확인없이 쉽게 데이타소스를 생성할수있다. 이는 Non-Technical 유저 입장에서 쉽게 페이지를 생성하고 데이터소스를 다이나믹하게 생성하는데 도움이된다.