Live Search 팝오버 CIF 구성 요소
- 주제:
- 상거래 통합 프레임워크
작성 대상:
- 관리자
Live Search 팝오버는 검색 필드에 입력할 때 Live Search 결과를 포함하는 요소입니다.
이 항목에서는 이 구성 요소를 AEM 사이트에 통합하는 방법을 설명합니다.
파일 구조
CIF 구성 요소를 활성화하려면 파일을 편집하고 만들어야 합니다.
-
ui.apps/src/main/content/jcr_root/apps/venia/components/commerce/searchbar/clientlibs/.content.xml
.content.xml
파일 만들기:<?xml version="1.0" encoding="UTF-8"?> <jcr:root xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" jcr:primaryType="cq:ClientLibraryFolder" allowProxy="{Boolean}true" categories="[venia.cif]" jsProcessor="[default:none,min:none]"/>
-
ui.apps/src/main/content/jcr_root/apps/venia/components/commerce/searchbar/clientlibs/css.txt
css.txt
파일 만들기:#base=css searchbar.css
-
ui.apps/src/main/content/jcr_root/apps/venia/components/commerce/searchbar/clientlibs/css/searchbar.css
searchbar.css
파일 만들기:.searchbar__root .action.search:before { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; font-size: 16px; line-height: 32px; color: #757575; /* content: "\e615"; */ font-family: "luma-icons"; margin: 0; vertical-align: top; display: inline-block; font-weight: normal; overflow: hidden; speak: none; text-align: center; } .searchbar__label { display: none; } .searchbar__root .action.search > span { border: 0; clip: rect(0, 0, 0, 0); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; width: 1px; } input.searchbar__input::placeholder { font-size: 14px; } input.searchbar__input { background: #fff; background-clip: padding-box; border: 1px solid #c2c2c2; border-radius: 1px; font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 16px; height: 32px; line-height: 1.42857143; padding: 0 9px; vertical-align: baseline; width: 100%; max-width: 200px; box-sizing: border-box; cursor: text; } .search-autocomplete { position: absolute; } div.searchbar { width: 100% !important; } div.searchbar__fields.search { display: flex; justify-content: center; } .searchbar__form { justify-items: center !important; } @media all and (min-width: 769px) { .searchbar__form { justify-items: stretch !important; } div.searchbar { width: 8.333333% !important; margin: 0; } .searchbar__root { position: relative; z-index: 4; } .searchbar__root .searchbar__control { border-top: 0; margin: 0; padding: 0.75em 0; } .searchbar__root .searchbar__input { margin: 0; padding-right: 12px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } }
-
ui.apps/src/main/content/jcr_root/apps/venia/components/commerce/searchbar/clientlibs/js.txt
js.txt
파일 만들기:js/searchbar.js
-
ui.apps/src/main/content/jcr_root/apps/venia/components/commerce/searchbar/clientlibs/js/searchbar.js
searchbar.js
파일 만들기:/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~ Copyright 2023 Adobe ~ ~ Licensed under the Apache License, Version 2.0 (the "License"); ~ you may not use this file except in compliance with the License. ~ You may obtain a copy of the License at ~ ~ http://www.apache.org/licenses/LICENSE-2.0 ~ ~ Unless required by applicable law or agreed to in writing, software ~ distributed under the License is distributed on an "AS IS" BASIS, ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ~ See the License for the specific language governing permissions and ~ limitations under the License. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ "use strict"; const dataServicesStorefrontInstanceContextQuery = ` query DataServicesStorefrontInstanceContext { dataServicesStorefrontInstanceContext { customer_group environment_id environment store_id store_view_id store_code store_view_code website_id website_name website_code store_url api_key store_name store_view_name base_currency_code store_view_currency_code catalog_extension_version } storeConfig { base_currency_code store_code } } `; const dataServicesMagentoExtensionContextQuery = ` query DataServicesStorefrontInstanceContext { dataServicesMagentoExtensionContext { magento_extension_version } } `; const dataServicesStoreConfigurationContextQuery = ` query DataServicesStoreConfigurationContext { dataServicesStoreConfigurationContext { currency_symbol currency_rate page_size page_size_options default_page_size_option display_out_of_stock allow_all_products locale min_query_length } } `; const getCookie = (cookieName) => { const cookie = document.cookie.match( `(^|[^;]+)\\s*${cookieName}\\s*=\\s*([^;]+)` ); return cookie ? cookie.pop() : ""; }; const getLoginToken = () => { const key = "M2_VENIA_BROWSER_PERSISTENCE__signin_token"; let token = getCookie("cif.userToken") || ""; try { const lsToken = JSON.parse(localStorage.getItem(key)); if (lsToken && lsToken.value) { const timestamp = new Date().getTime(); if (timestamp - lsToken.timeStored < lsToken.ttl * 1000) { token = lsToken.value.replace(/"/g, ""); } } } catch (e) { console.error(`Login token at ${key} is not valid JSON.`); } return token; }; async function getGraphQLQuery(query, variables = {}) { const graphqlEndpoint = `/api/graphql`; const headers = { "Content-Type": "application/json", }; const loginToken = getLoginToken(); if (loginToken) { headers["Authorization"] = `Bearer ${loginToken}`; } const response = await fetch(graphqlEndpoint, { method: "POST", headers, body: JSON.stringify({ query, variables, }), }).then((res) => res.json()); return response.data; } class SearchBar { constructor() { const stateObject = { dataServicesStorefrontInstanceContext: null, dataServicesStoreConfigurationContext: null, magentoExtensionVersion: null, storeConfig: null, }; this._state = stateObject; this._init(); } _init() { this._initLiveSearch(); } _injectStoreScript(src) { const script = document.createElement("script"); script.type = "text/javascript"; script.src = src; document.head.appendChild(script); } async _getStoreData() { const { dataServicesStorefrontInstanceContext, storeConfig } = (await getGraphQLQuery(dataServicesStorefrontInstanceContextQuery)) || {}; const { dataServicesStoreConfigurationContext } = (await getGraphQLQuery(dataServicesStoreConfigurationContextQuery)) || {}; this._state.dataServicesStorefrontInstanceContext = dataServicesStorefrontInstanceContext; this._state.dataServicesStoreConfigurationContext = dataServicesStoreConfigurationContext; this._state.storeConfig = storeConfig; if (!dataServicesStorefrontInstanceContext) { console.log("no dataServicesStorefrontInstanceContext"); return; } // set session storage to expose for widget sessionStorage.setItem( "WIDGET_STOREFRONT_INSTANCE_CONTEXT", JSON.stringify({ ...dataServicesStorefrontInstanceContext, ...dataServicesStoreConfigurationContext, }) ); } async _getMagentoExtensionVersion() { const { dataServicesMagentoExtensionContext } = (await getGraphQLQuery(dataServicesMagentoExtensionContextQuery)) || {}; this._state.magentoExtensionVersion = dataServicesMagentoExtensionContext?.magento_extension_version; if (!dataServicesMagentoExtensionContext) { console.log("no magentoExtensionVersion"); return; } } getStoreConfigMetadata() { const storeConfig = JSON.parse( document .querySelector("meta[name='store-config']") .getAttribute("content") ); const { storeRootUrl } = storeConfig; const redirectUrl = storeRootUrl.split(".html")[0]; return { storeConfig, redirectUrl }; } async _initLiveSearch() { await Promise.all([ this._getStoreData(), this._getMagentoExtensionVersion(), ]); if (!window.LiveSearchAutocomplete) { const liveSearchSrc = "https://livesearch-autocomplete.magento-ds.com/v0/LiveSearchAutocomplete.js"; this._injectStoreScript(liveSearchSrc); // wait until script is loaded await new Promise((resolve) => { const interval = setInterval(() => { if (window.LiveSearchAutocomplete) { clearInterval(interval); resolve(); } }, 200); }); } const { dataServicesStorefrontInstanceContext, dataServicesStoreConfigurationContext, } = this._state; if (!dataServicesStorefrontInstanceContext) { console.log("no dataServicesStorefrontInstanceContext"); return; } // initialize live-search new window.LiveSearchAutocomplete({ environmentId: dataServicesStorefrontInstanceContext.environment_id, websiteCode: dataServicesStorefrontInstanceContext.website_code, storeCode: dataServicesStorefrontInstanceContext.store_code, storeViewCode: dataServicesStorefrontInstanceContext.store_view_code, config: { pageSize: dataServicesStoreConfigurationContext.page_size, minQueryLength: dataServicesStoreConfigurationContext.min_query_length, currencySymbol: dataServicesStoreConfigurationContext.currency_symbol, currencyRate: dataServicesStoreConfigurationContext.currency_rate, displayOutOfStock: dataServicesStoreConfigurationContext.display_out_of_stock, allowAllProducts: dataServicesStoreConfigurationContext.allow_all_products, }, context: { customerGroup: dataServicesStorefrontInstanceContext.customer_group, }, route: ({ sku }) => { return `${ this.getStoreConfigMetadata().redirectUrl }.cifproductredirect.html/${sku}`; }, searchRoute: { route: `${this.getStoreConfigMetadata().redirectUrl}/search.html`, query: "search_query", }, }); const formEle = document.getElementById("search_mini_form"); formEle.setAttribute( "action", `${dataServicesStorefrontInstanceContext.store_url}catalogsearch/result` ); // initialize store event after live-search this._initMetrics(); } async _initMetrics() { // Magento Store event // wait until script is magentoStorefrontEvents is found await new Promise((resolve) => { const interval = setInterval(() => { if (window.magentoStorefrontEvents) { clearInterval(interval); resolve(); } }, 200); }); const mse = window.magentoStorefrontEvents; const { dataServicesStorefrontInstanceContext, storeConfig } = this._state; const { base_currency_code, catalog_extension_version, environment, environment_id, store_code, store_id, store_name, store_url, store_view_code, store_view_id, store_view_name, store_view_currency_code, website_code, website_id, website_name, } = dataServicesStorefrontInstanceContext; console.log("initializing magento extension"); mse.context.setMagentoExtension({ magentoExtensionVersion: this._state.magentoExtensionVersion, }); mse.context.setPage({ pageType: "pdp", maxXOffset: 0, maxYOffset: 0, minXOffset: 0, minYOffset: 0, ping_interval: 5, pings: 1, }); mse.context.setStorefrontInstance({ environmentId: environment_id, environment: environment, storeUrl: store_url, websiteId: website_id, websiteCode: website_code, storeId: store_id, storeCode: store_code, storeViewId: store_view_id, storeViewCode: store_view_code, websiteName: website_name, storeName: store_name, storeViewName: store_view_name, baseCurrencyCode: base_currency_code, storeViewCurrencyCode: store_view_currency_code, catalogExtensionVersion: catalog_extension_version, }); } } (function () { function onDocumentReady() { new SearchBar({}); } if (document.readyState !== "loading") { onDocumentReady(); } else { document.addEventListener("DOMContentLoaded", onDocumentReady); } })();
-
ui.apps/src/main/content/jcr_root/apps/venia/components/commerce/searchbar/searchbar.html
searchbar.html
파일 만들기:<!-- Livesearch popover --> <div data-sly-use.storeconfig="com.adobe.cq.commerce.core.components.models.storeconfigexporter.StoreConfigExporter" class="searchbar__root widget-search" > <div class="block-title" style="display: none"> <strong>Search</strong> </div> <div class="live-search-popover block-content"> <form class="searchbar__form" id="search_mini_form" method="get" style="width: auto" > <div class="searchbar__fields"> <label class="searchbar__label" for="search" data-role="minisearch-label" > <span>Search</span> </label> <div class="searchbar__control"> <input id="search" type="text" name="q" value="" placeholder="Search entire store here..." class="searchbar__input" maxlength="128" role="combobox" aria-haspopup="false" aria-autocomplete="both" autocomplete="off" aria-expanded="false" onchange="" /> <div id="search_autocomplete" class="search-autocomplete"></div> </div> </div> <div class="actions" style="display: none"> <button type="submit" title="Search" class="action search" aria-label="Search" > <span>Search</span> </button> </div> </form> </div> </div>
-
ui.config/src/main/content/jcr_root/apps/venia/osgiconfig/config/com.adobe.cq.commerce.core.components.internal.servlets.ProductPageRedirectServlet.cfg.json
com.adobe.cq.commerce.core.components.internal.servlets.ProductPageRedirectServlet.cfg.json
파일 만들기:{ "sling.servlet.resourceTypes": [ "core/cif/components/structure/page/v1/page", "core/cif/components/structure/page/v2/page", "core/cif/components/structure/page/v3/page" ] }
-
ui.tests/test-module/specs/venia/searchbar.js
searchbar.js
파일(19-20행)을 편집하고describe
을(를)describe.skip
(으)로 변경합니다.describe.skip('Venia Searchbar Component', () => {
-
Experience Manager
- 개요
- 릴리스 정보
- 릴리스 정보
- AEMaaCS 기능 릴리스 정보
- AEMaaCS 유지 관리 릴리스 정보
- Cloud Manager 릴리스 정보
- 마이그레이션 도구 릴리스 정보
- Experience Manager 강화 커넥터용 Workfront 릴리스 정보
- 베리에이션 생성 릴리스 정보
- 범용 편집기 릴리스 정보
- 새로운 기능
- AEM Cloud Service의 주요 변경 사항
- 사용 중단 및 제거된 기능과 API
- 프리릴리스 채널
- 보안
- AEM as a Cloud Service 보안 개요
- AEM as a Cloud Service에 대한 고급 네트워킹 구성
- AEM as a Cloud Service에 대한 IMS 지원
- AEM as a Cloud Service에 대한 Same Site 쿠키 지원
- 메일 서비스에 대한 OAuth2 지원
- WAF 규칙이 포함된 트래픽 필터 규칙
- Adobe Developer Console에서 JWT 자격 증명 사용 중단
- AEM as a Cloud Service에 대한 IMS 통합 설정
- Sling 서비스 사용자 매핑 및 서비스 사용자 정의의 모범 사례
- 온보딩
- AEM as a Cloud Service 마이그레이션 여정
- Sites
- AEM Cloud Service의 AEM Sites에 대한 주요 변경 사항
- Sites 및 Edge Delivery Services
- 작성
- 관리
- AEM as a Cloud Service와 통합
- AEM as a Cloud Service용 실제 사용 모니터링
- Assets
- 개요 및 새로운 기능
- Assets as a Cloud Service 주요 변경 사항
- Assets 아키텍처
- 지원되는 파일 형식
- 자산 마이크로서비스 개요
- Assets에서의 접근성
- Assets as a Cloud Service Ultimate
- Assets as a Cloud Service Ultimate 활성화
- Assets as a Cloud Service Prime
- Assets Collaborator 사용자
- AEM Assets를 통합하면서 Edge Delivery Services용 콘텐츠 작성
- 디지털 자산 관리
- 마이크로 프론트엔드 자산 선택기
- 마이크로 프론트엔드 대상 선택기
- 자산 공유
- 자산 재처리
- 자산 마이크로서비스 사용 시작하기
- 자산 추가 및 업로드
- 자산 검색
- 일반적인 자산 관리 작업
- 게시 관리
- 3D 자산 미리보기
- 이미지용 스마트 태그
- 비디오 자산에 스마트 태그 지정
- 자산 구성 방법
- Adobe Stock 자산 사용
- 컬렉션 관리
- 메타데이터 개요
- Adobe Creative Cloud와 통합
- 메타데이터 추가 또는 편집 방법
- 폴더 자산 및 컬렉션 검토
- Assets Insights 사용 및 구성
- 메타데이터 프로필
- 메타데이터 스키마
- 비디오 자산 관리
- MSM을 사용하여 자산 재사용
- 자산 다운로드
- 편집할 자산 체크인 및 체크아웃
- 비공개 폴더 생성 및 공유
- 자산용 Digital Rights Management
- 자산에 워터마크 추가
- Creative Cloud API를 사용하여 자산 처리
- 이미지용 색상 태그
- PDF 문서 관리
- Assets 구성, 관리 및 확장
- 자산 공유 및 배치
- 콘텐츠 조각
- Dynamic Media
- Dynamic Media 여정: 기본 사항
- Experience League의 Dynamic Media 뉴스레터 아카이브
- Dynamic Media 설정
- Dynamic Media를 사용하여 작업
- Dynamic Media 구성
- Dynamic Media Prime 및 Ultimate
- Dynamic Media Prime 및 Ultimate 활성화
- 옵션 - Dynamic Media, 일반 설정 구성
- 옵션 - Dynamic Media, 게시 설정 구성
- Dynamic Media 문제 해결
- Dynamic Media 별칭 계정 구성
- Dynamic Media에서의 접근성
- Dynamic Media 자산 관리
- 이미지 품질 최적화 모범 사례
- 이미지 프로필
- 비디오 프로필
- Dynamic Media 이미지 사전 설정 관리
- Dynamic Media 이미지 사전 설정 적용
- Dynamic Media 뷰어 사전 설정 관리
- Dynamic Media 뷰어 사전 설정 적용
- 일괄 처리 집합 사전 설정
- Dynamic Media의 방식으로 CDN 캐시 무효화
- Dynamic Media Classic의 방식으로 CDN 캐시 무효화
- 스마트 이미징
- 클라이언트측 디바이스 픽셀 비율을 활용한 스마트 이미징
- Dynamic Media 자산 전송
- Dynamic Media 템플릿
- Dynamic Media의 핫링크 보호 활성화
- 3D 지원
- Dynamic Media 제한 사항
- 이미지 세트
- 파노라마 이미지
- 혼합 미디어 세트
- 스핀 세트
- Dynamic Media의 비디오
- 슬라이드 배너
- 대화형 이미지
- 대화형 비디오
- 360 VR 비디오
- Dynamic Media 뷰어를 Adobe Analytics 및 Adobe Experience Platform 태그와 통합
- 빠른 보기를 사용하여 사용자 정의 팝업 만들기
- 반응형 사이트에 최적화된 이미지 게재
- Dynamic Media 자산 미리보기
- 페이지에 Dynamic Media 자산 추가
- 웹 페이지에 Dynamic Video 또는 Dynamic Image 뷰어 임베드
- 웹 애플리케이션에 URL 연결
- 규칙 세트를 사용하여 URL 변환
- Dynamic Media 자산 게시
- Dynamic Media의 선택적 게시를 사용하여 작업
- 선택기를 사용하여 작업
- 콘텐츠 FAQ의 HTTP2 게재
- Flash 뷰어 서비스 종료
- DHTML 뷰어 서비스 종료
- OpenAPI 기능이 포함된 Dynamic Media
- Assets 보기로 작업
- Content Hub
- 개요
- Content Hub 배포
- 브랜드 승인 자산을 Content Hub로 업로드 또는 가져오기
- Content Hub 사용자 인터페이스 구성
- Content Hub에 대한 자산 승인
- Content Hub에서 자산 검색
- 자산 속성
- Content Hub에서 자산 공유
- Content Hub를 사용하여 자산 다운로드
- Content Hub에서 라이선스가 부여된 자산 관리
- Content Hub에서 컬렉션 관리
- Content Hub에서 Adobe Express를 사용하여 이미지 편집
- Content Hub의 Asset Insights
- Content Hub에 대해 자주 묻는 질문
- 모범 사례
- Adobe Workfront와 통합
- Adobe Express와 통합
- Creative Cloud와 통합
- Forms
- 개요
- 설정 및 마이그레이션
- 통합
- 서비스
- Adobe Sign과 AEM Forms as a Cloud Service 통합
- DocuSign과 AEM Forms as a Cloud Service 통합
- Adobe Analytics에 적응형 양식 통합
- 적응형 양식 분석 보고서 보기 및 이해
- Adobe Workfront Fusion에 적응형 양식 제출
- Microsoft Power Automate와 적응형 양식 통합
- AEM Sites 페이지에 적응형 양식 임베드
- 외부 웹 페이지에 핵심 구성 요소 기반 적응형 양식 임베드
- 외부 웹 페이지에 기초 구성 요소 기반 적응형 양식 임베드
- Adobe Marketo Engage와 적응형 양식 통합
- Forms 데이터 모델
- 서비스
- 적응형 양식
- 적응형 양식 조각 만들기
- AEM Sites 페이지 또는 경험 조각에 적응형 양식 추가
- 핵심 구성 요소
- 적응형 양식 만들기
- 적응형 양식 만들기
- 핵심 구성 요소 기반 적응형 양식의 레이아웃 설정
- 적응형 양식 조각 만들기
- 적응형 양식의 테마 만들기 - 핵심 구성 요소
- 핵심 구성 요소 기반 적응형 템플릿 만들기
- XFA Forms 템플릿 기반 적응형 양식(핵심 구성 요소) 만들기
- 적응형 양식의 기록 문서 생성
- 기계 번역 또는 인간 번역을 사용하여 적응형 양식 번역
- 리디렉션 페이지 또는 감사 메시지 구성
- 반복 가능한 섹션으로 양식 만들기
- 적응형 양식에 대한 제출 액션 구성
- Azure Blob Storage에 적응형 양식 제출
- Microsoft에 적응형 양식 제출
- Microsoft® SharePoint에 적응형 양식 연결
- AEM 적응형 양식과 AEM Workflow 통합
- 적응형 양식의 REST 엔드포인트에 제출 액션 구성
- 적응형 양식의 이메일 보내기 제출 액션 구성
- 적응형 양식에서 Google reCAPTCHA 사용
- 적응형 양식 핵심 구성 요소의 hCaptcha 사용
- 적응형 양식 핵심 구성 요소의 Turnstile Captcha 사용
- 적응형 양식에서 사용자 정의 오류 핸들러 추가
- 핵심 구성 요소 기반 적응형 양식의 로케일 추가
- 적응형 양식에 대한 JSON 스키마 디자인 (핵심 구성 요소)
- 적응형 양식에 버전 관리, 댓글 및 주석 추가
- 적응형 양식 비교
- 사용자 정의 제출 액션 만들기
- Experience Manager Forms에서 게시 관리
- 핵심 구성 요소 기반 적응형 양식의 규칙 편집기 소개
- 핵심 구성 요소 기반 적응형 양식의 사용자 정의 함수 소개
- Forms 포털 및 해당 구성 요소 소개
- 적응형 양식 만들기
- 기초 구성 요소
- 적응형 양식 키워드
- 양식 미리보기
- 인터랙티브 커뮤니케이션
- Forms 중심 워크플로
- 커뮤니케이션 API
- 트랜잭션 보고서
- 개발자 API 참조
- 문제 해결
- Screens
- Content and Commerce
- Edge Delivery Services
- Edge Delivery Services 개요
- AEM과 함께 Edge Delivery Services 사용
- 작성 방법 선택
- WYSIWYG 작성
- 문서 기반 작성
- 애플리케이션 빌드
- 애플리케이션 실행
- Forms 빌드
- 개요
- WYSIWYG 작성
- Edge Delivery Services용 Forms Universal Editor 소개 - 전체 안내서
- 범용 편집기를 사용하여 작성을 시작하는 방법 - 단계별 자습서
- Universal Editor 인터페이스 안내서: 도구, 기능 및 탐색 설명
- 모바일 친화적인 Forms 만들기: 범용 편집기의 반응형 디자인
- 아름다운 Forms 디자인: 범용 편집기를 위한 스타일 및 테마 지정 가이드
- Forms에 동적 동작 추가: 규칙 편집기에 대한 전체 안내서
- 양식 제출 안내서: 양식 제출 작업 구성 및 사용자 지정
- 스팸으로부터 Forms 보호: reCAPTCHA 보안 추가
- Forms 게시 및 배포 방법: 범용 편집기 게시 안내서
- 사용자 지정 양식 구성 요소 빌드: 유니버설 편집기에 대한 개발자 안내서
- 문서 기반 작성
- 첫 번째 양식 작성: Google Sheets 및 Excel로 빠른 시작 안내서
- Google Sheets 또는 Excel을 사용하여 Forms을 만드는 방법: 단계별 안내서
- 적응형 양식 블록의 다양한 구성 요소
- 양식을 Google Sheets에 연결: 데이터 수집 설정 안내서
- 양식을 라이브로 만들기: 게시 및 데이터 수집 안내서
- 아름다운 Forms 디자인: 스타일 및 사용자 지정 안내서
- 성공 메시지 만들기: 양식의 감사 페이지 사용자 지정
- 양식 제출 안내서: Forms 제출 서비스 사용
- 동적 양식 필드: URL에서 옵션 로드
- 스마트 동작 추가: 양식 규칙 및 논리 안내서
- 동적 Forms 만들기: 반복 가능한 섹션 추가
- Forms 보호: reCAPTCHA 보안 추가
- Edge Delivery 리소스
- Headless
- 생성형 AI
- 구현
- AEM as a Cloud Service용 애플리케이션 구현
- Cloud Manager 사용
- AEM as a Cloud Service용 개발
- AEM 프로젝트 구조
- AEM 프로젝트 저장소 구조 패키지
- AEM as a Cloud Service SDK
- AEM 신속한 개발 환경
- AEM as a Cloud Service 개발 지침
- AEM as a Cloud Service Developer Console (Beta)
- 로깅
- 로그 전달
- 구성 및 구성 브라우저
- AEM 기술 기초
- API 참조 자료
- OpenAPI 기반 API
- 서버측 API용 액세스 토큰 생성
- 빠른 사이트 생성 및 프론트엔드 맞춤화
- 프론트엔드 파이프라인으로 Sites 개발
- 사이트 템플릿 및 테마 맞춤화
- AEM Headful 및 Headless
- Sling 모델 내보내기 도구를 통한 ResourceResolver 직렬화 비활성화
- 전체 스택 AEM 개발
- 범용 편집기
- Headless 경험 관리
- 하이브리드 및 SPA 개발
- 개발자 도구
- 개인화
- AEM as a Cloud Service 구성 및 확장
- AEM as a Cloud Service에 배포
- 작성자 계층
- 콘텐츠 게재 개요
- 커넥터
- 운영
- 규정 준수