The value of a PCF Control isn't always loaded; is it a race condition, or is it something else? How can I tell?

682 Views Asked by At

Has anyone else seen race conditions in the init of a Power Apps Component Framework (PCF) to where the value of the control isn't set?

How would I go about testing that?

I don't see an API call when the form is loaded (in UCI)? I do see it in the batch call from the grid view, but that must not be it?

Here's my code:

public init(context: ComponentFramework.Context<IInputs>, notifyOutputChanged: () => void, state: ComponentFramework.Dictionary, container: HTMLDivElement) {
        this.context = context;
        this.container = document.createElement("div");
        this.container.setAttribute("class", "acgContainer")
        this._refreshIndex = this.refreshIndex.bind(this);
        this.notifyOutputChanged = notifyOutputChanged;
        this.value = context.parameters.acgAriasYesNoUnControl.raw;
        //console.log("the init value: ", this.value);
        this.options = context.parameters.acgAriasYesNoUnControl.attributes?.Options;
        //console.log(this.options);
        this.selectElement = document.createElement("select");
        this.selectElement.addEventListener('change', this._refreshIndex);
        // @ts-ignore
        var zeroEle = this.selectElement.appendChild(new Option("---", null));
        zeroEle.style.backgroundColor = "#ffffff";
        if (this.options) {
            if (this.options.length > 0) {
                this.options.map((option: ComponentFramework.PropertyHelper.OptionMetadata, index: number) => {
                    var ele = this.selectElement.appendChild(new Option(option.Label, option.Value.toString()));
                    ele.style.backgroundColor = "#ffffff";
                    if (option.Label === this.envYesValue) {
                        //console.log("green option: ", option.Value);
                        this.valueOfYes = option.Value;
                    }
                    if (this.value === option.Value) {
                        ele.dataset.selected = "true";
                    }
                })
            }
        }
        // @ts-ignore
        this.selectElement.value = this.value?.toString() || null;
        this.selectElement.setAttribute("class", "acgYesNoUnControl");
        this.container.appendChild(this.selectElement);
        container.appendChild(this.container);
        //this.notifyOutputChanged();
    }
1

There are 1 best solutions below

1
Joe Crockett On

Turns out, you need to set the value of the HTMLElement in the updateView function!

The init method may not set the value initially, as it may not have the value from the server. But the updateView function runs each time it sees a new value, and will update the HTMLElement.

Reference, thanks to Diana B and Greg Hurlman

So, I should have highlighted the updateView function:

public updateView(context: ComponentFramework.Context<IInputs>): void {
        this.context = context;
        // storing the latest context from the control.
        // @ts-ignore
        this.selectElement.value = context.parameters.acgAriasYesNoUnControl.raw
            ? context.parameters.acgAriasYesNoUnControl.raw
            : null;
        this.value = context.parameters.acgAriasYesNoUnControl.raw
            ? context.parameters.acgAriasYesNoUnControl.raw
            : null;
        if (this.value === this.valueOfYes) {
            this.selectElement.style.backgroundColor = "#8cbd18";
        } else {
            this.selectElement.style.backgroundColor = "#ffffff";
        }
    }