Handling von Symbolausdrücken in Objekten

Ein Control-Setter kann Objekte erhalten in dem Symbolausdrücke enthalten sind. Dies muss vom Control über die Eigenschaft allowSymbolExpressionsInObject bei jedem Attribut einzeln freigeschaltet werden. In diesem Fall wird dies im Visual Studio so dargestellt:

Handling von Symbolausdrücken in Objekten 1:

Hierfür muss der Quelltext der das Attribut-Handling übernimmt entsprechend angepasst werden.

Zuerst wird ein vorhandener ObjectResolver gesucht. Im Erfolgsfall wird dieser zerstört. Anschließend wird ein neuer ObjectResolver mit dem neuen Objekt (welcher den Symbolausdruck enthalten kann) erstellt und gespeichert. Gleichzeitig wird eine watch Funktion verlinkt, welche initial und bei Änderung in referenzierten Symbolen aufgerufen wird.

Diese watch Funktion prüft, ob das Control gerade sichtbar ist. Ist dies nicht der Fall, wird der ObjectResolver in einen Wartezustand versetzt. Wird das Control später sichtbar geschaltet werden vom System alle ObjectResolver wieder aktiviert. Im Fehlerfall wird die Abarbeitung mit einer Fehlermeldung abgebrochen.
Die Abarbeitung wird beendet, wenn der neuen Wert mit dem alten Wert identisch ist. Ist der Wert geändert, so wird der neue Wert gespeichert, das System über die Änderung informiert und auf die Änderung reagiert.

Statt dem generischen Typ object kann auch eine spezifischere Typescript-Typ-Definition genutzt werden.

protected __value: object | undefined;

/**
* @description Setter function for 'data-tchmi-value' attribute.
* @param valueNew the new value or null 
*/
public setValue(valueNew: object | null): void {
    // convert the value with the value converter
    let convertedValue = TcHmi.ValueConverter.toObject<object>(valueNew);

    // check if the converted value is valid
    if (convertedValue === null) {
        // if we have no value to set we have to fall back to the defaultValueInternal from description.json
        convertedValue = this.getAttributeDefaultValueInternal('Value') as object;
    }

    let resolverInfo = this.__objectResolvers.get('value');

    if (resolverInfo) {
        if (resolverInfo.watchDestroyer) {
            resolverInfo.watchDestroyer();
        }
        resolverInfo.resolver.destroy();
    }

    let resolver = new Symbol.ObjectResolver(convertedValue);

    this.__objectResolvers.set('value', {
        resolver: resolver,
        watchCallback: this.__onResolverForMyAttributeWatchCallback,
        watchDestroyer: resolver.watch(this.__onResolverForMyAttributeWatchCallback)
    });
}

/**
* The watch callback for the value object resolver.
*/
protected __onResolverForMyAttributeWatchCallback = (data: Symbol.ObjectResolver.IWatchResultObject<Transform[]>) => {
    if (this.__isAttached === false) { // While not attached attribute should only be processed once during initializing phase.
        this.__suspendObjectResolver('value');
    }

    if (data.error !== TcHmi.Errors.NONE) {
        TcHmi.Log.error('[Source=Control, Module=TcHmi.Controls.System.TcHmiControl, Id=' + this.getId() + ', Attribute=Value] Resolving symbols from object failed with error: ' + TcHmi.Log.buildMessage(data.details));
        
        return;
    }

    if (tchmi_equal(data.value, this.__value)) {
        return;
    }

    this.__value = data.value;

    TcHmi.EventProvider.raise(this.__id + '.onPropertyChanged', { propertyName: 'Value' });


    this.__processValue();
};

public __processValue() {
    // process actions with Value
    // ...
}