Adicionar navegação e roteamento

Saiba como várias exibições no SPA são suportadas com as Páginas do AEM e o SDK do Editor do SPA. A navegação dinâmica é implementada usando rotas Angulares e adicionada a um componente Cabeçalho existente.

Objetivo

  1. Entenda as opções de roteamento do modelo SPA disponíveis ao usar o Editor SPA.
  2. Saiba como usar Roteamento Angular para navegar entre diferentes visualizações do SPA.
  3. Implemente uma navegação dinâmica orientada pela hierarquia de página do AEM.

O que você vai criar

Este capítulo adiciona um menu de navegação a um componente Header existente. O menu de navegação é orientado pela hierarquia de página do AEM e usa o modelo JSON fornecido pelo Componente principal de navegação.

Navegação implementada

Pré-requisitos

Revise as ferramentas e instruções necessárias para configurar um ambiente de desenvolvimento local.

Obter o código

  1. Baixe o ponto de partida para este tutorial via Git:

    $ git clone git@github.com:adobe/aem-guides-wknd-spa.git
    $ cd aem-guides-wknd-spa
    $ git checkout Angular/navigation-routing-start
    
  2. Implante a base de código em uma instância do AEM local usando o Maven:

    $ mvn clean install -PautoInstallSinglePackage
    

    Se estiver usando AEM 6.x adicione o perfil classic:

    $ mvn clean install -PautoInstallSinglePackage -Pclassic
    
  3. Instale o pacote concluído para o site de referência tradicional WKND. As imagens fornecidas pelo site de referência WKND serão reutilizadas no SPA da WKND. O pacote pode ser instalado usando o Gerenciador de Pacotes do AEM.

    O Gerenciador de Pacotes instala o wknd.all

Você sempre pode visualizar o código concluído em GitHub ou verificar o código localmente ao alternar para a ramificação Angular/navigation-routing-solution.

Inspecionar atualizações de HeaderComponent

Em capítulos anteriores, o componente HeaderComponent era adicionado como um componente Angular puro incluído por meio de app.component.html. Neste capítulo, o componente HeaderComponent é removido do aplicativo e será adicionado por meio do Editor de modelo. Isso permite que os usuários configurem o menu de navegação do HeaderComponent de dentro do AEM.

OBSERVAÇÃO

Várias atualizações de CSS e JavaScript já foram feitas na base de código para iniciar este capítulo. Para se concentrar nos conceitos principais, não todas das alterações de código são discutidas. Você pode visualizar as alterações completas aqui.

  1. No IDE de sua escolha, abra o projeto inicial do SPA para este capítulo.

  2. Abaixo do módulo ui.frontend inspecione o arquivo header.component.ts em: ui.frontend/src/app/components/header/header.component.ts.

    Várias atualizações foram feitas, incluindo a adição de um HeaderEditConfig e um MapTo para permitir que o componente seja mapeado para um componente do AEM wknd-spa-angular/components/header.

    /* 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);
    

    Observe a anotação @Input() para items. items conterá uma matriz de objetos de navegação passados do AEM.

  3. No módulo ui.apps inspecione a definição do componente do AEM Header: ui.apps/src/main/content/jcr_root/apps/wknd-spa-angular/components/header/.content.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"/>
    

    O componente Header do AEM herdará toda a funcionalidade do Componente principal de navegação através da propriedade sling:resourceSuperType.

Adicionar o HeaderComponent ao modelo SPA

  1. Abra um navegador e faça logon no AEM, http://localhost:4502/. A base de código inicial já deve ser implantada.

  2. Navegue até Modelo de Página SPA: http://localhost:4502/editor.html/conf/wknd-spa-angular/settings/wcm/templates/spa-page-template/structure.html.

  3. Selecione o Contêiner de layout raiz mais externo e clique no ícone Política. Tenha cuidado e não para selecionar o Contêiner de layout desbloqueado para criação.

    Selecione o ícone de política do contêiner de layout de raiz

  4. Copie a política atual e crie uma nova política chamada Estrutura do SPA:

    Política de Estrutura do SPA

    Em Componentes permitidos > Geral > selecione o componente Contêiner de layout.

    Em Componentes permitidos > WKND SPA ANGULAR - ESTRUTURA > selecione o componente Cabeçalho:

    Selecionar componente do cabeçalho

    Em Componentes permitidos > WKND SPA ANGULAR - Content > selecione os componentes Image e Text. Você deve ter quatro componentes totais selecionados.

    Clique em Concluído para salvar as alterações.

  5. Atualize a página. Adicione o componente Cabeçalho acima do Contêiner de layout desbloqueado:

    adicionar componente Cabeçalho ao modelo

  6. Selecione o componente Cabeçalho e clique no ícone Política para editar a política.

    Clique na política Cabeçalho

  7. Crie uma nova política com um Título da Política de "Cabeçalho SPA WKND".

    Em Propriedades:

    • Defina Raiz de navegação para /content/wknd-spa-angular/us/en.
    • Defina Excluir níveis de raiz para 1.
    • Desmarque Coletar todas as páginas secundárias.
    • Defina Profundidade da estrutura de navegação para 3.

    Configurar política de cabeçalho

    Isso coletará os 2 níveis de navegação abaixo de /content/wknd-spa-angular/us/en.

  8. Depois de salvar suas alterações, você deve ver o Header preenchido como parte do modelo:

    Componente de cabeçalho preenchido

Criar páginas secundárias

Em seguida, crie páginas adicionais no AEM que servirão como diferentes exibições no SPA. Também verificaremos a estrutura hierárquica do modelo JSON fornecido pelo AEM.

  1. Navegue até o console Sites: http://localhost:4502/sites.html/content/wknd-spa-angular/us/en/home. Selecione a Página Inicial Angular de SPA WKND e clique em Criar > Página:

    Criar nova página

  2. Em Modelo selecione Página SPA. Em Propriedades, digite "Página 1" para o Título e "página-1" como o nome.

    Insira as propriedades da página inicial

    Clique em Criar e, na janela pop-up, clique em Abrir para abrir a página no Editor de SPA do AEM.

  3. Adicione um novo componente Text ao Contêiner de layout principal. Edite o componente e insira o texto: "Página 1" usando o RTE e o elemento H1 (você terá que entrar no modo de tela cheia para alterar os elementos de parágrafo)

    Exemplo de página de conteúdo 1

    Você pode adicionar conteúdo adicional, como uma imagem.

  4. Retorne ao console Sites do AEM e repita as etapas acima, criando uma segunda página chamada "Página 2" como um irmão da Página 1. Adicione conteúdo a Página 2 para que seja facilmente identificado.

  5. Por fim, crie uma terceira página, "Page 3", mas como child de Page 2. Depois de concluída, a hierarquia do site deve ser semelhante ao seguinte:

    Hierarquia de site de exemplo

  6. Em uma nova guia, abra a API do modelo JSON fornecida pelo AEM: http://localhost:4502/content/wknd-spa-angular/us/en.model.json. Esse conteúdo JSON é solicitado quando o SPA é carregado pela primeira vez. A estrutura externa tem a seguinte aparência:

    {
    "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": {}
        }
    }
    

    Em :children você deve ver uma entrada para cada uma das páginas criadas. O conteúdo de todas as páginas está nesta solicitação JSON inicial. Depois que o roteamento de navegação for implementado, as exibições subsequentes do SPA serão carregadas rapidamente, já que o conteúdo já está disponível no lado do cliente.

    Não é recomendável carregar ALL do conteúdo de um SPA na solicitação JSON inicial, pois isso atrasaria o carregamento da página inicial. Em seguida, vamos examinar como a profundidade da hierarquia das páginas é coletada.

  7. Navegue até o modelo Raiz do SPA em: http://localhost:4502/editor.html/conf/wknd-spa-angular/settings/wcm/templates/spa-app-template/structure.html.

    Clique no menu Propriedades da página > Política da página:

    Abra a política de página para a Raiz do SPA

  8. O modelo Raiz do SPA tem uma guia Estrutura Hierárquica extra para controlar o conteúdo JSON coletado. A Profundidade da estrutura determina o quão profundo na hierarquia do site é coletar páginas secundárias abaixo de root. Também é possível usar o campo Structure Patterns para filtrar páginas adicionais com base em uma expressão regular.

    Atualize a Profundidade da estrutura para "2":

    Atualizar profundidade da estrutura

    Clique em Concluído para salvar as alterações na política.

  9. Abra novamente o modelo JSON http://localhost:4502/content/wknd-spa-angular/us/en.model.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": {}
        }
    }
    

    Observe que o caminho Page 3 foi removido: /content/wknd-spa-angular/us/en/home/page-2/page-3 do modelo JSON inicial.

    Posteriormente, observaremos como o SDK do Editor SPA do AEM pode carregar dinamicamente conteúdo adicional.

Implementar a navegação

Em seguida, implemente o menu de navegação com um novo NavigationComponent. Podemos adicionar o código diretamente em header.component.html, mas uma prática melhor é evitar componentes grandes. Em vez disso, implemente um NavigationComponent que possa ser reutilizado posteriormente.

  1. Revise o JSON exposto pelo componente Header do AEM em http://localhost:4502/content/wknd-spa-angular/us/en.model.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"
    

    A natureza hierárquica das páginas do AEM é modelada no JSON que pode ser usado para preencher um menu de navegação. Lembre-se de que o componente Header herda toda a funcionalidade do Componente principal de navegação e que o conteúdo exposto por meio do JSON será mapeado automaticamente para a anotação Angular @Input.

  2. Abra uma nova janela de terminal e navegue até a pasta ui.frontend do projeto SPA. Crie um novo NavigationComponent usando a ferramenta de CLI Angular:

    $ 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. Em seguida, crie uma classe chamada NavigationLink usando a CLI Angular no diretório recém-criado components/navigation:

    $ 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. Retorne ao IDE de sua escolha e abra o arquivo em navigation-link.ts em /src/app/components/navigation/navigation-link.ts.

    Abrir arquivo navigation-link.ts

  5. Preencha navigation-link.ts com o seguinte:

    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);
            });
        }
    }
    

    Esta é uma classe simples para representar um link de navegação individual. No construtor de classe, esperamos que data seja o objeto JSON passado do AEM. Essa classe será usada dentro de NavigationComponent e HeaderComponent para preencher facilmente a estrutura de navegação.

    Nenhuma transformação de dados é executada, essa classe é criada primariamente para digitar fortemente o modelo JSON. Observe que this.children é digitado como NavigationLink[] e que o construtor cria recursivamente novos objetos NavigationLink para cada um dos itens na matriz children. Lembre-se de que o modelo JSON para Header é hierárquico.

  6. Abra o arquivo navigation-link.spec.ts. Este é o arquivo de teste para a classe NavigationLink. Atualize com o seguinte:

    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();
        });
    });
    

    Observe que const data segue o mesmo modelo JSON inspecionado anteriormente para um único link. Isso está longe de ser um teste de unidade robusto, no entanto, deve ser suficiente testar o construtor de NavigationLink.

  7. Abra o arquivo navigation.component.ts. Atualize com o seguinte:

    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 O espera um object[] nomeado items que seja o modelo JSON do AEM. Essa classe expõe um único método get navigationLinks() que retorna uma matriz de objetos NavigationLink.

  8. Abra o arquivo navigation.component.html e atualize-o com o seguinte:

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

    Isso gera um <ul> inicial e chama o método get navigationLinks() de navigation.component.ts. Um <ng-container> é usado para fazer uma chamada para um template chamado recursiveListTmpl e o transmite como navigationLinks como uma variável chamada links.

    Adicione o recursiveListTmpl próximo:

    <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>
    

    Aqui, o restante da renderização do link de navegação é implementado. Observe que a variável link é do tipo NavigationLink e todos os métodos/propriedades criados por essa classe estão disponíveis. [routerLink] é usado em vez do href atributo normal. Isso nos permite vincular a rotas específicas no aplicativo, sem uma atualização de página inteira.

    A parte recursiva da navegação também é implementada pela criação de outro <ul> se o link atual tiver uma matriz children não vazia.

  9. Atualize navigation.component.spec.ts para adicionar suporte para RouterTestingModule:

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

    É necessário adicionar o RouterTestingModule porque o componente usa [routerLink].

  10. Atualize navigation.component.scss para adicionar alguns estilos básicos ao 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;
    }

}

Atualizar o componente de cabeçalho

Agora que NavigationComponent foi implementado, o HeaderComponent deve ser atualizado para referenciá-lo.

  1. Abra um terminal e navegue até a pasta ui.frontend no projeto do SPA. Inicie o servidor de desenvolvimento do webpack:

    $ npm start
    
  2. Abra uma guia do navegador e navegue até http://localhost:4200/.

    O servidor de desenvolvimento de webpack deve ser configurado para proxy do modelo JSON de uma instância local do AEM (ui.frontend/proxy.conf.json). Isso nos permitirá codificar diretamente no conteúdo criado no AEM da parte anterior do tutorial.

    alternância de menu funcionando

    O HeaderComponent atualmente possui a funcionalidade de alternância de menu já implementada. Em seguida, adicione o componente de navegação.

  3. Retorne ao IDE de sua escolha e abra o arquivo header.component.ts em ui.frontend/src/app/components/header/header.component.ts.

  4. Atualize o método setHomePage() para remover a String codificada e use as props dinâmicas passadas pelo componente AEM:

    /* 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;
        }
    }
    ...
    

    Uma nova instância de NavigationLink é criada com base em items[0], a raiz do modelo JSON de navegação passado do AEM. this.route.snapshot.data.path retorna o caminho da rota Angular atual. Esse valor é usado para determinar se a rota atual é a Home Page. this.homePageUrl é usada para preencher o link de âncora no logotipo.

  5. Abra header.component.html e substitua o espaço reservado estático para a navegação por uma referência para o NavigationComponent recém-criado:

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

    [items]=items transmite o @Input() items do HeaderComponent para o NavigationComponent local em que criará a navegação.

  6. Abra header.component.spec.ts e adicione uma declaração para NavigationComponent:

        /* 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();
        }));
    

    Como o NavigationComponent agora é usado como parte do HeaderComponent, ele precisa ser declarado como parte da base de teste.

  7. Salve as alterações em qualquer arquivo aberto e retorne ao servidor dev do webpack: http://localhost:4200/

    Navegação de cabeçalho concluída

    Abra a navegação clicando no botão de alternância do menu e você deverá ver os links de navegação preenchidos. É possível navegar para diferentes exibições do SPA.

Entender o roteamento SPA

Agora que a navegação foi implementada, inspecione o roteamento no AEM.

  1. No IDE, abra o arquivo app-routing.module.ts em ui.frontend/src/app.

    /* 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 {}
    

    A matriz routes: Routes = []; define as rotas ou os caminhos de navegação para os mapeamentos de componentes Angulares.

    AemPageMatcher é um roteador Angular personalizado UrlMatcher, que corresponde a qualquer coisa que "pareça" com uma página no AEM que faz parte deste aplicativo Angular.

    PageComponent é o Componente Angular que representa uma Página no AEM, e as rotas correspondentes serão chamadas. O PageComponent será inspecionado posteriormente.

    AemPageDataResolver, fornecido pelo SDK JS do Editor SPA do AEM, é um Resolvedor de Roteador Angular personalizado usado para transformar o URL da rota, que é o caminho no AEM incluindo a extensão .html, para o caminho do recurso no AEM, que é o caminho da página menos a extensão.

    Por exemplo, o AemPageDataResolver transforma o URL de uma rota de content/wknd-spa-angular/us/en/home.html em um caminho de /content/wknd-spa-angular/us/en/home. Isso é usado para resolver o conteúdo da página com base no caminho na API do modelo JSON.

    AemPageRouteReuseStrategy, fornecido pelo SDK JS do Editor do SPA do AEM, é uma 🔗 RouteReuseStrategy personalizada que impede a reutilização de PageComponent várias rotas. Caso contrário, o conteúdo da página "A" pode ser exibido ao navegar até a página "B".

  2. Abra o arquivo page.component.ts em ui.frontend/src/app/components/page/.

    ...
    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];
            });
        }
    }
    

    O PageComponent é necessário para processar o JSON recuperado do AEM e é usado como o componente Angular para renderizar as rotas.

    ActivatedRoute, que é fornecido pelo módulo Roteador Angular, contém o estado que indica qual conteúdo JSON da Página do AEM deve ser carregado nesta instância do componente Página Angular.

    ModelManagerService, obtém os dados JSON com base na rota e mapeia os dados para variáveis de classe path, items, itemsOrder. Eles serão passados para o AEMPageComponent

  3. Abra o arquivo page.component.html em ui.frontend/src/app/components/page/

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

    aem-page inclui o AEMPageComponent. As variáveis path, items e itemsOrder são passadas para AEMPageComponent. O AemPageComponent, fornecido por meio dos SDKs do JavaScript do Editor do SPA, iterará sobre esses dados e instanciará dinamicamente os componentes Angulares com base nos dados JSON, conforme visto no Tutorial Mapear componentes.

    O PageComponent é realmente apenas um proxy para o AEMPageComponent e é o AEMPageComponent que faz a maioria do trabalho pesado para mapear corretamente o modelo JSON para os componentes Angulares.

Inspecionar o roteamento SPA no AEM

  1. Abra um terminal e pare o servidor dev do webpack, se iniciado. Navegue até a raiz do projeto e implante o projeto no AEM usando suas habilidades Maven:

    $ cd aem-guides-wknd-spa
    $ mvn clean install -PautoInstallSinglePackage
    
    CUIDADO

    O projeto Angular tem algumas regras de impressão muito restritas ativadas. Se a build Maven falhar, verifique o erro e procure por Lint errors encontrados nos arquivos listados.. Corrija quaisquer problemas encontrados pelo link e execute novamente o comando Maven.

  2. Navegue até a página inicial do SPA no AEM: http://localhost:4502/content/wknd-spa-angular/us/en/home.html e abra as ferramentas de desenvolvedor do seu navegador. As capturas de tela abaixo são capturadas pelo navegador Google Chrome.

    Atualize a página e você deve ver uma solicitação XHR para /content/wknd-spa-angular/us/en.model.json, que é a Raiz do SPA. Observe que apenas três páginas filhas são incluídas com base na configuração de profundidade da hierarquia para o modelo de Raiz do SPA feito anteriormente no tutorial. Isso não inclui Página 3.

    Solicitação JSON inicial - Raiz do SPA

  3. Com as ferramentas do desenvolvedor abertas, navegue até Página 3:

    Página 3: Navegar

    Observe que uma nova solicitação de XHR é feita para: /content/wknd-spa-angular/us/en/home/page-2/page-3.model.json

    Página três Solicitação XHR

    O Gerenciador de modelos do AEM entende que o conteúdo JSON da Página 3 não está disponível e aciona automaticamente a solicitação XHR adicional.

  4. Continue navegando no SPA usando os vários links de navegação. Observe que nenhuma solicitação XHR adicional é feita e que nenhuma atualização de página completa ocorre. Isso torna o SPA rápido para o usuário final e reduz solicitações desnecessárias de volta para o AEM.

    Navegação implementada

  5. Experimente com deep links navegando diretamente para: http://localhost:4502/content/wknd-spa-angular/us/en/home/page-2.html. Observe que o botão Voltar do navegador continua funcionando.

Parabéns!

Parabéns, você aprendeu como várias exibições no SPA podem ser suportadas com o mapeamento para páginas do AEM com o SDK do Editor do SPA. A navegação dinâmica foi implementada usando o roteamento Angular e adicionada ao componente Header.

Você sempre pode visualizar o código concluído em GitHub ou verificar o código localmente ao alternar para a ramificação Angular/navigation-routing-solution.

Próximas etapas

Criar um componente personalizado - saiba como criar um componente personalizado a ser usado com o Editor de SPA do AEM. Saiba como desenvolver caixas de diálogo do autor e Modelos do Sling para estender o modelo JSON para preencher um componente personalizado.

Nesta página

Adobe Maker Awards Banner

Time to shine!

Apply now for the 2021 Adobe Experience Maker Awards.

Apply now
Adobe Maker Awards Banner

Time to shine!

Apply now for the 2021 Adobe Experience Maker Awards.

Apply now