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?

Sachith Rukshan
fonte
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

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

Robin Dijkhof
fonte
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 .

Burak Gök
fonte
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;
  }

}
Amrish Khan Sheik
fonte
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)

GideonMax
fonte
-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.

Vugar Abdullayev
fonte
Se fosse possível fazê-lo como eu gostaria, mas o plugin usado apenas fornece o HTMLElement
Sachith Rukshan