시각적 컨텐츠 조각 - 템플릿 visual-content-fragments-templates
- 적용 대상:
- Experience Manager as a Cloud Service
Adobe Experience Manager(AEM) as a Cloud Service에서 HTML 템플릿을 사용하여 콘텐츠 조각을 시각화하고 HTML 형식으로 전달할 수 있습니다.
시각적 콘텐츠 조각 및 시각적 콘텐츠 조각에 대한 조각 작업은 현재 제한된 가용성입니다.
HTML 템플릿을 사용하면 콘텐츠 조각이 표시되는 방식을 제어할 수 있습니다. 선택한 코드 편집기에서 HTML 템플릿을 만든 다음 업로드하고 AEM의 콘텐츠 조각 모델에 할당할 수 있습니다. Handlebars.js를 사용하는 콘텐츠 자리 표시자를 사용하면 콘텐츠 조각 모델의 데이터 유형에 템플릿을 매핑할 수 있습니다. 모델에 할당되면 모델을 기반으로 하는 모든 콘텐츠 조각에서 템플릿을 사용하여 조각을 시각화하거나 웹, 이메일, 모바일 애플리케이션 등과 같은 모든 채널에 HTML 형식의 모듈식 환경으로 전달할 수 있습니다.
이 문서에서는 시각적 컨텐츠 조각을 렌더링하기 위해 Handlebars 구문을 사용하여 사용자 지정 HTML 템플릿을 만드는 방법에 대해 설명합니다.
템플릿을 만든 후 다음을 수행할 수 있습니다.
학습 내용 what-you-will-learn
다음에 대한 (매우 빠른) 소개를 제공하면:
- AEM에서 템플릿을 사용하는 방법
- 게시 URL 사용
이 페이지에서는 다음 항목을 다룹니다(자세히 알아보기).
- Handlebars - 구문에 필요한 기본 사항
- 콘텐츠 조각 데이터에 액세스하는 방법
- 중첩된 콘텐츠 조각을 사용하여 작업
- 여러 값 필드 처리
- 루프 및 조건부 논리 만들기
- 콘텐츠 조각을 위한 템플릿 디자인 모범 사례
사전 요구 사항 prerequisites
여기에서 다루는 기술을 이해하고 사용하려면 다음을 수행해야 합니다.
- HTML에 대한 기본 이해
- AEM 콘텐츠 조각 및 콘텐츠 조각 모델에 대한 친숙도
- 콘텐츠 조각 모델 이해
컨텐츠 조각 HTML 템플릿 사용 using-a-content-fragment-html-template
AEM에서 컨텐츠 조각 HTML 템플릿 사용 using-a-content-fragment-html-template-in-aem
AEM에서 템플릿을 사용하는 방법에 대한 자세한 내용은 다음을 참조하십시오.
시각적 콘텐츠 조각 게시 URL 사용 using-the-visual-content-fragment-publish-url
템플릿을 사용하여 시각적 콘텐츠 조각을 만든 후에는 시각적 콘텐츠 조각의 게시 URL을 사용할 수 있습니다.
Handlebars - (매우) 기본 사항 handlebars-the-very-basics
Handlebars는 이중 중괄호(대괄호) {{ }}를 사용하여 동적 콘텐츠를 HTML에 삽입하는 간단한 템플릿 언어입니다.
기본 구문 basic-syntax
기본 Handlebars 구문의 예는 다음과 같습니다.
<!-- Output a variable (HTML-escaped) -->
{{snippet-not-found:variableName}}
<!-- Output raw HTML (unescaped) -->
{{{htmlContent}}}
<!-- Comment (not rendered) -->
{{! This is a comment }}
주요 개념 key-concepts
Handlebars의 주요 개념:
{{ }}
HTML 특수 문자를 이스케이프 처리합니다.
메타데이터, 레이블, 부울
{{{ }}}
원시 HTML(이스케이프 처리되지 않음)를 출력합니다.
리치 텍스트 및 에셋 출력
{{! }}
Handlebars 전용 주석
템플릿 설명서
값이 HTML에 미리 렌더링되어 있으므로 필드 값에 삼중 중괄호({{{ }}})를 사용하십시오.
템플릿 컨텍스트 참조 template-context-reference
템플릿이 렌더링되면 콘텐츠 조각에 대한 모든 데이터가 포함된 컨텍스트 개체를 수신합니다. 다음이 포함됩니다.
-
선택한 조각
-
선택한 조각에서 참조된 모든 추가 조각
| note |
| NOTE |
| 조각을 참조할 수 있습니다. |
- UI에서: 최대 깊이 5까지
- api 사용 시: 최대 깊이 10까지 깊이를 구성할 수 있습니다.
|
콘텐츠 조각 content-fragment
(선택한) 콘텐츠 조각에 대한 컨텍스트 오브젝트 구조:
fields
맵
이름별 필드 값에 직접 액세스
allFields
목록
반복을 위한 {name, value} 배열
hasFields
부울
조각에 필드가 있는 경우 true
속성 구조 properties-structure
properties 개체의 구조는 선택한 조각과 참조된 각 조각에 대해 동일합니다.
title
문자열
조각 제목
유타 남부 자전거 경기
description
문자열
조각 설명
모험…
path
문자열
조각에 대한 JCR 경로
/content/dam/...
hasDescription
부울
설명이 비어 있지 않으면 참
true
createdDate
문자열
ISO-8601 생성일
modifiedDate
문자열
ISO-8601 수정 날짜
publishedDate
문자열
ISO-8601 게시 날짜
status
문자열
게시 계층의 복제 상태
DRAFT
model
맵
포함: id, path, name, technicalName, description
validationStatus
목록
{property, message}과(와) 같은 항목
previewReplicationStatus
문자열
미리보기 계층에 대한 복제 상태
tags
목록
조각 수준 태그. 각 항목: id, title, titlePath, name, path, description
fieldTags
목록
필드 수준 태그. tags과(와) 같은 구조입니다.
예: 템플릿 액세스
(선택한) 콘텐츠 조각의 경우:
{{properties.title}}, {{properties.description}}, {{{fields.field_name}}}
참조된 콘텐츠 조각 referenced-content-fragments
참조된 조각에 대한 컨텍스트 오브젝트 구조:
hasReferencedFragments
부울
참조가 있을 때 true
referencedFragments
목록
참조된 조각 개체 배열
referencesError
부울
참조를 로드할 때 오류가 발생한 경우 true
referencesErrorMessage
문자열
referencesError이(가) true일 때 오류 메시지
참조된 조각 구조 referenced-fragment-structure
referencedFragments의 각 항목에는 다음이 포함됩니다.
anchorId
문자열
HTML 안전 앵커 ID(조각 수준이며 콘텐츠 조각 속성이 아님)
properties
맵
조각 메타데이터(위와 동일한 구조)
hasFields
부울
조각에 필드가 있으면 참
fields
맵
이 조각 내의 필드에 직접 액세스
allFields
목록
반복을 위한 {name, value} 배열
예: 처음 참조된 콘텐츠 조각(0으로 인덱싱된 목록의 첫 번째 항목)에 대한 템플릿 액세스:
{{referencedFragments.[0].anchorId}}, {{referencedFragments.[0].properties.title}}, {{referencedFragments.[0].properties.description}}
또는 필드 맵에서 다음을 수행합니다.
{{{ fields.referenced_cf_field_name.properties.description }}}
기본 필드 액세스 basic-field-access
필요한 경우 모든 필드를 반복할 수 있으므로 직접 필드 액세스가 권장됩니다.
직접 필드 액세스(권장) direct-field-access-recommended
필드 맵을 사용하여 이름으로 직접 필드에 액세스합니다.
<!DOCTYPE html>
<html>
<head>
<title>{{properties.title}}</title>
</head>
<body>
<article>
<h1>{{{fields.title}}}</h1>
<p class="subtitle">{{{fields.subtitle}}}</p>
<div class="content">
{{{fields.description}}}
</div>
<div class="image">
{{{fields.primaryImage}}}
</div>
</article>
</body>
</html>
기억하십시오.
- 사전 렌더링된 HTML(서식 있는 텍스트)가 포함된 경우 필드 값에 삼중 중괄호
{{{ }}}을(를) 사용합니다.
- 필드 이름(제목, 자막, 설명, primaryImage) 은(는) 콘텐츠 조각 모델정확히과(와) 일치해야 합니다.
- 누락된 필드는 렌더링되지 않습니다. 오류가 발생하지 않으며 Handlebars 구문이 렌더링된 HTML 조각에 표시(및 표시)됩니다.
모든 필드 반복 iterate-through-all-fields
필드 이름을 미리 알 수 없는 경우 allFields을(를) 사용합니다.
<table>
<thead>
<tr>
<th>Field Name</th>
<th>Field Value</th>
</tr>
</thead>
<tbody>
{{#each allFields}}
<tr>
<td>{{name}}</td>
<td>{{{value}}}</td>
</tr>
{{/each}}
</tbody>
</table>
기억하십시오.
{{name}}이(가) 이중 중괄호(일반 텍스트 레이블)를 사용합니다.
{{{value}}}에서 트리플 중괄호(사전 렌더링된 HTML 값)를 사용합니다.
중첩된 콘텐츠 조각 nested-content-fragments
콘텐츠 조각 필드가 다른 콘텐츠 조각을 참조하는 경우 점 표기법을 사용하여 참조된 조각의 필드에 직접 액세스할 수 있습니다.
단일 수준 중첩 single-level-nesting
단일 수준 중첩의 예:
<article>
<h1>{{{fields.title}}}</h1>
<!-- Access author (a referenced Content Fragment) -->
<div class="author-info">
<h3>Author</h3>
<p>Name: {{{fields.author.name}}}</p>
<p>Email: {{{fields.author.email}}}</p>
<p>Bio: {{{fields.author.bio}}}</p>
</div>
<div class="content">
{{{fields.content}}}
</div>
</article>
패턴: fields.referenceFieldName.nestedFieldName
다중 레벨 중첩 multi-level-nesting
시스템은 무제한 중첩 깊이를 지원합니다.
<article>
<h1>{{{fields.title}}}</h1>
<div class="author-details">
<!-- Level 1: Author -->
<p>Author: {{{fields.author.name}}}</p>
<!-- Level 2: Author's Organization -->
<p>Organization: {{{fields.author.organization.name}}}</p>
<p>Website: {{{fields.author.organization.website}}}</p>
<!-- Level 3: Organization's Address -->
<p>Located in: {{{fields.author.organization.address.city}}},
{{{fields.author.organization.address.country}}}</p>
</div>
<div class="content">
{{{fields.content}}}
</div>
</article>
패턴: fields.level1.level2.level3.fieldName(제한된 깊이; 기본값은 5이며, API를 사용할 경우 10으로 확장할 수 있음)
API 매개 변수 요구 사항: 하이드레이션 api-parameter-requirements
중첩된 콘텐츠 조각 액세스를 활성화하려면 API 호출에 hydration 쿼리 매개 변수를 포함해야 합니다.
하이드레이션을 사용하려면:
# Enable hydration with depth=2 for 2 levels of nesting
GET /adobe/sites/cf/fragments/{id}/preview?hydration=%7B%22enabled%22%3Atrue%2C%22maxDepth%22%3A2%7D
다중 값 필드 multi-valued-fields
여러 유형의 여러 값 필드가 있습니다.
다중 값 텍스트 필드 multi-valued-text-fields
다중 값을 지정하면 텍스트, number, 날짜 및 기타 단순 필드가 배열이 됩니다.
<article>
<h1>{{{fields.title}}}</h1>
<!-- Access individual items by index (use dot before bracket) -->
<div class="tags">
<span class="tag">{{{fields.tags.[0]}}}</span>
<span class="tag">{{{fields.tags.[1]}}}</span>
</div>
<!-- Better: Iterate through all tags -->
<div class="tags">
{{#each fields.tags}}
<span class="tag">{{{this}}}</span>
{{/each}}
</div>
</article>
Handlebars에서 색인별로 배열 항목에 액세스할 때는 다음을 잊지 마십시오.
다중 값 숫자 필드 multi-valued-number-fields
숫자를 렌더링하기 위해 문자열(으)로 변환됨:
<div class="pricing">
<h3>Available Prices:</h3>
{{#each fields.prices}}
<span class="price">${{{this}}}</span>
{{/each}}
</div>
다중 값 콘텐츠 조각 참조 multi-valued-content-fragment-references
필드가 여러 콘텐츠 조각을 참조하는 경우:
<div class="authors">
<h3>Authors:</h3>
{{#each fields.authors}}
<div class="author">
<h4>{{{this.name}}}</h4>
<p>Email: {{{this.email}}}</p>
{{#if this.bio}}
<p class="bio">{{{this.bio}}}</p>
{{/if}}
</div>
{{/each}}
</div>
여러 값 자산 참조 multi-valued-asset-references
에셋(예: 이미지 및 문서)인 콘텐츠 형식에 대해 구성된 콘텐츠 참조 필드가 HTML으로 미리 렌더링됩니다. 다중 값 자산이 배열이 됨:
<!-- Single asset -->
<div class="hero-image">
{{{fields.heroImage}}}
</div>
<!-- Multi-valued: iterate through all images -->
<div class="gallery">
{{#each fields.gallery}}
<div class="image">{{{this}}}</div>
{{/each}}
</div>
중첩된 다중 값 참조 nested-multi-valued-references
다중 값 참조는 어떤 깊이에서든 다중 값 참조를 포함할 수 있습니다.
{{#each fields.chapters}}
<div class="chapter">
<h3>Chapter: {{{this.title}}}</h3>
{{#each this.authors}}
<p>Author: {{{this.name}}}</p>
{{#each this.publications}}
<p>Publication: {{{this.title}}}</p>
{{/each}}
{{/each}}
</div>
{{/each}}
루프 및 반복 loops-and-iteration
Handlebars는 배열 및 개체를 반복하는 데 {{#each}} 도우미를 제공합니다.
배열 반복 iterating-over-arrays
배열에 대한 반복의 예:
<!-- Simple array iteration -->
{{#each fields.tags}}
<span class="tag">{{{this}}}</span>
{{/each}}
<!-- Array of objects -->
{{#each fields.authors}}
<div class="author">
<h4>{{{this.name}}}</h4>
<p>{{{this.email}}}</p>
</div>
{{/each}}
<!-- With empty-state fallback -->
{{#each fields.tags}}
<span class="tag">{{{this}}}</span>
{{snippet-not-found:else}}
<p>No tags available.</p>
{{/each}}
루프의 특수 변수 special-variables-in-loops
{{#each}}개 블록 내에서 Handlebars는 특수 변수를 제공합니다.
{{#each fields.items}}
<div class="item">
<p>Index: {{@index}}</p> <!-- 0-based index -->
<p>Number: {{@number}}</p> <!-- 1-based index -->
<p>First: {{@first}}</p> <!-- true for first item -->
<p>Last: {{@last}}</p> <!-- true for last item -->
<p>Value: {{{this}}}</p> <!-- current item -->
</div>
{{/each}}
<!-- Example: numbered steps with first/last CSS classes -->
<ul>
{{#each fields.steps}}
<li class="{{#if @first}}first{{/if}} {{#if @last}}last{{/if}}">
Step {{@number}}: {{{this}}}
</li>
{{/each}}
</ul>
참조된 조각 반복 iterating-over-referenced-fragments
참조된 조각을 반복하는 예:
{{#if hasReferencedFragments}}
<section class="references">
<h2>Related Content</h2>
{{#each referencedFragments}}
<article id="{{anchorId}}">
<h3>{{title}}</h3>
{{#if hasDescription}}
<p>{{description}}</p>
{{/if}}
{{#if hasFields}}
<ul>
{{#each allFields}}
<li><strong>{{name}}:</strong> {{{value}}}</li>
{{/each}}
</ul>
{{/if}}
</article>
{{/each}}
</section>
{{/if}}
중첩 루프 nested-loops
중첩 루프의 예:
{{#each fields.categories}}
<section class="category">
<h2>{{{this.name}}}</h2>
{{#each this.products}}
<article class="product">
<h3>{{{this.name}}}</h3>
<p>{{{this.description}}}</p>
</article>
{{/each}}
</section>
{{/each}}
조건부 렌더링 conditional-rendering
데이터 가용성을 기반으로 콘텐츠를 표시하거나 숨기려면 조건을 사용하십시오.
기본 If/Else basic-if-else
기본 if-else 구문의 예는 다음과 같습니다.
{{#if hasMainDescription}}
<p class="description">{{properties.description}}</p>
{{snippet-not-found:else}}
<p class="no-description">No description available.</p>
{{/if}}
<!-- Check field existence before rendering -->
{{#if fields.author}}
<div class="author">
<p>By {{{fields.author.name}}}</p>
</div>
{{/if}}
{{#if fields.publishDate}}
<time>{{{fields.publishDate}}}</time>
{{/if}}
Unless(음수 조건부) unless-negative-conditional
unless 도우미:
<!-- Show author unless explicitly hidden -->
{{#unless fields.hideAuthor}}
<div class="author">{{{fields.author.name}}}</div>
{{/unless}}
중첩된 조건 nested-conditials
중첩된 조건의 예:
{{#if fields.author}}
<div class="author">
<h3>{{{fields.author.name}}}</h3>
{{#if fields.author.bio}}
<p class="bio">{{{fields.author.bio}}}</p>
{{/if}}
{{#if fields.author.website}}
<a href="{{{fields.author.website}}}">Visit Website</a>
{{/if}}
</div>
{{/if}}
기본 제공 Handlebars 도우미 built-in-handlebars-helpers
Handlebars에는 {{#if}} 및 {{#each}} 이상의 기본 제공 도우미가 포함되어 있습니다.
{{#if condition}}
조건이 truthy인 경우 콘텐츠를 렌더링합니다. 잘못된 값: false, undefined, null, 0, "", []
{{#unless condition}}
조건이 falsy인 경우 콘텐츠를 렌더링합니다(#if의 역).
{{#each array}}
각 항목에 대해 콘텐츠를 반복합니다. 빈 배열에 대해 {{else}}을(를) 지원합니다.
{{#with object}}
중첩된 오브젝트에 대한 새 범위를 만들어 경로 반복을 줄입니다
{{lookup this "key"}}
이름으로 속성을 동적으로 조회
도우미 사용 with-helper
중첩된 오브젝트에 대한 새 범위를 만들어 반복적인 경로 접두사를 줄입니다.
{{#with fields.author}}
<div class="author">
<h3>{{{name}}}</h3> <!-- same as fields.author.name -->
<p>{{{email}}}</p> <!-- same as fields.author.email -->
<p>{{{bio}}}</p> <!-- same as fields.author.bio -->
</div>
{{/with}}
<!-- Useful for deeply nested objects -->
{{#with fields.author.organization}}
<div class="organization">
<h4>{{{name}}}</h4>
<p>{{{website}}}</p>
{{#with address}}
<address>
{{{street}}}<br/>
{{{city}}}, {{{country}}}
</address>
{{/with}}
</div>
{{/with}}
고급 패턴 advanced-patterns
다음과 같은 고급 패턴의 몇 가지 예가 있습니다.
중첩 루프의 상위 컨텍스트 액세스 accessing-parent-context-in-nested-loops
../을(를) 사용하여 중첩 루프 내에서 상위 범위에 액세스합니다.
<h1>{{{fields.title}}}</h1>
{{#each fields.chapters}}
<section class="chapter">
<h2>Chapter {{@number}}: {{{this.title}}}</h2>
{{#each this.sections}}
<article>
<!-- Access parent chapter via ../ -->
<p>Chapter: {{{../title}}}</p>
<!-- Access root context via ../../ -->
<p>Book: {{{../../fields.title}}}</p>
<h3>{{{this.title}}}</h3>
<div>{{{this.content}}}</div>
</article>
{{/each}}
</section>
{{/each}}
동적 CSS 클래스 dynamic-css-classes
동적 CSS 클래스의 예:
<article class="content-fragment {{#if hasMainDescription}}with-description{{/if}} {{#if hasReferencedFragments}}has-refs{{/if}}">
<h1>{{properties.title}}</h1>
</article>
<ul class="tag-list">
{{#each fields.tags}}
<li class="tag {{#if @first}}first{{/if}} {{#if @last}}last{{/if}}">
{{{this}}}
</li>
{{/each}}
</ul>
전체 예 complete-examples
몇 가지 완전한 예가 참고용으로 제공됩니다.
작성자가 있는 블로그 게시물
작성자 세부 정보가 포함된 블로그 게시물:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{{properties.title}}</title>
<style>
body { font-family: Arial, sans-serif; margin: 40px; }
.author-card { background: #f5f5f5; padding: 20px; border-radius: 8px; }
.tags { display: flex; gap: 10px; }
.tag { background: #007bff; color: white; padding: 5px 10px; border-radius: 4px; }
</style>
</head>
<body>
<article>
<header>
<h1>{{{fields.title}}}</h1>
{{#if fields.publishDate}}
<time datetime="{{{fields.publishDate}}}">{{{fields.publishDate}}}</time>
{{/if}}
{{#if fields.tags}}
<div class="tags">
{{#each fields.tags}}
<span class="tag">{{{this}}}</span>
{{/each}}
</div>
{{/if}}
</header>
{{#if fields.heroImage}}
<figure>
{{{fields.heroImage}}}
{{#if fields.imageCaption}}
<figcaption>{{{fields.imageCaption}}}</figcaption>
{{/if}}
</figure>
{{/if}}
<div class="content">
{{{fields.content}}}
</div>
{{#if fields.author}}
<aside class="author-card">
<h3>About the Author</h3>
<h4>{{{fields.author.name}}}</h4>
{{#if fields.author.profilePicture}}
<div class="author-image">{{{fields.author.profilePicture}}}</div>
{{/if}}
{{#if fields.author.bio}}
<p>{{{fields.author.bio}}}</p>
{{/if}}
{{#if fields.author.email}}
<p>Contact: <a href="mailto:{{{fields.author.email}}}">{{{fields.author.email}}}</a></p>
{{/if}}
</aside>
{{/if}}
</article>
</body>
</html>
필수 API 호출:
GET /adobe/sites/cf/fragments/{id}/preview?hydration=%7B%22enabled%22%3Atrue%2C%22maxDepth%22%3A1%7D
일반 테이블 보기(필드에 대한 사전 지식 없음) generic-table-view-no-prior-knowledge-of-fields
필드에 대한 고유 지식이 없는 일반 테이블 보기입니다. 은(는) 일반 템플릿과(와) 유사합니다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{{properties.title}}</title>
<style>
body { font-family: Arial, sans-serif; margin: 40px; }
table { width: 100%; border-collapse: collapse; margin: 20px 0; }
th, td { border: 1px solid #ddd; padding: 12px; text-align: left; }
th { background-color: #f4f4f4; font-weight: bold; }
.ref-section { background: #f9f9f9; padding: 20px; margin: 20px 0; border-radius: 8px; }
</style>
</head>
<body>
<header>
<h1>{{properties.title}}</h1>
{{#if properties.description}}<p>{{properties.description}}</p>{{/if}}
<p><small>Path: {{properties.path}}</small></p>
</header>
{{#if hasFields}}
<section>
<h2>Fields</h2>
<table>
<thead>
<tr><th>Field Name</th><th>Field Value</th></tr>
</thead>
<tbody>
{{#each allFields}}
<tr>
<td><strong>{{name}}</strong></td>
<td>{{{value}}}</td>
</tr>
{{/each}}
</tbody>
</table>
</section>
{{/if}}
{{#if hasReferencedFragments}}
<section class="ref-section">
<h2>Referenced Content Fragments</h2>
{{#each referencedFragments}}
<article id="{{anchorId}}" style="margin-bottom: 30px;">
<h3>{{title}}</h3>
{{#if hasDescription}}<p>{{description}}</p>{{/if}}
<p><small>Path: {{path}}</small></p>
{{#if hasFields}}
<table>
<thead>
<tr><th>Field Name</th><th>Field Value</th></tr>
</thead>
<tbody>
{{#each allFields}}
<tr>
<td><strong>{{name}}</strong></td>
<td>{{{value}}}</td>
</tr>
{{/each}}
</tbody>
</table>
{{/if}}
</article>
{{/each}}
</section>
{{/if}}
</body>
</html>
모범 사례 best-practices
모범 사례는 다음과 같습니다.
-
HTML 마크업 콘텐츠가 포함된 필드 값에는 항상 3중 중괄호를 사용하십시오.
-
필드 값은 사전 렌더링된 HTML입니다.
| note |
| NOTE |
| 이중 중괄호는 원시 HTML 태그를 일반 텍스트로 표시합니다. |
| code language-handlebars |
<!-- CORRECT -->
{{{fields.description}}}
<!-- WRONG - displays HTML tags as text -->
{{fields.description}}
|
-
중첩된 필드에 액세스하기 전에 존재 여부를 확인합니다.
| code language-handlebars |
<!-- GOOD: check before accessing nested fields -->
{{#if fields.author}}
<p>By {{{fields.author.name}}}</p>
{{/if}}
<!-- RISKY: may render empty if author is not set -->
<p>By {{{fields.author.name}}}</p>
|
-
가능하면 직접 필드 액세스를 사용하십시오.
allFields을(를) 반복하고 이름별로 일치시키는 것보다 더 읽기 쉽고 유지 관리할 수 있습니다.
-
섹션 주석을 사용하여 템플릿을 구성합니다.
| code language-handlebars |
{{! ===== HEADER SECTION ===== }}
<header>
<h1>{{properties.title}}</h1>
</header>
{{! ===== MAIN CONTENT ===== }}
<main>
{{#if hasFields}}
<!-- fields rendering -->
{{/if}}
</main>
{{! ===== REFERENCES ===== }}
{{#if hasReferencedFragments}}
<!-- references rendering -->
{{/if}}
|
-
폴백을 사용하여 누락된 데이터를 우아하게 처리합니다.
| code language-handlebars |
{{#if fields.title}}
<h1>{{{fields.title}}}</h1>
{{snippet-not-found:else}}
<h1>Untitled</h1>
{{/if}}
|
-
항상 적절한 HTML 문서 구조를 사용하십시오.
| code language-handlebars |
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{properties.title}}</title>
</head>
<body>
<!-- your content here -->
</body>
</html>
|
-
다양한 콘텐츠 시나리오로 테스트합니다.
- 모든 필드가 완전히 채워짐
- 선택적 필드 누락
- 비어 있는 다중 값 필드
- 딥 중첩(여러 수준)
- 로드에 실패한 참조
-
의미 체계 HTML 요소 사용:
- 액세스 가능성 개선을 위해
<article>, <header>, <main>, <footer>, <time>, <address> 또는 유사한 항목을 사용하십시오.
-
CSS에서 스타일을 유지합니다.
<style>개 태그 또는 외부 스타일시트를 사용하십시오.
- 가능하면 인라인 스타일을 사용하지 마십시오.
-
문서 복합 논리:
- Handlebars 주석
({{! }})을(를) 사용합니다.
- 렌더링된 출력에 표시되는 HTML 주석을 사용하지 마십시오.
문제 해결 troubleshooting
일부 문제 해결 힌트에는 다음이 포함됩니다.
필드에 HTML 태그가 텍스트로 표시됩니다.
문자 그대로 표시된 <p>Hello World</p>
트리플 중괄호 사용: {{{fields.description}}}
중첩된 콘텐츠 조각 필드가 비어 있거나 [개체 개체]를 표시합니다.
{{{fields.author.name}}}이(가) 비어 있음
API 호출에서 하이드레이션을 사용하도록 설정하고, 필드 이름 철자를 확인하고, maxDepth이(가) 충분히 깊은지 확인하십시오.
다중 값 필드에는 첫 번째 항목만 표시됩니다.
5개 항목이 있는 배열은 하나만 렌더링합니다.
{{#each fields.tags}}을(를) 사용하여 모든 항목 반복
배열 인덱스 액세스가 작동하지 않음
{{{fields.tags[0]}}} 렌더링이 비어 있음
점 대괄호 구문 사용: {{{fields.tags.[0]}}}
참조된 조각이 표시되지 않음
hasReferencedFragments은(는) 항상 false입니다.
하이드레이션 사용: ?hydration=%7B%22enabled%22%3Atrue%7D; 또한 {{#if referencesError}} 확인
템플릿이 렌더링되지 않음
빈 페이지 또는 빈 출력
닫히지 않은 {{#if}} 또는 {{#each}} 블록을 확인합니다. 진단 출력 추가: <pre>hasFields: {{hasFields}} | title: {{properties.title}}</pre>
렌더링된 페이지에 주석이 나타납니다
최종 사용자에게 표시되는 HTML 주석 텍스트
HTML <!-- comment --> 대신 Handlebars 주석 {{! comment }} 사용
조건부 은 항상 true로 평가됩니다.
{{#if fields.enabled}}은(는) 항상 신뢰할 수 있음
참고: "false" 문자열은 Handlebars에서 truthy입니다. 실제 false, null, undefined, 0, "" 및 []만 거짓 같습니다.
엔티티로 렌더링하는 특수 문자
<, & 대신 <, &이(가) 표시됨
사전 렌더링된 HTML 콘텐츠에 삼중 중괄호를 사용합니다. {{{fields.content}}}
내부 루프에서 외부 루프 변수에 액세스할 수 없습니다.
부모 #each의 변수가 정의되지 않았습니다.
상위 범위: {{{../name}}}에 대해 ../ 사용; 최상위 범위에 대해 ../../ 사용
빈 목록에 대체 메시지가 표시되지 않음
항목이 없는 다중 값 필드에 아무 것도 표시되지 않음
{{#each}} 내의 {{else}} 사용: {{#each fields.tags}}...{{else}}<p>No tags</p>{{/each}}
자산 작업 working-with-assets
컨텐츠 조각에서 참조된 Assets은 AEM에 의해 HTML으로 사전 렌더링됩니다. 따라서 모든 에셋 참조에는 삼중 중괄호가 필수입니다.
이미지
<img src="..." alt="...">
기억하십시오.
- 자산 필드에는 항상 3중 중괄호를 사용하십시오.
이중 중괄호를 사용하면 이미지, 비디오 또는 링크를 렌더링하는 대신 생성된 HTML 태그가 이스케이프되고 원시 텍스트로 표시됩니다.
에셋 필드 사용 asset-field-usage
에셋 필드 사용의 예:
<!-- CORRECT - triple braces render the image -->
{{{fields.heroImage}}}
<!-- Output: <img src="path/to/image.jpg" alt="Hero"> -->
<!-- WRONG - double braces escape the tag, showing it as text -->
{{fields.heroImage}}
<!-- Output: <img src="path/to/image.jpg" alt="Hero"> -->
사용자 지정 템플릿 도우미 customer-template-helpers
시스템에서는 사용자 지정 HTML 속성을 사용하여 HTML 요소를 생성하는 사용자 지정 Handlebars 도우미를 제공합니다. 이러한 도우미를 통해 사전 렌더링된 콘텐츠에서 소스 URL을 추출하는 복잡한 작업을 처리하면서 생성된 마크업을 제어할 수 있습니다.
사용 가능한 도우미:
asset - 사용자 지정 특성을 사용하여 <img> 태그를 생성합니다.
text - 텍스트 콘텐츠를 사용자 지정 특성으로 래핑하는 <span>개의 태그를 생성합니다.
asset 도우미 asset-helper
구문:
{{{asset fieldValue attribute1="value1" attribute2="value2"}}}
기억하십시오.
- 이중 중괄호가 아닌 자산 도우미와 함께 삼중 중괄호
{{{ }}}을(를) 사용하십시오.
네 가지 기본 예 four-basic-examples
네 가지 기본 예는 다음과 같습니다.
<!-- Add a CSS class to an image -->
{{{asset fields.heroImage class="hero-image"}}}
<!-- Output: <img src="..." alt="..." class="hero-image"> -->
<!-- Add multiple CSS classes -->
{{{asset fields.productImage class="product-img responsive shadow"}}}
<!-- Add id and class -->
{{{asset fields.logo class="brand-logo" id="main-logo"}}}
<!-- Add data attributes -->
{{{asset fields.thumbnail class="thumb" data-category="product" data-id="123"}}}
지원되는 속성 supported-attributes
유효한 HTML 속성을 추가할 수 있습니다.
class
class="my-class another-class"
alt
alt="Custom alt text" (overrides existing alt)
data-*
data-index="1" data-type="hero"
aria-*
aria-label="Description" aria-hidden="true"
style
style="border-radius: 8px;"
대체 텍스트 재정의 override-alt-text
원본 이미지의 alt 특성을 재정의할 수 있습니다.
{{{asset fields.photo alt="Custom description for accessibility"}}}
복잡한 예 complex-example
복잡한 예는 다음과 같습니다.
<article class="blog-post">
<header>
{{{asset fields.featuredImage
class="featured-image responsive"
id="post-hero"
loading="lazy"
data-post-id="12345"}}}
</header>
</article>
루프와 함께 사용 using-with-loops
루프의 자산 도우미:
{{#each fields.galleryImages}}
{{{asset this class="gallery-item" data-index=@index}}}
{{/each}}
text 도우미 text-helper
텍스트 도우미는 텍스트 콘텐츠를 사용자 지정 CSS 클래스 및 HTML 특성으로 래핑하는 <span> 태그를 생성합니다. 개별 텍스트 필드의 스타일을 지정하는 데 유용합니다.
구문:
{{{text fieldValue attribute1="value1" attribute2="value2"}}}
기억하십시오.
- 중괄호가 아닌 텍스트 도우미와 함께 중괄호
{{{ }}}을(를) 사용하십시오.
세 가지 기본 예 three-basic-examples
세 가지 기본 예는 다음과 같습니다.
<!-- Add a CSS class to text -->
{{{text fields.title class="article-title"}}}
<!-- Output: <span class="article-title">The Title Text</span> -->
<!-- Add multiple attributes -->
{{{text fields.price class="price-tag" id="product-price" data-currency="USD"}}}
<!-- Style inline text -->
{{{text fields.highlightedText class="highlighted" style="background: yellow;"}}}
일반적인 사용 사례 common-use-cases
일반적인 사용 사례는 다음과 같습니다.
<!-- Styling article metadata -->
<article>
<header>
{{{text fields.category class="category-badge"}}}
<h1>{{{fields.title}}}</h1>
{{{text fields.author class="byline"}}}
{{{text fields.publishDate class="date"}}}
</header>
</article>
<!-- Creating styled labels -->
<div class="product-card">
{{{text fields.productName class="product-name"}}}
{{{text fields.brand class="brand-label" data-brand-id="abc"}}}
{{{text fields.price class="price" id="main-price"}}}
</div>
<!-- Accessibility enhancements -->
{{{text fields.importantNote class="alert" role="alert" aria-live="polite"}}}
루프 사용 with-loops
루프를 사용하는 일반적인 사용 사례는 다음과 같습니다.
{{#each fields.tags}}
{{{text this class="tag-badge"}}}
{{/each}}
도우미 - 속성 유효성 검사 helpers-attribute-validation
두 도우미 모두 속성 이름을 출력에 포함하기 전에 유효성을 검사합니다.
유효한 속성 이름:
잘못된 속성 이름은 로그에 경고와 함께 자동으로 건너뜁니다.
{{{asset fields.image class="valid" 123-invalid="skipped" id="also-valid"}}}
<!-- Output: <img src="..." alt="..." class="valid" id="also-valid"> -->
<!-- 123-invalid is skipped because it starts with a number -->
기억하십시오.
- 서버 로그에서 “잘못된 특성 이름 형식 차단” 경고를 확인하십시오.
직접 출력을 도우미와 비교 comparing-direct-output-to-helpers
직접 출력 {{{fields.xxx}}}을(를) 사용해야 하는 경우:
- 사용자 지정 스타일은 필요하지 않습니다.
- 기본 출력을 그대로 원하는 경우
- 필드에는 수정하지 않을 복잡한 HTML이 포함되어 있습니다
도우미 사용 시기:
- 스타일링을 위해 CSS 클래스를 추가해야 합니다.
- 사용자 지정 HTML 특성(
data-*, aria-* 등)을 추가해야 합니다.
- 일관되고 제어된 HTML 구조를 원합니다.
비교:
<!-- Direct output - uses whatever HTML the system generates -->
{{{fields.heroImage}}}
<!-- Output: <img src="/path/image.jpg" alt="Hero Image"> -->
<!-- With asset helper - full control over attributes -->
{{{asset fields.heroImage class="hero responsive" id="main-hero" loading="lazy"}}}
<!-- Output: <img src="/path/image.jpg" alt="Hero Image" class="hero responsive" id="main-hero" loading="lazy"> -->
빠른 참조 quick-reference
몇 가지 빠른 참조 정보가 참조용으로 제공됩니다.
컨텍스트 변수 context-variables
컨텍스트 변수:
{{properties}} <!-- Main fragment metadata -->
{{fields}} <!-- Map keyed by field name to rendered values (such as strings, lists, nested maps for Content Fragment references, commerce maps, HTML, and others) -->
{{allFields}} <!-- List of { name, value } maps (uniform iteration) -->
{{hasFields}}. <!-- Boolean -->
{{hasReferencedFragments}}. <!-- Boolean -->
{{referencedFragments}} <!-- List of referenced-fragment maps -->
필드 액세스 field-access
필드에 액세스하는 방법:
{{{fields.fieldName}}} <!-- Direct field -->
{{{fields.author.name}}} <!-- Nested Content Fragment field -->
{{{fields.author.org.address.city}}} <!-- Multi-level nesting -->
{{{fields.tags.[0]}}} <!-- Array by index -->
{{#each fields.tags}}...{{/each}} <!-- Array iteration -->
{{{fields.authors.[0].name}}} <!-- Multi-valued Content Fragment reference -->
제어 흐름 control-flow
제어 흐름은 다음과 같습니다.
{{#if condition}}...{{/if}} <!-- Conditional -->
{{#if condition}}...{{else}}...{{/if}} <!-- If/else -->
{{#unless condition}}...{{/unless}} <!-- Negative conditional -->
{{#each array}}...{{/each}} <!-- Iteration -->
{{#each array}}...{{else}}...{{/each}} <!-- Iteration with fallback -->
{{#with object}}...{{/with}} <!-- Change scope -->
루프 변수 loop-variables
루프 변수:
{{@index}} <!-- 0-based index -->
{{@number}} <!-- 1-based index -->
{{@first}} <!-- true for first item -->
{{@last}} <!-- true for last item -->
{{@key}} <!-- Object property name -->
{{this}} <!-- Current item -->
{{../parent}} <!-- Access parent scope -->
사용자 지정 템플릿 도우미 custom-template-helpers
사용자 지정 템플릿 도우미:
{{{asset fields.image class="css-class"}}} <!-- Image with class -->
{{{asset fields.image class="c1" id="my-id"}}} <!-- Image with multiple attrs -->
{{{asset fields.image alt="Custom alt text"}}} <!-- Override alt text -->
{{{asset fields.image loading="lazy" data-x="val"}}} <!-- Custom attributes -->
{{{text fields.title class="title-class"}}} <!-- Span with class -->
{{{text fields.price class="price" id="p1"}}} <!-- Span with multiple attrs -->
{{{text this class="item" data-index=@index}}} <!-- In loops -->
추가 리소스 additional-resources
추가 리소스를 사용할 수 있습니다.
experience-manager-cloud-service-help-main-toc