탐색 및 라우팅 추가 navigation-routing

SPA Pages 및 SPA Editor SDK를 사용하여 AEM의 여러 보기를 지원하는 방법에 대해 알아봅니다. 동적 탐색은 Angular 경로를 사용하여 구현되고 기존 헤더 구성 요소에 추가됩니다.

목표

  1. SPA Editor를 사용할 때 사용할 수 있는 SPA 모델 라우팅 옵션을 이해합니다.
  2. 사용 방법 알아보기 Angular 라우팅 를 클릭하여 SPA의 다른 보기 사이를 이동합니다.
  3. AEM 페이지 계층 구조에 의해 실행되는 동적 탐색 구현

빌드할 내용

이 장에서는 기존 탐색 메뉴를 추가합니다 Header 구성 요소. 탐색 메뉴는 AEM 페이지 계층에 의해 구동되며,에서 제공하는 JSON 모델을 사용합니다. 탐색 핵심 구성 요소.

탐색 구현

사전 요구 사항

설정에 필요한 도구 및 지침 검토 로컬 개발 환경.

코드 가져오기

  1. Git을 통해 이 자습서의 시작점을 다운로드하십시오.

    code language-shell
    $ git clone git@github.com:adobe/aem-guides-wknd-spa.git
    $ cd aem-guides-wknd-spa
    $ git checkout Angular/navigation-routing-start
    
  2. Maven을 사용하여 로컬 AEM 인스턴스에 코드 베이스를 배포합니다.

    code language-shell
    $ mvn clean install -PautoInstallSinglePackage
    

    사용 중인 경우 AEM 6.x 추가 classic 프로필:

    code language-shell
    $ mvn clean install -PautoInstallSinglePackage -Pclassic
    
  3. 기존 패키지를 위한 완료된 패키지 설치 WKND 참조 사이트. 에서 제공한 이미지 WKND 참조 사이트 는 WKND SPA에서 다시 사용됩니다. 패키지를 설치하려면 AEM 패키지 관리자.

    패키지 관리자 설치 wknd.all

에서 완성된 코드를 항상 볼 수 있습니다. GitHub 또는 분기로 전환하여 코드를 로컬에서 확인합니다. Angular/navigation-routing-solution.

Inspect HeaderComponent 업데이트 inspect-header

이전 장에서는 HeaderComponent 구성 요소를 를 통해 포함된 순수 Angular 구성 요소로 추가했습니다. app.component.html. 이 장에서는 HeaderComponent 구성 요소가 앱에서 제거되고 를 통해 추가됩니다. 템플릿 편집기. 이렇게 하면 사용자가 의 탐색 메뉴를 구성할 수 있습니다. HeaderComponent AEM 내에서.

NOTE
이 장을 시작하기 위해 코드 베이스에 대한 여러 CSS 및 JavaScript 업데이트가 이미 수행되었습니다. 핵심 개념에 집중하기 위해 모두 코드 변경 사항에 대해 설명합니다. 전체 변경 사항을 볼 수 있습니다 여기.
  1. 선택한 IDE에서 이 장에 대한 SPA 스타터 프로젝트를 엽니다.

  2. 아래 ui.frontend 모듈 파일 검사 header.component.ts 위치: ui.frontend/src/app/components/header/header.component.ts.

    의 추가를 포함하여 몇 가지 업데이트가 이루어졌습니다. HeaderEditConfig 및 a MapTo 구성 요소를 AEM 구성 요소에 매핑하려면 wknd-spa-angular/components/header.

    code language-js
    /* header.component.ts */
    ...
    const HeaderEditConfig = {
        ...
    };
    
    @Component({
    selector: 'app-header',
    templateUrl: './header.component.html',
    styleUrls: ['./header.component.scss']
    })
    export class HeaderComponent implements OnInit {
    @Input() items: object[];
        ...
    }
    ...
    MapTo('wknd-spa-angular/components/header')(withRouter(Header), HeaderEditConfig);
    

    다음을 참고하십시오. @Input() 주석 items. items 은 AEM에서 전달된 탐색 개체의 배열을 포함합니다.

  3. 다음에서 ui.apps 모듈은 AEM의 구성 요소 정의를 검사합니다. Header 구성 요소: ui.apps/src/main/content/jcr_root/apps/wknd-spa-angular/components/header/.content.xml:

    code language-xml
    <?xml version="1.0" encoding="UTF-8"?>
    <jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:cq="http://www.day.com/jcr/cq/1.0"
        xmlns:jcr="http://www.jcp.org/jcr/1.0"
        jcr:primaryType="cq:Component"
        jcr:title="Header"
        sling:resourceSuperType="wknd-spa-angular/components/navigation"
        componentGroup="WKND SPA Angular - Structure"/>
    

    더 AEM Header 구성 요소는 의 모든 기능을 상속합니다. 탐색 핵심 구성 요소 를 통해 sling:resourceSuperType 속성.

SPA 템플릿에 HeaderComponent 추가 add-header-template

  1. 브라우저를 열고 AEM에 로그인합니다. http://localhost:4502/. 시작 코드 베이스를 이미 배포해야 합니다.

  2. 다음 위치로 이동 SPA 페이지 템플릿: http://localhost:4502/editor.html/conf/wknd-spa-angular/settings/wcm/templates/spa-page-template/structure.html.

  3. 가장 바깥쪽 선택 루트 레이아웃 컨테이너 및 클릭 정책 아이콘. 조심해 아님 을(를) 선택하려면 레이아웃 컨테이너 작성을 위해 잠금 해제되었습니다.

    루트 레이아웃 컨테이너 정책 아이콘 선택

  4. 현재 정책을 복사하고 이름이 인 새 정책을 만듭니다. SPA 구조:

    SPA 구조 정책

    아래 허용된 구성 요소 > 일반 > 다음을 선택합니다. 레이아웃 컨테이너 구성 요소.

    아래 허용된 구성 요소 > WKND SPA ANGULAR - 구조 > 다음을 선택합니다. 머리글 구성 요소:

    헤더 구성 요소 선택

    아래 허용된 구성 요소 > WKND SPA ANGULAR - 컨텐츠 > 다음을 선택합니다. 이미지텍스트 구성 요소. 총 4개의 구성 요소를 선택해야 합니다.

    완료 ​를 클릭하여 변경 내용을 저장합니다.

  5. 새로 고침 페이지. 추가 머리글 잠금 해제됨 위의 구성 요소 레이아웃 컨테이너:

    템플릿에 헤더 구성 요소 추가

  6. 다음 항목 선택 머리글 구성 요소 및 클릭 정책 아이콘을 클릭하여 정책을 편집합니다.

    헤더 정책 클릭

  7. 을(를) 사용하여 새 정책 만들기 정책 제목 / "WKND SPA 헤더".

    아래 속성:

    • 설정 탐색 루트/content/wknd-spa-angular/us/en.
    • 설정 루트 수준 제외1.
    • 선택 취소 모든 하위 페이지 수집.
    • 설정 탐색 구조 깊이3.

    헤더 정책 구성

    이렇게 하면 2단계 아래에 탐색이 수집됩니다. /content/wknd-spa-angular/us/en.

  8. 변경 사항을 저장하면 가 채워집니다. Header 템플릿의 일부로:

    채워진 헤더 구성 요소

하위 페이지 만들기

그런 다음 AEM에서 다른 보기 역할을 할 추가 페이지를 SPA에서 만듭니다. AEM에서 제공하는 JSON 모델의 계층 구조도 함께 살펴볼 것이다.

  1. 다음 위치로 이동 사이트 콘솔: http://localhost:4502/sites.html/content/wknd-spa-angular/us/en/home. 다음 항목 선택 WKND SPA Angular 홈 페이지 및 클릭 만들기 > 페이지:

    새 페이지 만들기

  2. 아래 템플릿 선택 SPA 페이지. 아래 속성 입력 "페이지 1" 대상: 제목"page-1" 을(를) 이름으로 사용하십시오.

    초기 페이지 속성 입력

    클릭 만들기 대화 상자 팝업에서 열기 를 클릭하여 AEM SPA 편집기에서 페이지를 엽니다.

  3. 새 항목 추가 텍스트 주 구성 요소 레이아웃 컨테이너. 구성 요소를 편집하고 다음 텍스트를 입력합니다. "페이지 1" rte 및 H1 요소(단락 요소를 변경하려면 전체 화면 모드로 전환해야 함)

    샘플 콘텐츠 페이지 1

    이미지와 같은 콘텐츠를 자유롭게 추가할 수 있습니다.

  4. AEM Sites 콘솔로 돌아가서 위의 단계를 반복하여 이라는 두 번째 페이지를 만듭니다. "페이지 2" 의 형제 페이지 1. 콘텐츠 추가 페이지 2 쉽게 식별할 수 있도록 합니다.

  5. 마지막으로 세 번째 페이지를 만듭니다. "3페이지" 하지만 하위 / 페이지 2. 사이트 계층 구조가 완료되면 다음과 같이 표시됩니다.

    샘플 사이트 계층

  6. 새 탭에서 AEM에서 제공하는 JSON 모델 API를 엽니다. http://localhost:4502/content/wknd-spa-angular/us/en.model.json. 이 JSON 콘텐츠는 SPA이 처음 로드될 때 요청됩니다. 외부 구조는 다음과 같습니다.

    code language-json
    {
    "language": "en",
    "title": "en",
    "templateName": "spa-app-template",
    "designPath": "/libs/settings/wcm/designs/default",
    "cssClassNames": "spa page basicpage",
    ":type": "wknd-spa-angular/components/spa",
    ":items": {},
    ":itemsOrder": [],
    ":hierarchyType": "page",
    ":path": "/content/wknd-spa-angular/us/en",
    ":children": {
        "/content/wknd-spa-angular/us/en/home": {},
        "/content/wknd-spa-angular/us/en/home/page-1": {},
        "/content/wknd-spa-angular/us/en/home/page-2": {},
        "/content/wknd-spa-angular/us/en/home/page-2/page-3": {}
        }
    }
    

    아래 :children 작성된 각 페이지에 대한 항목이 표시됩니다. 모든 페이지의 컨텐츠는 이 초기 JSON 요청에 있습니다. 콘텐츠가 클라이언트측에서 이미 사용 가능하기 때문에 탐색 라우팅이 구현되면 SPA의 후속 보기가 빠르게 로드됩니다.

    짐을 싣는 것은 현명하지 않다 모두 초기 JSON 요청에 있는 SPA 콘텐츠의 경우, 초기 페이지 로드 속도가 느려집니다. 다음으로 페이지 계층 깊이가 수집되는 방식을 살펴보겠습니다.

  7. 다음 위치로 이동 SPA 루트 템플릿 위치: http://localhost:4502/editor.html/conf/wknd-spa-angular/settings/wcm/templates/spa-app-template/structure.html.

    다음을 클릭합니다. 페이지 속성 메뉴 > 페이지 정책:

    SPA 루트에 대한 페이지 정책 열기

  8. 다음 SPA 루트 템플릿에 추가 항목이 있습니다. 계층 구조 탭으로 이동하여 수집된 JSON 콘텐츠를 제어합니다. 다음 구조 깊이 사이트 계층 구조에서 하위 페이지를 수집할 깊이를 결정합니다. 루트. 다음을 사용할 수도 있습니다 구조 패턴 정규 표현식을 기반으로 추가 페이지를 필터링할 필드입니다.

    업데이트 구조 깊이"2":

    구조 깊이 업데이트

    클릭 완료 정책에 대한 변경 사항을 저장합니다.

  9. JSON 모델 다시 열기 http://localhost:4502/content/wknd-spa-angular/us/en.model.json.

    code language-json
    {
    "language": "en",
    "title": "en",
    "templateName": "spa-app-template",
    "designPath": "/libs/settings/wcm/designs/default",
    "cssClassNames": "spa page basicpage",
    ":type": "wknd-spa-angular/components/spa",
    ":items": {},
    ":itemsOrder": [],
    ":hierarchyType": "page",
    ":path": "/content/wknd-spa-angular/us/en",
    ":children": {
        "/content/wknd-spa-angular/us/en/home": {},
        "/content/wknd-spa-angular/us/en/home/page-1": {},
        "/content/wknd-spa-angular/us/en/home/page-2": {}
        }
    }
    

    다음 사항에 주목하십시오. 페이지 3 경로가 제거되었습니다. /content/wknd-spa-angular/us/en/home/page-2/page-3 초기 JSON 모델에서.

    나중에 AEM SPA Editor SDK가 추가 콘텐츠를 동적으로 로드하는 방법을 살펴보겠습니다.

탐색 구현

그런 다음 새 탐색 메뉴를 구현합니다. NavigationComponent. 에서 바로 코드를 추가할 수 있습니다. header.component.html 그러나 더 나은 방법은 큰 구성 요소를 피하는 것입니다. 대신 NavigationComponent 나중에 다시 사용할 수 있습니다.

  1. AEM에 의해 노출된 JSON 검토 Header 구성 요소 http://localhost:4502/content/wknd-spa-angular/us/en.model.json:

    code language-json
    ...
    "header": {
        "items": [
        {
        "level": 0,
        "active": true,
        "path": "/content/wknd-spa-angular/us/en/home",
        "description": null,
        "url": "/content/wknd-spa-angular/us/en/home.html",
        "lastModified": 1589062597083,
        "title": "WKND SPA Angular Home Page",
        "children": [
                {
                "children": [],
                "level": 1,
                "active": false,
                "path": "/content/wknd-spa-angular/us/en/home/page-1",
                "description": null,
                "url": "/content/wknd-spa-angular/us/en/home/page-1.html",
                "lastModified": 1589429385100,
                "title": "Page 1"
                },
                {
                "level": 1,
                "active": true,
                "path": "/content/wknd-spa-angular/us/en/home/page-2",
                "description": null,
                "url": "/content/wknd-spa-angular/us/en/home/page-2.html",
                "lastModified": 1589429603507,
                "title": "Page 2",
                "children": [
                    {
                    "children": [],
                    "level": 2,
                    "active": false,
                    "path": "/content/wknd-spa-angular/us/en/home/page-2/page-3",
                    "description": null,
                    "url": "/content/wknd-spa-angular/us/en/home/page-2/page-3.html",
                    "lastModified": 1589430413831,
                    "title": "Page 3"
                    }
                ],
                }
            ]
            }
        ],
    ":type": "wknd-spa-angular/components/header"
    

    AEM 페이지의 계층적 특성은 탐색 메뉴를 채우는 데 사용할 수 있는 JSON에서 모델링됩니다. 다음 사항을 기억하십시오. Header 구성 요소는 의 모든 기능을 상속합니다. 탐색 핵심 구성 요소 그리고 JSON을 통해 노출된 콘텐츠는 자동으로 Angular에 매핑됩니다 @Input 주석.

  2. 새 터미널 창을 열고 다음으로 이동 ui.frontend SPA 프로젝트 폴더 새로 만들기 NavigationComponent angular CLI 툴 사용:

    code language-shell
    $ cd ui.frontend
    $ ng generate component components/navigation
    CREATE src/app/components/navigation/navigation.component.scss (0 bytes)
    CREATE src/app/components/navigation/navigation.component.html (25 bytes)
    CREATE src/app/components/navigation/navigation.component.spec.ts (656 bytes)
    CREATE src/app/components/navigation/navigation.component.ts (286 bytes)
    UPDATE src/app/app.module.ts (2032 bytes)
    
  3. 다음으로 이름이 인 클래스를 만듭니다. NavigationLink 새로 생성된 시스템에서 Angular CLI 사용 components/navigation 디렉터리:

    code language-shell
    $ cd src/app/components/navigation/
    $ ng generate class NavigationLink
    CREATE src/app/components/navigation/navigation-link.spec.ts (187 bytes)
    CREATE src/app/components/navigation/navigation-link.ts (32 bytes)
    
  4. 선택한 IDE로 돌아가서 다음 위치에서 파일을 엽니다. navigation-link.ts 위치: /src/app/components/navigation/navigation-link.ts.

    navigation-link.ts 파일 열기

  5. 채우기 navigation-link.ts 다음을 사용하여:

    code language-js
    export class NavigationLink {
    
        title: string;
        path: string;
        url: string;
        level: number;
        children: NavigationLink[];
        active: boolean;
    
        constructor(data) {
            this.path = data.path;
            this.title = data.title;
            this.url = data.url;
            this.level = data.level;
            this.active = data.active;
            this.children = data.children.map( item => {
                return new NavigationLink(item);
            });
        }
    }
    

    개별 탐색 링크를 나타내는 간단한 클래스입니다. 클래스 생성자에는 data AEM에서 전달된 JSON 개체입니다. 이 클래스는 NavigationComponentHeaderComponent 를 클릭하여 탐색 구조를 쉽게 채울 수 있습니다.

    데이터 변환은 수행되지 않습니다. 이 클래스는 주로 JSON 모델을 강하게 입력하도록 만들어집니다. 주의: this.children 다음과같이 입력됨: NavigationLink[] 및 생성자가 재귀적으로 새 NavigationLink 의 각 항목에 대한 개체 children 배열입니다. 에 대한 JSON 모델 회수 Header 계층 구조입니다.

  6. 파일 열기 navigation-link.spec.ts. 다음에 대한 테스트 파일입니다. NavigationLink 클래스. 다음과 같이 업데이트합니다.

    code language-js
    import { NavigationLink } from './navigation-link';
    
    describe('NavigationLink', () => {
        it('should create an instance', () => {
            const data = {
                children: [],
                level: 1,
                active: false,
                path: '/content/wknd-spa-angular/us/en/home/page-1',
                description: null,
                url: '/content/wknd-spa-angular/us/en/home/page-1.html',
                lastModified: 1589429385100,
                title: 'Page 1'
            };
            expect(new NavigationLink(data)).toBeTruthy();
        });
    });
    

    주의: const data 는 단일 링크에 대해 이전에 검사한 동일한 JSON 모델을 따릅니다. 이는 강력한 단위 테스트와는 거리가 멀지만 의 생성자를 테스트하는 것만으로도 충분합니다. NavigationLink.

  7. 파일 열기 navigation.component.ts. 다음과 같이 업데이트합니다.

    code language-js
    import { Component, OnInit, Input } from '@angular/core';
    import { NavigationLink } from './navigation-link';
    
    @Component({
    selector: 'app-navigation',
    templateUrl: './navigation.component.html',
    styleUrls: ['./navigation.component.scss']
    })
    export class NavigationComponent implements OnInit {
    
        @Input() items: object[];
    
        constructor() { }
    
        get navigationLinks(): NavigationLink[] {
    
            if (this.items && this.items.length > 0) {
                return this.items.map(item => {
                    return new NavigationLink(item);
                });
            }
    
            return null;
        }
    
        ngOnInit() {}
    
    }
    

    NavigationComponent 다음 예상: object[] 명명된 items AEM의 JSON 모델입니다. 이 클래스는 단일 메서드를 노출합니다 get navigationLinks() 배열 반환 NavigationLink 개체.

  8. 파일 열기 navigation.component.html 다음을 사용하여 업데이트합니다.

    code language-html
    <ul *ngIf="navigationLinks && navigationLinks.length > 0" class="navigation__group">
        <ng-container *ngTemplateOutlet="recursiveListTmpl; context:{ links: navigationLinks }"></ng-container>
    </ul>
    

    이렇게 하면 이니셜이 생성됩니다. <ul> 및 호출 get navigationLinks() 방법: 부터 navigation.component.ts. An <ng-container> 은(는) 이라는 템플릿을 호출하는 데 사용됩니다. recursiveListTmpl 를 전달합니다. navigationLinks 를 이라는 변수로 links.

    추가 recursiveListTmpl 다음:

    code language-html
    <ng-template #recursiveListTmpl let-links="links">
        <li *ngFor="let link of links" class="{{'navigation__item navigation__item--' + link.level}}">
            <a [routerLink]="link.url" class="navigation__item-link" [title]="link.title" [attr.aria-current]="link.active">
                {{link.title}}
            </a>
            <ul *ngIf="link.children && link.children.length > 0">
                <ng-container *ngTemplateOutlet="recursiveListTmpl; context:{ links: link.children }"></ng-container>
            </ul>
        </li>
    </ng-template>
    

    여기에서는 탐색 링크에 대한 나머지 렌더링이 구현됩니다. 변수는 link 은(는) 유형입니다. NavigationLink 및 해당 클래스에서 만든 모든 메서드/속성을 사용할 수 있습니다. [routerLink] 일반 대신 사용됨 href 특성. 이렇게 하면 전체 페이지를 새로 고치지 않고도 앱의 특정 경로에 연결할 수 있습니다.

    탐색의 재귀 부분도 다른 를 만들어 구현합니다 <ul> 현재 link 이(가) 비어 있지 않습니다. children 배열입니다.

  9. 업데이트 navigation.component.spec.ts 에 대한 지원을 추가하려면 RouterTestingModule:

    code language-diff
     ...
    + import { RouterTestingModule } from '@angular/router/testing';
     ...
     beforeEach(async(() => {
        TestBed.configureTestingModule({
    +   imports: [ RouterTestingModule ],
        declarations: [ NavigationComponent ]
        })
        .compileComponents();
     }));
     ...
    

    추가 RouterTestingModule 구성 요소가 을 사용하기 때문에 필요합니다. [routerLink].

  10. 업데이트 navigation.component.scss 기본 스타일을 추가하려면 NavigationComponent:

@import "~src/styles/variables";

$link-color: $black;
$link-hover-color: $white;
$link-background: $black;

:host-context {
    display: block;
    width: 100%;
}

.navigation__item {
    list-style: none;
}

.navigation__item-link {
    color: $link-color;
    font-size: $font-size-large;
    text-transform: uppercase;
    padding: $gutter-padding;
    display: flex;
    border-bottom: 1px solid $gray;

    &:hover {
        background: $link-background;
        color: $link-hover-color;
    }

}

헤더 구성 요소 업데이트

이제 NavigationComponent 이(가) 구현되었으므로 HeaderComponent 참조하려면 을(를) 업데이트해야 합니다.

  1. 터미널을 열고 다음으로 이동 ui.frontend SPA 프로젝트 내의 폴더입니다. 시작 webpack 개발 서버:

    code language-shell
    $ npm start
    
  2. 브라우저 탭을 열고 다음으로 이동 http://localhost:4200/.

    다음 webpack 개발 서버 는 AEM의 로컬 인스턴스에서 JSON 모델을 프록시하도록 구성해야 합니다(ui.frontend/proxy.conf.json). 이렇게 하면 자습서의 앞부분에서 AEM에서 만든 콘텐츠에 대해 직접 코드를 작성할 수 있습니다.

    메뉴 전환 작업

    다음 HeaderComponent 에는 이미 구현된 메뉴 전환 기능이 있습니다. 그런 다음 탐색 구성 요소를 추가합니다.

  3. 선택한 IDE로 돌아가서 파일을 엽니다. header.component.ts 위치: ui.frontend/src/app/components/header/header.component.ts.

  4. 업데이트 setHomePage() 하드 코딩된 문자열을 제거하고 AEM 구성 요소에 의해 전달된 동적 prop을 사용하는 방법:

    code language-js
    /* header.component.ts */
    import { NavigationLink } from '../navigation/navigation-link';
    ...
     setHomePage() {
        if (this.hasNavigation) {
            const rootNavigationLink: NavigationLink = new NavigationLink(this.items[0]);
            this.isHome = rootNavigationLink.path === this.route.snapshot.data.path;
            this.homePageUrl = rootNavigationLink.url;
        }
    }
    ...
    

    의 새 인스턴스 NavigationLink 을(를) 기반으로 함 items[0]: AEM에서 전달된 탐색 JSON 모델의 루트입니다. this.route.snapshot.data.path 현재 Angular 경로의 경로를 반환합니다. 이 값은 현재 경로가 홈 페이지. this.homePageUrl 에서 앵커 링크를 채우는 데 사용됩니다. 로고.

  5. 열기 header.component.html 탐색에 대한 정적 자리 표시자를 새로 만든 참조에 대한 참조로 바꿉니다 NavigationComponent:

    code language-diff
        <div class="header-navigation">
            <div class="navigation">
    -            Navigation Placeholder
    +           <app-navigation [items]="items"></app-navigation>
            </div>
        </div>
    

    [items]=items 속성은 를 전달합니다. @Input() items 다음에서 HeaderComponent (으)로 NavigationComponent 탐색을 작성할 위치입니다.

  6. 열기 header.component.spec.ts 및에 대한 선언을 추가합니다. NavigationComponent:

    code language-diff
        /* header.component.spect.ts */
    +   import { NavigationComponent } from '../navigation/navigation.component';
    
        describe('HeaderComponent', () => {
        let component: HeaderComponent;
        let fixture: ComponentFixture<HeaderComponent>;
    
        beforeEach(async(() => {
            TestBed.configureTestingModule({
            imports: [ RouterTestingModule ],
    +       declarations: [ HeaderComponent, NavigationComponent ]
            })
            .compileComponents();
        }));
    

    다음 이후 NavigationComponent 는 현재 의 일부로 사용됩니다. HeaderComponent 이는 테스트 베드의 일부로 선언될 필요가 있습니다.

  7. 열려 있는 파일에 변경 내용을 저장하고 webpack 개발 서버: http://localhost:4200/

    헤더 탐색 완료됨

    메뉴 전환을 클릭하여 탐색을 열면 채워진 탐색 링크가 표시됩니다. SPA의 다른 보기로 이동할 수 있어야 합니다.

SPA 라우팅 이해

탐색이 구현되었으므로 AEM에서 라우팅을 검사합니다.

  1. IDE에서 파일을 엽니다. app-routing.module.ts 위치: ui.frontend/src/app.

    code language-js
    /* app-routing.module.ts */
    import { AemPageDataResolver, AemPageRouteReuseStrategy } from '@adobe/cq-angular-editable-components';
    import { NgModule } from '@angular/core';
    import { RouteReuseStrategy, RouterModule, Routes, UrlMatchResult, UrlSegment } from '@angular/router';
    import { PageComponent } from './components/page/page.component';
    
    export function AemPageMatcher(url: UrlSegment[]): UrlMatchResult {
        if (url.length) {
            return {
                consumed: url,
                posParams: {
                    path: url[url.length - 1]
                }
            };
        }
    }
    
    const routes: Routes = [
        {
            matcher: AemPageMatcher,
            component: PageComponent,
            resolve: {
                path: AemPageDataResolver
            }
        }
    ];
    @NgModule({
        imports: [RouterModule.forRoot(routes)],
        exports: [RouterModule],
        providers: [
            AemPageDataResolver,
            {
            provide: RouteReuseStrategy,
            useClass: AemPageRouteReuseStrategy
            }
        ]
    })
    export class AppRoutingModule {}
    

    다음 routes: Routes = []; 배열은 Angular 구성 요소 매핑에 대한 경로 또는 탐색 경로를 정의합니다.

    AemPageMatcher 은(는) 사용자 정의 Angular 라우터입니다. UrlMatcher: 이 Angular 애플리케이션의 일부인 AEM의 페이지와 "유사"하는 모든 항목과 일치합니다.

    PageComponent 는 AEM의 페이지를 나타내며 일치하는 경로를 렌더링하는 데 사용되는 Angular 구성 요소입니다. 다음 PageComponent 은 자습서의 뒷부분에서 검토됩니다.

    AemPageDataResolverAEM SPA Editor JS SDK에서 제공하는 는 사용자 지정입니다 Angular 라우터 확인자 AEM.html 확장자를 포함하는 AEM의 경로인 경로 URL을 확장자가 없는 페이지 경로인 의 리소스 경로로 변환하는 데 사용됩니다.

    예를 들어 AemPageDataResolver 경로의 URL을 content/wknd-spa-angular/us/en/home.html 의 경로에 /content/wknd-spa-angular/us/en/home. JSON 모델 API의 경로를 기반으로 페이지의 콘텐츠를 확인하는 데 사용됩니다.

    AemPageRouteReuseStrategyAEM SPA Editor JS SDK에서 제공하는 는 사용자 지정입니다 RouteReuseStrategy 을 사용하면 PageComponent 길 건너편입니다. 그렇지 않으면 페이지 "B"로 이동할 때 페이지 "A"의 콘텐츠가 표시될 수 있습니다.

  2. 파일 열기 page.component.ts 위치: ui.frontend/src/app/components/page/.

    code language-js
    ...
    export class PageComponent {
        items;
        itemsOrder;
        path;
    
        constructor(
            private route: ActivatedRoute,
            private modelManagerService: ModelManagerService
        ) {
            this.modelManagerService
            .getData({ path: this.route.snapshot.data.path })
            .then(data => {
                this.path = data[Constants.PATH_PROP];
                this.items = data[Constants.ITEMS_PROP];
                this.itemsOrder = data[Constants.ITEMS_ORDER_PROP];
            });
        }
    }
    

    다음 PageComponent AEM에서 검색한 JSON을 처리하는 데 필요하며 경로를 렌더링하는 Angular 구성 요소로 사용됩니다.

    ActivatedRouteangular 라우터 모듈에서 제공하는 에는 이 Angular 페이지 구성 요소 인스턴스에 로드해야 하는 AEM 페이지의 JSON 콘텐츠를 나타내는 상태가 포함되어 있습니다.

    ModelManagerService를 통해 경로를 기반으로 JSON 데이터를 가져오고 데이터를 클래스 변수에 매핑합니다 path, items, itemsOrder. 그런 다음 로 전달됩니다. AEMPageComponent

  3. 파일 열기 page.component.html 위치: ui.frontend/src/app/components/page/

    code language-html
    <aem-page
        class="structure-page"
        [attr.data-cq-page-path]="path"
        [cqPath]="path"
        [cqItems]="items"
        [cqItemsOrder]="itemsOrder">
    </aem-page>
    

    aem-page 다음을 포함: AEMPageComponent. 변수 path, items, 및 itemsOrder 이(가)에 전달됩니다. AEMPageComponent. 다음 AemPageComponentSPA Editor JavaScript SDK를 통해 제공되는 는 이후 이 데이터를 반복하고 다음에 표시된 대로 JSON 데이터를 기반으로 Angular 구성 요소를 동적으로 인스턴스화합니다. 구성 요소 매핑 자습서.

    다음 PageComponent 은(는) 다음을 위한 프록시에 불과합니다. AEMPageComponent and it is AEMPageComponent 이는 JSON 모델을 Angular 구성 요소에 올바르게 매핑하기 위한 대규모 작업에 해당됩니다.

AEM의 SPA 라우팅 Inspect

  1. 터미널을 열고 webpack 개발 서버 시작하는 경우. 프로젝트의 루트로 이동한 다음 Maven 기술을 사용하여 프로젝트를 AEM에 배포합니다.

    code language-shell
    $ cd aem-guides-wknd-spa
    $ mvn clean install -PautoInstallSinglePackage
    
    note caution
    CAUTION
    angular 프로젝트에 매우 엄격한 린팅 규칙이 활성화되어 있습니다. Maven 빌드가 실패하면 오류를 확인하고 나열된 파일에서 Lint 오류가 발견되었습니다.. 링터에서 발견한 문제를 수정하고 Maven 명령을 다시 실행합니다.
  2. AEM에서 SPA 홈 페이지로 이동합니다. http://localhost:4502/content/wknd-spa-angular/us/en/home.html 브라우저의 개발자 도구를 엽니다. 아래 스크린샷은 Google Chrome 브라우저에서 캡처됩니다.

    페이지를 새로 고치면 다음에 대한 XHR 요청이 표시됩니다. /content/wknd-spa-angular/us/en.model.json, SPA 루트 자습서에서 이전에 만든 SPA Root 템플릿에 대한 계층 깊이 구성에 따라 세 개의 하위 페이지만 포함됩니다. 여기에는 포함되지 않습니다 페이지 3.

    초기 JSON 요청 - SPA 루트

  3. 개발자 도구를 연 상태에서 다음 위치로 이동 페이지 3:

    3페이지 탐색

    다음에 대한 새 XHR 요청이 수행되는지 확인합니다. /content/wknd-spa-angular/us/en/home/page-2/page-3.model.json

    페이지 3 XHR 요청

    AEM 모델 관리자는 페이지 3 JSON 콘텐츠를 사용할 수 없으며 자동으로 추가 XHR 요청을 트리거합니다.

  4. 다양한 탐색 링크를 사용하여 SPA 탐색을 계속합니다. 추가적인 XHR 요청이 수행되지 않으며 전체 페이지 새로 고침이 발생하지 않는지 확인합니다. 이렇게 하면 최종 사용자가 SPA을 빠르게 사용할 수 있으며 불필요한 요청을 다시 AEM으로 줄일 수 있습니다.

    탐색 구현

  5. 다음으로 직접 이동하여 딥링크 실험: http://localhost:4502/content/wknd-spa-angular/us/en/home/page-2.html. 브라우저의 뒤로 단추가 계속 작동하는지 확인하십시오.

축하합니다! congratulations

축하합니다. SPA Editor SDK를 사용하여 AEM Pages에 매핑함으로써 SPA의 여러 보기를 지원하는 방법에 대해 알아보았습니다. 동적 탐색은 Angular 라우팅을 사용하여 구현되었으며 Header 구성 요소.

에서 완성된 코드를 항상 볼 수 있습니다. GitHub 또는 분기로 전환하여 코드를 로컬에서 확인합니다. Angular/navigation-routing-solution.

다음 단계 next-steps

사용자 지정 구성 요소 만들기 - AEM SPA 편집기에서 사용할 사용자 지정 구성 요소를 만드는 방법을 알아봅니다. 작성자 대화 상자 및 Sling 모델을 개발하여 JSON 모델을 확장하여 사용자 지정 구성 요소를 채우는 방법에 대해 알아봅니다.

recommendation-more-help
e25b6834-e87f-4ff3-ba56-4cd16cdfdec4