Wie füge ich eine Komponente zu einem Elementref hinzu?

8

Ich möchte als untergeordnetes Element eine Komponente zu einer Elementref hinzufügen und Zugriff auf deren Eigenschaften haben.

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

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

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

Ich habe meinem Projekt einen vollständigen Kalender hinzugefügt und für die Zeitleiste muss ich benutzerdefinierte Ressourcenelemente hinzufügen. Dafür bekomme ich nur Zugriff auf das HTMLElement und einige Daten. Ich möchte also eine initialisierte Komponente an das HTMLElement übergeben.

Im Moment besteht meine einzige Option darin, das HTML als Zeichenfolge zu schreiben und an das innerHTML zu übergeben. Gibt es eine bessere Option?

Sachith Rukshan
quelle
Kannst du mehr erklären?
GaurangDhorda
Was ist Ihre Anforderung? Was du machen willst, ist nicht möglich.
Angular
Kannst du eine Alternative geben ist möglich
Sachith Rukshan
Versuchte es, funktionierte aber nicht @Caro
Sachith Rukshan

Antworten:

7

In einem meiner Projekte habe ich auf diese Weise etwas erreicht, das Ihrer Anforderung entspricht. Lassen Sie mich wissen, ob es hilft?

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

Auf diese Weise haben Sie Verweis auf Ihre dynamische Komponente als componentRef

Prabhatojha
quelle
Danke für die Antwort. Ich kann mit componentRef auf die Instanz zugreifen. Recht?
Sachith Rukshan
1
@SachithRukshan ja
prabhatojha
4

Möglicherweise können Sie Renderer2 verwenden

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

Mehr Beispiele

Robin Dijkhof
quelle
Vielen Dank für die Antwort, aber ich habe diese Lösung schon einmal überprüft. Und es macht es nicht einfacher. Und es ist besser als HTMLElement
Sachith Rukshan
1
Es ist besser, weil Angular jetzt die DOM-Änderung kennt. Durch einfaches Anhängen an den DOM-Winkel wird dies nicht bemerkt.
Robin Dijkhof
Was ist der genaue Vorteil davon.
Sachith Rukshan
4
Ich habe es buchstäblich nur erklärt
Robin Dijkhof
Ich habe bereits die inneren Elemente des elemenrref implementiert und auch Geschäftslogiken hinzugefügt. Ich muss also wissen, ob das Hinzufügen von renderer2 es einfacher macht
Sachith Rukshan
1

In der Angular-Dokumentation heißt es

Winkelelemente sind Winkelkomponenten, die als benutzerdefinierte Elemente verpackt sind (auch als Webkomponenten bezeichnet).

Auf diese Weise können Sie das Element erstellen, das Sie mit hinzufügen möchten

  1. document.createElement('elementName')wenn es sich um ein autonomes benutzerdefiniertes Element handelt , oder
  2. document.createElement('baseElementName', {is: 'elementName'})wenn es sich um ein benutzerdefiniertes integriertes Element handelt .

Sie können das von Ihnen erstellte containerElement container.insertAdjacentElement(position, element)wie hier beschrieben in ein Element einfügen .

Burak Gök
quelle
Genau das habe ich getan, aber was ich wissen möchte, ist eine bessere Lösung. Bitte lesen Sie die Frage richtig
Sachith Rukshan
1
@SachithRukshan Ich glaube, das ist ganz anders alswriting 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
quelle
Ich fand das, als ich ein bisschen Dogging machte. Ich hoffe, Sie finden es nützlich
Amrish Khan Sheik
Hallo Amrish, danke, dass du versucht hast zu helfen. Kann ein bisschen erklären, wie es meinem Problem helfen könnte.
Sachith Rukshan
@ AmrishkhanSheik Hallo, willkommen bei Stackoverflow. Wenn Sie eine Antwort posten, wird empfohlen, dass Sie auch eine Erklärung angeben. Nur ein Codezaun erklärt nicht, warum oder wie dies für die Antwort relevant ist. Siehe: Wie schreibe ich eine gute Antwort?
Dane Brouwer
0

Da die Komponente in window.customElements registriert ist
und dies laut Angular-Dokumentation wahrscheinlich der Fall ist, können
Sie Folgendes tun:

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

Was Sie erreichen möchten, ist unmöglich und widerspricht Best Practices. Stattdessen müssen Sie diese Komponente mit Bedingungen anzeigen. Sie können eine Variable im Service erstellen und basierend auf diesem Wert kann die Komponente angezeigt oder geloopt werden.

Vugar Abdullayev
quelle
Wenn es möglich wäre, es so zu machen, würde ich es gerne tun, aber das verwendete Plugin liefert nur das HTMLElement
Sachith Rukshan