Qual fluxo de trabalho integrar o Polymer com o Angular?


Polímero. Sua promessa de permitir o desenvolvimento de bibliotecas de componentes de interface do usuário sem ficar preso a uma pilha técnica, contando com os recursos (futuros) do navegador. Basta escrever seus componentes e reutilizá-los em qualquer lugar com a garantia de não gerar efeitos colaterais. É desejável, não? Se você trabalha com várias tecnologias da web e deseja desenvolver um catálogo de componentes genéricos de interface do usuário, o Polymer pode parecer uma boa solução.
Veremos juntos como integrar um componente escrito com Polymer 2.0 em uma aplicação Angular.

Preâmbulo: Componentes de Polímero e Web

Se houvesse apenas uma coisa para lembrar:
Polímero != Componentes da Web
Os Web Components, que surgiram pela primeira vez em 2011, são um conjunto de 4 tecnologias para criar e usar elementos cujo estilo e código são encapsulados do restante da aplicação. Essas 4 tecnologias são baseadas nas especificações do W3C, algumas das quais já estão no status Living Standard.
Em 2013, os engenheiros do Google queriam tornar os Web Components acessíveis criando uma sobreposição para essas tecnologias. Seu objetivo é poder começar a escrever e usar Web Components sem esperar que as especificações sejam concluídas e implementadas em navegadores suficientes. Essa sobreposição, carinhosamente chamada de Polymer, estava destinada a ficar mais leve – ou até mesmo desaparecer – em proporção à cobertura do navegador.
Essas 4 tecnologias são:

Elementos personalizados

Estas são APIs JS para definir seus elementos HTML e seu comportamento associado. Após a chamada para CustomElementRegistry.define(), você pode usar a tag correspondente em seu HTML.
Eles também definem os retornos de chamada do ciclo de vida do elemento que o Polymer coleta.

A Sombra DOM

É isso que permitirá encapsular a estrutura HTML e o estilo do elemento, sem que o mundo externo possa interferir de forma descontrolada.
Polymer gerencia o Shadow DOM para nós, enquanto nos permite manipulá-lo

Modelos HTML

Este techno define dois elementos. <template>, que permite escrever HTML não renderizado que será copiado para os elementos que os utilizam. a <slot> nos permite escrever um espaço em nossa estrutura HTML onde os elementos filhos de nosso elemento serão inseridos.

Importações HTML

Se você escreveu seu Web Component em seu arquivo .html dedicado, uma maneira de usá-lo em seu aplicativo é importá-lo por meio de uma importação HTML:

<link rel="import" href="myfile.html">

Este techno é controverso e, em última análise, não será adotado pelo padrão. Segundo o Firefox, as ferramentas atuais e futuras (Módulo ES6) são suficientes e oferecem mais controle do que o HTML Import.

Adições de polímeros

Além de fazer essas 4 tecnologias funcionarem em todos os navegadores, você encontrará na caixa de ferramentas Polymer algo para facilitar o desenvolvimento de Web Components:
– Auxiliar para declarar as propriedades do nosso componente (valor padrão, somente leitura, calculado, função observadora, desserialização automática)
– Gerenciamento de eventos (assinatura e cancelamento automáticos, eventos gestuais para usuários móveis)
– Gerenciamento de dados, com vinculação de dados bidirecional
– Elementos personalizados equivalentes a ngIf e ngFor de Angular
– e vários utilitários, como um debouncer, para evitar chamar um retorno de chamada em um intervalo muito curto
Além dessas funcionalidades básicas, o Polymer oferece soluções para o desenvolvimento de aplicações completas (gerenciamento de rotas, internacionalização, gerenciamento offline), pouco úteis por já serem gerenciadas pela Angular.

e angular?

O Angular começou depois do Polymer, em setembro de 2014. Mas, ao contrário do Polymer, os componentes do Angular não são Web Components. Eles usam técnicas específicas para isso, como uma emulação do shadow dom (que também pode ser ativado nativamente) para o encapsulamento do estilo, mas você não pode usar um componente Angular em um ambiente diferente do Angular.

Integração angular e polímero

Para ilustrar essa integração, veremos duas formas: uma simples e rápida, conveniente para testes, e outra mais adequada para um ambiente de produção.
De qualquer forma, você vai precisar de caramanchão.

O caminho fácil

Neste caso, os elementos alfandegários serão desenvolvidos localmente, relacionados ao projeto Angular. Os elementos são importados para o index.html.

  1. Na raiz do seu projeto, inicialize o bower com
$ bower init

Solicitações imediatas não são interessantes porque não publicaremos via bower. Nosso uso será limitado ao gerenciamento de dependências do Polymer.

  1. Ainda na raiz, crie um arquivo .bowerrc com este conteúdo:
{
  "directory": "src/assets/bower_components/"
}

onde assets corresponde ao seu diretório de ativos Angular.

  1. em .gitignore, adicione o mesmo caminho que o directory du .bowerrc.

Para o exemplo, usaremos elementos desenvolvidos pela equipe Polymer.

  1. Instale os itens paper-slider et paper-card
$ bower install --save PolymerElements/paper-slider PolymerElements/paper-card
  1. Adicione suas dependências no index.html.
<head>
  <link rel="import" href="assets/bower_components/paper-card/paper-card.html">
  <link rel="import" href="assets/bower_components/paper-slider/paper-slider.html">
</head>
<body>
  <app-root></app-root>
</body>
  1. Para poder usar seus novos elementos, você deve autorizar tags desconhecidas para o Angular. Em cada módulo declarando componentes usando elementos personalizados, você deve aplicar o valor CUSTOM_ELEMENTS_SCHEMA para a propriedade schemas :
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from "@angular/core";
@NgModule({
  declarations: [AppComponent],
  bootstrap: [AppComponent],
  schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class AppModule {}

E lá vai você! Se você deseja desenvolver seus WebComponents localmente, coloque-os em uma pastaassets. Não use polímero-cli, que gerará tudo o que você precisa publicar e entrará em conflito com coisas em bower_components.
Em seu HTML definindo seu WebComponent, você poderá importar o Polymer recuperado após instalar os elementos do bower:

<link rel="import" href="../bower_components/polymer/polymer.html">

A maneira certa de produzir

Em vez de carregar todos os seus componentes no ponto de entrada do seu aplicativo, você os importará para seus componentes Angular no lado do TypeScript. Eles serão incorporados no bloco correspondente ao módulo do seu componente, o que é interessante quando você carrega seus módulos com preguiça. Assim, você reduz bastante a carga inicial.
Isso é possível graças ao projeto Carregador de Webpack de Polímero que transformará suas definições de elementos HTML em um pacote JS.
Operação PolymerWebackLoader
Isso é bom, o Webpack já está presente e configurado via Angular CLI. Você pode corrigir a configuração gerada pela CLI usando Origami (Polymer + Angular) e ver um exemplo de uso com isso kit iniciante.
Tenha cuidado, porém, se seus elementos hospedarem imagens, você terá que alterar a maneira como eles são usados. Ou movendo as imagens para a pasta de ativos do Angular para que o importPath de Polymer corresponde, seja referindo-se a ele por meio de uma variável:

const img = require('./checked.png');

para que a imagem seja incluída no pacote.

Integração com formulários Angular

Para integrar um elemento Polymer em uma forma Angular, você deve garantir que eles falem o mesmo idioma!
Usando a diretiva ngDefaultControl no seu componente, você garante que o Angular levará os eventos em consideração input emitido pelo seu componente. Ou seja, quando você quer o valor do FormControl Angular é atualizado pelo elemento Polymer, você precisará emitir um evento input. Por exemplo, para um campo de texto, input pode ser emitido após cada pressionamento de tecla.

class DemoElem extends Polymer.Element {
  static get is() { return 'demo-elem'; }
  static get properties() {
    return {
      value: {
        type: String
      }
    };
  }
  notifyChange() {
    this.dispatchEvent(new CustomEvent('input'));
  }
}

Então Angular irá recuperar o valor atual através da propriedade value do componente.
Se você estiver usando um WebComponent obtido que não emite input, você pode passar por uma diretiva que implementará ControlValueAccessor. A equipe Angular desenvolveu uma boa quantidade deles (aqui) que podemos usar como modelo se não encontrarmos o que procuramos. É aqui que você pode ouvir o evento do componente e interpretar o resultado antes de passá-lo para o formulário Angular e vice-versa quando o formulário Angular deseja definir um valor para esse controle.
Você pode encontrar um exemplo de implementação no repositório de programa demonstrativo.
Normalmente, a validação de um controle é sempre feita no lado Angular, via Validators. Angular pode dizer a um WebComponent que ele é inválido por meio de vinculação de dados. É gerenciado pelos WebComponents desenvolvidos pela equipe Polymer que oferece uma propriedade invalid et error-message. Em alguns casos complexos, você pode querer gerenciar a validade no componente (para ter melhor controle sobre a formatação, por exemplo). Para tornar o Angular ciente da invalidade desse componente, em vez de duplicar o código de validação, você pode capturar um evento gerado pelo componente para indicar que seu estado de validade foi alterado.

Conclusão: O Futuro dos Componentes Web com Angular

Vimos que a integração do Polymer 2.0 no Angular pode complicar o fluxo de trabalho (principalmente se for um controle de formulário). Com o Polymer 3.0, passaremos do Bower para o NPM e do HTML Import para os módulos ES6, tornando necessária a etapa de construção. Como alternativa, a Angular está desenvolvendo Angular Elements, que nos permitirá exportar nossos componentes Angular para Web Components que podem ser usados ​​em qualquer lugar! No futuro, acho que, portanto, haverá menos interesse em usar o Polymer além do Angular, se ambos permitirem o máximo de reutilização… Será uma questão de gosto!
Projeto de demonstração do Github
Thibault Chevrin, JS-Artesão @JS-República