Como adicionar um componente a um elementref?


8

Eu quero adicionar um componente em um elementref como um filho e ter acesso a suas propriedades.

const element: HTMLElement = document.createElement('div');

element.innerHTML = // Component needs to be added here

// Need to have access to properties of the Component here

Adicionei um calendário completo ao meu projeto e, para a linha do tempo, preciso adicionar elementos de recursos personalizados. Para isso, só tenho acesso ao HTMLElement e alguns dados. Então, o que eu quero fazer é passar um componente inicializado para o HTMLElement.

No momento, minha única opção é escrever o html como string e passá-lo para o innerHTML. Existe uma opção melhor?


Você pode explicar mais?
— GaurangDhorda

Qual é a sua exigência? O que você quer fazer não é possível.
— Angular

Você pode dar uma alternativa é possível
— Sachith Rukshan 02/01


Tentei, mas não funcionou @Caro
— Sachith Rukshan

Respostas:


7

Em um dos meus projetos, consegui algo semelhante à sua exigência dessa maneira. Deixe-me saber se isso ajuda?

constructor(private componentFactoryResolver: ComponentFactoryResolver,
            private injector: Injector, 
            private appRef: ApplicationRef) {

  const componentFactory = this.componentFactoryResolver.resolveComponentFactory(DynamicComponent); // Your dynamic component will replace DynamicComponent

  const componentRef = componentFactory.create(this.injector);

  this.appRef.attachView(componentRef.hostView);  

  const domElem = (componentRef.hostView as EmbeddedViewRef<any>).rootNodes[0] as HTMLElement;

  const element: HTMLElement = document.createElement('div');
  element.appendChild(domElem); // Component needs to be added here
  document.body.appendChild(element);
}

Dessa forma, você terá referência ao seu componente dinâmico como componentRef


Obrigado pela resposta. Eu posso acessar a instância usando o componentRef. Direita?
— Sachith Rukshan 28/01

1
@SachithRukshan yes
— prabhatojha

4

Você pode usar o Renderer2

export class AppComponent { 
@ViewChild('addButton') 
  private animateThis: ElementRef;  
  constructor(private renderer: Renderer2) {}

  addBtn() {
    const button = this.renderer.createElement('button'); 
    const buttonText = this.renderer.createText('This is a button');
    this.renderer.appendChild(button, buttonText);
    this.renderer.appendChild(this.animateThis.nativeElement, button);
  }
}

Mais exemplos


Obrigado pela resposta, mas eu verifiquei esta solução antes. E isso não facilita as coisas. E y é melhor que HTMLElement
— Sachith Rukshan

1
É melhor porque agora o angular está ciente da alteração do DOM. Apenas anexá-lo ao DOM angular não o conhece.
— Robin Dijkhof 24/01

Qual é a vantagem exata disso?
— Sachith Rukshan 24/01

4
Eu literalmente acabei de explicar
— Robin Dijkhof 24/01

Eu já implementei os elementos internos do elemenrref e adicionei lógicas de negócios também. Então, o que eu preciso saber é se a adição do renderer2 tornará as coisas mais fáceis
— Sachith Rukshan

1

A documentação Angular diz

Elementos angulares são componentes angulares empacotados como elementos personalizados (também chamados de Web Components)

Assim, você pode criar o elemento que deseja adicionar usando

  1. document.createElement('elementName')se for um elemento personalizado autônomo ou
  2. document.createElement('baseElementName', {is: 'elementName'})se for um elemento interno personalizado .

Você pode inserir o elemento criado em um containerelemento, container.insertAdjacentElement(position, element)conforme explicado aqui .


Foi exatamente isso que fiz, mas o que quero saber é uma solução melhor. Por favor, leia a pergunta corretamente
— Sachith Rukshan

1
@SachithRukshan Eu acredito que isso é bem diferente dewriting the html as the string and passing it to the innerHTML
— Dane Brouwer

0
import { AfterContentInit, Component, ElementRef } from '@angular/core';

@Component({
    selector: 'app-root',
    template: `
    <h1>My App</h1>
    <pre>
      <code>{{ node }}</code>
    </pre>
  `
})
export class AppComponent implements AfterContentInit {
  node: string;

  constructor(private elementRef: ElementRef) { }

  ngAfterContentInit() {
    const tmp = document.createElement('div');
    const el = this.elementRef.nativeElement.cloneNode(true);

    tmp.appendChild(el);
    this.node = tmp.innerHTML;
  }

}

Descobri isso quando fiz algumas perseguições. Espero que você ache útil
— Amrish Khan Sheik

Oi Amrish, Obrigado por tentar ajudar. Pode explicar um pouco sobre como isso pode ajudar meu problema.
— Sachith Rukshan 27/01

@AmrishkhanSheik Olá, bem-vindo ao Stackoverflow. Quando você posta uma resposta, é recomendável fornecer uma explicação também. Apenas uma cerca de código não explica por que ou como isso é pertinente à resposta. Veja: Como escrevo uma boa resposta?
— Dane Brouwer

0

considerando que o componente está registrado em window.customElements
e , de acordo com a documentação do Angular, provavelmente,
você pode:

var element = document.createElement("div");

var comp= document.createElement("your-component")
/*
optionally set component attributes or anything else
you also have access to the component's properties here
comp.setAttribute("name",value)
console.log(comp.exampleProperty)
*/
element.appendChild(comp)


-1

O que você está tentando alcançar é impossível e contra as melhores práticas. Em vez disso, você deve mostrar esse componente com condições. Você pode criar variável em serviço e, com base nesse valor, o componente pode ser mostrado ou em loop.


Se fosse possível fazê-lo como eu gostaria, mas o plugin usado apenas fornece o HTMLElement
— Sachith Rukshan
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.