Dynamische Control-Generierung

Controls können weitere fremde Controls erstellen und in ihrem eigenen Kontext nutzen. Daraufhin kann auf Events dieser Kind-Controls reagiert werden.

Beispiel über die ControlFactory-API

In diesem Beispiel wird die API der ControlFactory genutzt. Bei der Erstellung des Controls wird das Kind-Control erstellt und in die eigene Darstellung eingehängt.

Durch die Definition des Parent wird das Kind-Control in den eigenen Lebenszyklus eingebettet, so dass das Kind-Control automatisch mitverwaltet wird.

Weiterhin wird ein Event-Handler registriert um auf Ereignisse des Kind-Controls zu reagieren. Beachten Sie, dass diese Event-Registrierung im eigenen Destroy aufgeräumt werden muss um ein Speicherleck zu beheben.

Siehe auch Control-Lebenszyklus

protected __childOnPressedDestroyEvent: DestroyFunction | undefined; 

public __init() {
   super.__init();

   let childName = this.__id + '_startAction';
   let myButton = TcHmi.ControlFactory.createEx<TcHmi.Controls.Beckhoff.TcHmiButton> (
      'TcHmi.Controls.Beckhoff.TcHmiButton',
      childName,
      {
         'data-tchmi-top': 25,
         'data-tchmi-left': 250,
         'data-tchmi-width': 200,
         'data-tchmi-height': 50,
         'data-tchmi-text': 'Start Action',
         'data-tchmi-background-color': {
            'color': 'rgba(55, 55, 55, 1)'
         },
         'data-tchmi-state-symbol': '%s%PLC1.MAIN.testBool%/s%' // Binding a symbol to an attribute during control creation
      },
      this // marks our control as the parent
   );
   if (myButton) {
      // Append to our DOM. This will be detected by the framework and its .__attach function will be called automatically.
      this.__element.append(myButton.getElement());
      this.__childOnPressedDestroyEvent = TcHmi.EventProvider.register(childName + '.onPressed', () => {
         // do something
      });

      // Binding a symbol to an attribute after control creation
      Binding.createEx2('%s%PLC1.MAIN.anotherBool%/s%', 'StateSymbol', myButton);
   }
}

public destroy() {
   if (this.__keepAlive) {
      return;
   }
   if(this.__childOnPressedDestroyEvent){
      this.__childOnPressedDestroyEvent();
   }
   super.destroy();
}

Beispiel eines in das Template eingebetteten Kind-Controls

Kind-Controls können auch direkt in das Template eines Controls eingebettet werden. Dafür wird die gleiche Syntax genutzt, die auch im Engineering benutzt wird um ein Control im Code darzustellen. Den einzigen Unterschied stellt der {Id}-Platzhalter dar, der beim Kompilieren des Controls durch die tatsächliche ID ersetzt wird.

Es ist zwingend notwendig, den {Id}-Platzhalter zu nutzen, da es sonst unmöglich wäre mehr als eine Instanz des Controls zu erzeugen. Die Kompilation der zweiten Instanz würde in einen Fehler laufen, da versucht würde ein Control mit einem bereits vergebenen Namen zu erzeugen.

<div class="TcHmi_Controls_Example-template">
    <div id="{Id}_startAction" data-tchmi-type="TcHmi.Controls.Beckhoff.TcHmiButton"
        data-tchmi-top="25" data-tchmi-left="250"
        data-tchmi-width="200" data-tchmi-height="50"
        data-tchmi-text="Start Action" data-tchmi-state-symbol="%s%PLC1.MAIN.testBool%/s%"
    >
        <script data-tchmi-target-attribute="data-tchmi-background-color" type="application/json">
            {
                "color": "rgba(55, 55, 55, 1)"
            }
        </script>
    </div>
</div>

Auf die Instanz des Kind-Controls kann dann im __previnit oder __init des Controls so zugegriffen werden:

let button = Controls.get<TcHmi.Controls.Beckhoff.Button>(this.getId() + '_startAction');