Skip to main content

Notifications

Community site session details

Community site session details

Session Id :
Power Apps - Power Apps Pro Dev & ISV
Unanswered

Output property not updated after calling getOutputs undefined (React control)

(0) ShareShare
ReportReport
Posted on by

I am creating a custom code control using the react framework. It is a text input that should return a text as output after the user entered text in the control.

Now I have the following manifest (shorted):

 

 

 

<?xml version="1.0" encoding="utf-8"?>
<manifest>
 <property name="Text"
 display-name-key="Text"
 description-key="Text of the text input"
 of-type="SingleLine.Text"
 usage="output"
 required="true" />
 <resources>
...
 </resources>
 </control>
</manifest>

 

 

Then I have the following  index.ts:

 

 

imports ...
export class CustomTextInput implements ComponentFramework.ReactControl<IInputs, IOutputs> {
 private notifyOutputChanged: () => void;
 private _text: string | undefined;
 private _props: ITextInputProps;
 constructor() { }

 public init(
 context: ComponentFramework.Context<IInputs>,
 notifyOutputChanged: () => void,
 void {
 this.notifyOutputChanged = notifyOutputChanged;

 this._props = {
 // ... some properties
 default: context.parameters.Default.raw!,
 maxLength: context.parameters.MaxLength.raw!,
 onTextChange: this.onTextChange,
 }
 console.log("init calls this.onTextChange: " + JSON.stringify(this._props.default))
 this.onTextChange(this._props.default);
 }

 public updateView(context: ComponentFramework.Context<IInputs>): React.ReactElement {
 console.log("update view");
 if (context.updatedProperties.indexOf('Default') > -1 || this._props.default !== context.parameters.Default.raw!) {
 this._props.default = context.parameters.Default.raw!;
 }

 if (context.updatedProperties.indexOf('MaxLength') > -1 || this._props.maxLength !== context.parameters.MaxLength.raw!) {
 const newMaxLength = this._props.maxLength = context.parameters.MaxLength.raw!;
 if (this._text && this._text.length > newMaxLength) {
 this._text = this._text.substring(0, newMaxLength) || "";
 }
 }
 return React.createElement(
 TextInput, this._props
 );
 }

 public getOutputs(): IOutputs {
 console.log("getOutputs, this._text: " + JSON.stringify(this._text));
 return { Text: this._text } as IOutputs;
 }

 onTextChange = (newValue: string | undefined): void => {
 console.log("onTextChange");
 console.log("newValue: " + JSON.stringify(newValue));

 if (newValue && newValue.trim().length !== 0) {
 this._text = newValue;
 } else {
 this._text = undefined;
 }
 console.log(this._text);
 this.notifyOutputChanged();
 };

 

 

My React Component file TextInput.tsx looks like this:

 

 

imports ...
export interface ITextInputProps {
 default?: string;
 maxLength?: number;
 onTextChange: (newText: string) => void
}
export interface ITextInputState {
 text: string;
}

export class TextInput extends React.Component<ITextInputProps, ITextInputState> {
 constructor(props: ITextInputProps) {
 super(props);
 this.state = {
 text: props.default || ""
 };
 }

 public render(): React.ReactNode {
 return (
 <ThemeProvider theme={this.props.theme}>
 <TextInputContainer>
 <LabelsContainer>
 <Label>{this.props.label}</Label>
 {this.props.hasClearButton && <ClearLabel onClick={this.handleOnClear}>Clear</ClearLabel>}
 </LabelsContainer>
 <Input placeholder={this.props.hintText} value={this.state.text.trim() !== "" ? this.state.text : ""} spellCheck={this.props.shouldSpellCheck}
 onChange={this.handleInputChange} type={this.props.format === "Text" ? "text" : "number"}
 maxLength={this.props.maxLength} />
 </TextInputContainer>
 </ThemeProvider>
 )
 }

 componentDidUpdate(prevProps: ITextInputProps) {
 if (prevProps.maxLength !== this.props.maxLength || this.props.maxLength && this.props.maxLength < this.state.text.length) {
 const { maxLength, onTextChange } = this.props;
 let { text } = this.state;
 if (maxLength === undefined || maxLength === null) {
 text = "";
 } else if (maxLength && text.length > maxLength) {
 text = text.substring(0, maxLength);
 }
 this.setState({ text }, () => onTextChange(text));
 }
 }

 handleInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {
 const newValue = event.target.value;
 console.log("handleInputChange: newValue: " + JSON.stringify(newValue));

 this.setState({
 text: newValue
 });

 this.props.onTextChange(newValue);
 }

 handleOnClear = () => {
 console.log("handleOnClear")
 console.log("this.state before: "+ JSON.stringify(this.state));

 this.setState({
 text: ""
 }, () => console.log("this.state after: " + JSON.stringify(this.state)));

 this.props.onTextChange("");
 }
}

 

 

 

When I add the code control to an app and I add a normal powerapps textlabel it looks like this:

Britninja_0-1681317808768.png

With TextLabel.Text being: "CustomTextInput1.Text: " & CustomTextInput1.Text

 

Now when I type text in the control it updates the label as well. Only if I try to delete all characters, it will stick with the old value unless I save and refresh the page.
Same thing when I hit the clear button: It deletes the content in the control, but doesn't update the value of CustomTextInput1.Text in the TextLabel. It looks like this (note the logs on the right).

Britninja_1-1681318176844.png

 

 

Does anyone know why it would not update the TextProperty although getOutputs is called with the undefined value?

 

Also note that in the test harness the output value also shows the value of undefined after activating the clear or deleting the letters. And if I delete the letters one by one in the power app it updates the label each time except for the last letter (control input is empty but CustomTextInput1.Text shows the last letter).

  • Community Power Platform Member Profile Picture
    on at
    Re: Output property not updated after calling getOutputs undefined (React control)

    I was able to solve my problem by returning null instead of undefined in handleInputChange. I think this causes the output property to be read as or converted to "Blank()" in Power Apps.

    So my code now looks like this:
    index.ts

     onTextChange = (newValue: string | undefined): void => {
     // ...
    
     if (newValue && newValue.trim().length !== 0) {
     this._text = newValue;
     } else {
     this._text = null;
     }
     // ...
     this.notifyOutputChanged();
     };

     TextInput.tsx (didn't really change anything except I am using the handleInputChange method now)

     <ClearLabel onClick={() => isEditMode ? this.handleInputChange("") : {}}
     className={displayMode?.toLowerCase()}>Clear</ClearLabel>

     
    Interestingly enough it seems I get the following errors in the testharness (but the code runs as it should).

    Britninja_0-1682100813124.png

     

    But in my app I don't get these errors so maybe that's something about updating values in the test harness.

  • Community Power Platform Member Profile Picture
    on at
    Re: Output property not updated after calling getOutputs undefined (React control)

    Hello @DianaBirkelbach ! Thank you for replying!

     

    Sorry if my question was confusing.

    What does the control do?

    The control is a custom text input. The app user clicks in it, types something and can provide that way a string input (not via a property in the property panel, but by using the control).

    That input value should be reusable in the app. So I need to get its value as output from the control.

    The property I am using for this is called "Text".

    So CustomTextInput1.Text should return the value that was provided by the user in the control.


    What does work?

    Now when I type for example "Apple" and I delete letters one by one (or a chunk of them) the output value (CustomTextInput1.Text) is visibly updated. So Text is updated on text changes (when they are not empty string).

    What is the problem?
    BUT, when I remove all letters,(or use the "onClear" function) that is, when the control input is completely empty (empty string), it does NOT update the value in CustomTextInput1.Text to be Blank().

    I am using state.text for containing and displaying the user input and it does work as expected (state.text is "" when deleting all the letters, also the control shows that it is empty). BUT the output value of the property seems to not be taken correctly when it's an empty string (undefined) value.

    The thing is, I do call the props.onTextChange() with the value of "" (empty string). it propagates through to the getOutputs method and actually does return "undefined" as output value (as the logs show). But still the CustomTextInput1.Text variable does not show the updated value.

    TDLR;
    getOutputs returns {Text: undefined} but the corresponding output variable CustomTextInput1.Text in the App still contains the last value that is not undefined unless I save and refresh the page.

    Hope this  helps to get a better understanding. I have the feeling state.text is not the problem, because getOutputs does return undefined. 

    Also notice that in the logs updateView is called, it shows state.text before the update and state.text after the update and its value shows empty string.

    Britninja_0-1681488429101.png

  • Diana Birkelbach Profile Picture
    3,072 Most Valuable Professional on at
    Re: Output property not updated after calling getOutputs undefined (React control)

    Hi @Anonymous , 

     

    It's a little hard to follow... not sure if I get it right, since I don't really understand what the PCF should do.
    But usually for this kind of issues it's important to understand how the updateView works.

    When a value changes inside the PCF, and you call the notifyOutputChanges(), the getOutputs gets called by the platform. Then the Platform Runtime evaluates the value, and then calls the updateView again, providing the new value. So after that the updateView will be called, and your TextInput component will rerender. 

    I guess the problems are cased by the TextInput component using an internal state for the "text", which doesn't get updated after the updateView. 

    Have a look to this PCF-Tutorial from the docs, and the explanation about "Controlled React component": https://learn.microsoft.com/en-us/power-apps/developer/component-framework/tutorial-create-model-driven-field-component?tabs=before&WT.mc_id=BA-MVP-5004107#controlled-react-component

     

    Hope it helps!

Under review

Thank you for your reply! To ensure a great experience for everyone, your content is awaiting approval by our Community Managers. Please check back later.

Helpful resources

Quick Links

Announcing the Engage with the Community forum!

This forum is your space to connect, share, and grow!

🌸 Community Spring Festival 2025 Challenge Winners! 🌸

Congratulations to all our community participants!

Warren Belz – Community Spotlight

We are honored to recognize Warren Belz as our May 2025 Community…

Leaderboard > Power Apps - Power Apps Pro Dev & ISV

#1
WarrenBelz Profile Picture

WarrenBelz 87 Most Valuable Professional

#2
mmbr1606 Profile Picture

mmbr1606 71 Super User 2025 Season 1

#3
Michael E. Gernaey Profile Picture

Michael E. Gernaey 65 Super User 2025 Season 1

Overall leaderboard