¿Cómo agregar un componente en un elementref?

8

Quiero agregar un componente en un elementref como hijo y tener acceso a sus propiedades.

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

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

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

He agregado un calendario completo a mi proyecto y para la línea de tiempo necesito agregar elementos de recursos personalizados. Para esto solo tengo acceso al elemento HTMLE y algunos datos. Entonces, lo que quiero hacer es pasar un componente inicializado al elemento HTMLE.

En este momento, mi única opción es escribir el html como la cadena y pasarlo al innerHTML. ¿Hay alguna opción mejor?

Sachith Rukshan
fuente
¿Puedes explicarme mas?
GaurangDhorda
¿Cuál es su requerimiento? Lo que quieres hacer no es posible.
Angular
¿Puede dar una alternativa posible?
Sachith Rukshan
Probé pero no funcionó @Caro
Sachith Rukshan

Respuestas:

8

En uno de mis proyectos, logré algo similar a su requerimiento de esta manera. Avísame si te ayuda

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

De esta manera tendrá referencia a su componente dinámico como componentRef

prabhatojha
fuente
Gracias por la respuesta. Puedo acceder a la instancia usando el componentRef. ¿Derecha?
Sachith Rukshan
1
@SachithRukshan sí
prabhatojha
4

Es posible que pueda usar 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);
  }
}

Más ejemplos

Robin Dijkhof
fuente
Gracias por la respuesta, pero he comprobado esta solución antes. Y no lo hace más fácil. Y es mejor que HTMLElement
Sachith Rukshan
1
Es mejor porque ahora angular está al tanto del cambio DOM. Simplemente agregándolo al DOM angular no es consciente de ello.
Robin Dijkhof
¿Cuál es la ventaja exacta de esto?
Sachith Rukshan
44
Literalmente acabo de explicar
Robin Dijkhof
Ya he implementado los elementos internos de elemenrref y también he agregado lógicas comerciales, así que lo que necesito saber es si agregar renderer2 lo hará más fácil
Sachith Rukshan
1

La documentación angular dice

Los elementos angulares son componentes angulares empaquetados como elementos personalizados (también llamados componentes web)

Por lo tanto, puede crear el elemento que desea agregar usando

  1. document.createElement('elementName')si es un elemento personalizado autónomo , o
  2. document.createElement('baseElementName', {is: 'elementName'})si es un elemento incorporado personalizado .

Puede insertar el elemento que creó en un containerelemento utilizando container.insertAdjacentElement(position, element)como se explica aquí .

Burak Gök
fuente
Eso fue exactamente lo que hice, pero lo que quiero saber es una mejor solución. Lea la pregunta correctamente
Sachith Rukshan
1
@SachithRukshan Creo que esto es muy diferente awriting 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
fuente
Encontré esto cuando hice algunos dogging. Espero que les sea útil
Amrish khan Sheik
Hola Amrish, gracias por intentar ayudar. Puedo explicar un poco sobre cómo podría ayudar a mi problema.
Sachith Rukshan
@AmrishkhanSheik Hola, bienvenido a Stackoverflow. Cuando publica una respuesta, se recomienda que también proporcione una explicación. Solo una cerca de código no explica por qué o cómo esto es pertinente a la respuesta. Ver: ¿Cómo escribo una buena respuesta?
Dane Brouwer
0

dado que el componente está registrado en window.customElements,
y de acuerdo con la documentación de Angular probablemente lo sea,
podría hacer lo siguiente:

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

Lo que intenta lograr es imposible y va en contra de las mejores prácticas. En su lugar, debe mostrar ese componente con condiciones. Puede crear una variable en servicio y, en función de ese valor, el componente se puede mostrar o enlazar.

Vugar Abdullayev
fuente
Si fuera posible hacerlo así, me encantaría, pero el complemento que se ha utilizado solo proporciona el elemento HTMLE
Sachith Rukshan