Thursday, April 25, 2019

Cannot display selected office fabric ui dropdown value from SharePoint framework

We are using SharePoint framework with office fabric UI component. The current project is to use SPFx to display an list item that has a Dropdown field. The issue is we are getting the value all options as an array from the SharePoint but cannot display the option value already set in the list.

After few days debugging the issue, we have isolated to the SharePoint framework REACT how to pass the pros from parent to child component. Here is the simple code to reproduce this issue.

1. Hard coded the array like this below in parent component named LoopUp.

private defaultOptionList: IDropdownOption[] = [
{
key: '0',
text: 'None',
isSelected: false
},
{
key: '1',
text: 'Encore/Review Publication',
isSelected: true
},
{
key: '2',
text: 'Non-Scientific',
isSelected: false
},
{
key: '3',
text: 'Assay Method',
isSelected: false
},
{
key: '4',
text: 'Research Data',
isSelected: false
},
{
key: '5',
text: 'PK/Tox Data',
isSelected: false
},
{
key: '6',
text: 'Clinical Data',
isSelected: false
},
{
key: '7',
text: 'Clinical Study Design',
isSelected: false
},
{
key: '8',
text: 'Clintrials.gov Posting',
isSelected: false
}

];

2. If we initialize the state in the constructor below and pass to child, child can display the selected option value.  The state we set up is named submissionContentListState2.

constructor(props) {

super(props);
this.state = {
submissionContentListState2: [] = this.defaultOptionList, // Set in constructor
submissionContentListState4: [] // Set in componentDidMount
};

}

3. If we set the same value from  componentDidMount  like below, child cannot display the selected value. The state we set up is named submissionContentListState4.

public componentDidMount() {
this.setState({
submissionContentListState4: this.defaultOptionList
});
}           

The code to pass to child is listed below.
public render(): React.ReactElement<ILoopUpProps> {

SPFacade.logOptions(this.state.submissionContentListState2, "Parent Rendor submissionContentListState2");
SPFacade.logOptions(this.state.submissionContentListState4, "Parent Rendor submissionContentListState4");
return (
<Child
defaultOptionListParent2={this.state.submissionContentListState2} // This is in constructor
defaultOptionListParent4={this.state.submissionContentListState4} // This is in componentDidMount
/>

);
}


The code in child is listed below.
import * as React from 'react';
import styles from './LoopUp.module.scss';
import { ILoopUpProps } from './ILoopUpProps';
import { Dropdown, IDropdownOption } from "office-ui-fabric-react";
import { SPFacade } from "./SPFacade";

export class Child extends React.Component<any,
{
}
> {
constructor(props) {
// Required step: always call the parent class' constructor
super(props);
}
public render(): React.ReactElement<ILoopUpProps> {

SPFacade.logOptions(this.props.submissionContentListState2, "Child Rendor submissionContentListState2");
SPFacade.logOptions(this.props.submissionContentListState4, "Child Rendor submissionContentListState4");
return (
<div className={ styles.loopUp }>
<div className={ styles.container }>

<div className={ styles.row }>
<div className={ styles.column }>
<Dropdown
placeHolder="Select a content type"
required={true}
label="Lokup values from parent props set in constructor - working"
options={this.props.defaultOptionListParent2}
/>
</div>
</div>

<div className={ styles.row }>
<div className={ styles.column }>
<Dropdown
placeHolder="Select a content type"
required={true}
label="Lokup values from parent props set in componentDidMount - not working"
options={this.props.defaultOptionListParent4}
/>
</div>
</div>

</div>
</div>
);
}

}


The result is show as below.

You can see the top DOM element did show the selected value named "Encore/Review Publications". However, the bottom DOM element could not display the selected value even all the option values are retrieved.

This is a show stopper for us at this point since we need to get the value from SharePoint list item and it should be done in componentDidMount function and cannot be in constructor.

If you know the solution or workaround, please let me know.

The complete parent code is listed below.

import * as React from 'react';
import { ILoopUpProps } from './ILoopUpProps';
import { IDropdownOption } from "office-ui-fabric-react";
import { Child } from "./Child";
import { SPFacade } from "./SPFacade";

export default class LoopUp extends React.Component<ILoopUpProps,
{
submissionContentListState2: IDropdownOption[];
submissionContentListState4: IDropdownOption[];
}
> {

private defaultOptionList: IDropdownOption[] = [
{
key: '0',
text: 'None',
isSelected: false
},
{
key: '1',
text: 'Encore/Review Publication',
isSelected: true
},
{
key: '2',
text: 'Non-Scientific',
isSelected: false
},
{
key: '3',
text: 'Assay Method',
isSelected: false
},
{
key: '4',
text: 'Research Data',
isSelected: false
},
{
key: '5',
text: 'PK/Tox Data',
isSelected: false
},
{
key: '6',
text: 'Clinical Data',
isSelected: false
},
{
key: '7',
text: 'Clinical Study Design',
isSelected: false
},
{
key: '8',
text: 'Clintrials.gov Posting',
isSelected: false
}

];

constructor(props) {

super(props);
this.state = {
submissionContentListState2: [] = this.defaultOptionList, // Set in constructor
submissionContentListState4: [] // Set in componentDidMount
};

}

// Get the itemId received form the parent and display attachment if itemId is not NaN
public componentDidMount() {
this.setState({
submissionContentListState4: this.defaultOptionList
});
}

public render(): React.ReactElement<ILoopUpProps> {

SPFacade.logOptions(this.state.submissionContentListState2, "Parent Rendor submissionContentListState2");
SPFacade.logOptions(this.state.submissionContentListState4, "Parent Rendor submissionContentListState4");
return (
<Child
defaultOptionListParent2={this.state.submissionContentListState2} // This is in constructor
defaultOptionListParent4={this.state.submissionContentListState4} // This is in componentDidMount
/>

);
}




}








2 comments: