0

I am creating an SPFX React project that will display a field from a SharePoint list in a web part

A user opens the property pane and:

  1. selects a list
  2. selects the item ID from that list
  3. selects the column of the content they would like to display in the web part

I have successfully created the drop downs in the property pane for selecting a list, item ID and column in the .ts file.

groups: [
        {
          groupName: strings.BasicGroupName,
          groupFields: [
            PropertyFieldListPicker("listId", {
              label: "Select a list",
              selectedList: this.properties.listId,
              includeHidden: false,
              orderBy: PropertyFieldListPickerOrderBy.Title,
              disabled: false,
              onPropertyChange: this.onPropertyPaneFieldChanged.bind(this),
              properties: this.properties,
              context: this.context,
              onGetErrorMessage: null,
              deferredValidationTime: 0,
              key: "listPickerFieldId",
            }),

            PropertyPaneDropdown("itemId", {
              label: "Select ID of item to display",
              options: this.dropdownOptions,
              disabled: this.columnsDropdownDisabled,
            }),

            PropertyPaneDropdown("columnTitle", {
              label: "Select field to display",
              options: this.listColumns,
              disabled: this.columnsDropdownDisabled,
            }),                

          ],
        },
      ],

The above works as expected and I am able to display the itemId and column title in the web part so I know the values are passing from the .tx to the .tsx file

this is the render method in the .tsx file

public render(): React.ReactElement<IDisplayItemFieldProps> {
return (
  <div className={styles.displayItemField}>
    <div className={styles.container}>
      <div className={`ms-Grid-row ms-bgColor-themeDark ms-fontColor-white ${styles.row}`}>
        <div className="ms-Grid-col ms-u-lg10 ms-u-xl8 ms-u-xlPush2 ms-u-lgPush1">         
          <p className="ms-font-l ms-fontColor-white">Item ID selected : {escape(this.props.itemId)}</p>
          <p className="ms-font-l ms-fontColor-white">Column selected : {escape(this.props.columnTitle)}</p>              
        </div>
      </div>
    </div>
  </div>
);

enter image description here

The issue I have is how do I capture and store the content from the column for the item selected and display it in the web part.

I presume I need to make an HTML call (with a URL like below) but unsure how/where to put this, and how to store the HTML response in the .tsx file to use it in the public render() section.

this.context.pageContext.web.absoluteUrl + `/_api/Web/Lists/GetById(guid'` + this.properties.listId + `')/items(` +  this.properties.itemId + `)?$select=,` + this.properties.columnTitle

The displayed field content also needs to be able to be automatically updated if a user changes the drop downs in the property pane.

I have been looking at the ReactAccordian SPFX project and that displays it correctly (with formatting and images retained) using the following in the .tsx public render() section. This is what I m trying to achieve

dangerouslySetInnerHTML={{
                      __html: item[this.props.accordianContentColumn],
                    }}

Any help would be greatly appreciated

4
  • Do you want to show the value of the selected column in the web part? Also please share the code you have used in the render method! Jun 25, 2021 at 0:56
  • hi, yes I would like to show the value of the selected column in the webpart. The column will be a rich text and potentially contain formatting, tables, images etc... Jun 25, 2021 at 1:07
  • I have added the render method code to the original question Jun 25, 2021 at 1:13
  • You can call the REST API you mentioned in "on change" event of columnTitle property pane dropdown. Once you get the results, store it in react this.state which you can refer in render() method. This way, whenever you change the column title, it will change the react state & update the rendering. Jun 25, 2021 at 4:16

4 Answers 4

0

Call the below REST API call in method, onPropertyPaneFieldChanged

this.context.pageContext.web.absoluteUrl + `/_api/Web/Lists/GetById(guid'` + this.properties.listId + `')/items(` +  this.properties.itemId + `)?$select=` + this.properties.columnTitle

Then store the retrieved response in a State variable and display it in the render method.

If you are not storing in State Variable, you have to call the render method again to show the retrieved value.

Edited


Use the below code to retrieve the response in JSON format,

  private fetchFieldValue(): Promise<SPHttpClientResponse> {
    var url = this.context.pageContext.web.absoluteUrl + `/_api/Web/Lists/GetById(guid'` + this.properties.listId + `')/items(` + this.properties.itemId + `)?$select=` + this.properties.columnTitle;
    console.log(url)
    return this.context.spHttpClient.get(url, SPHttpClient.configurations.v1, {
      headers: {
        'Accept': 'application/json;odata=verbose',
        'odata-version': ''
      }
    }).then((response: SPHttpClientResponse) => {
      if (response.ok) {
        console.log(response)
        return response.json();

      } else {
        console.log("WARNING - failed to hit URL " + url + ". Error = " + response.statusText);
        return null;
      }
    });
  }
1
  • Thanks Shantha, this is where I am getting a little stuck... I am new to spfx. I will post what I have done so far, but in the console log it states : Uncaught (in promise) SyntaxError: Unexpected token < in JSON at position 0 Jun 28, 2021 at 0:34
0

As suggested, I have now added a function for calling the REST API

private fetchFieldValue(): Promise<any> {    
var url = this.context.pageContext.web.absoluteUrl + `/_api/Web/Lists/GetById(guid'` + this.properties.listId + `')/items(` +  this.properties.itemId + `)?$select=` + this.properties.columnTitle;
console.log(url)
return this.context.spHttpClient.get(url, SPHttpClient.configurations.v1).then((response: SPHttpClientResponse) => {
  console.log(response)
  response.json().then((responseJSON: any) => {  
    console.log(responseJSON.Question);  
    this.properties.itemValue = responseJSON.Question
  });          
});}

then in the onPropertyPaneFieldChanged method I have added a call

if (this.properties.columnTitle) {
  this.fetchFieldValue()
  console.log("columnTitle changed")

}

However when I look at the console log I can see that the url is correct but get the following error :

Uncaught (in promise) SyntaxError: Unexpected token < in JSON at position 0

enter image description here

putting the url in the browser the response back is xml

<?xml version="1.0" encoding="utf-8"?><entry xml:base="https://.......

I presume the issue is the response I am getting back is not in json

Any help is greatly appreciated

This is what I get is a put console.log(response) before the return response.json()

enter image description here

2
  • I think you are getting the result in XML format. But we need to get the value in json format. Please add console.log(response) before the return response.json() and check. Jun 28, 2021 at 2:32
  • just added the screen shot of the response Jun 28, 2021 at 4:08
0

Try the below code to get the response,

if (this.properties.columnTitle) {
  this.fetchFieldValue().then((response) => {
        console.log(response);
});
  console.log("columnTitle changed")

}




  private fetchFieldValue(): Promise<SPHttpClientResponse> {
    var url = this.context.pageContext.web.absoluteUrl + `/_api/Web/Lists/GetById(guid'` + this.properties.listId + `')/items(` + this.properties.itemId + `)?$select=` + this.properties.columnTitle;
    console.log(url)
    return this.context.spHttpClient.get(url, SPHttpClient.configurations.v1, {
      headers: {
        'Accept': 'application/json;odata=verbose',
        'odata-version': ''
      }
    }).then((response: SPHttpClientResponse) => {
      if (response.ok) {
        console.log(response)
        return response.json();

      } else {
        console.log("WARNING - failed to hit URL " + url + ". Error = " + response.statusText);
        return null;
      }
    });
  }
1
  • nearly there......!!!! I have got the JSON response now working for the multiline rich text field... :) I will respond to what is needed now Jun 29, 2021 at 0:59
0

Nearly there.....

The JSON response changes based on the type of content in the rich text field.

sometimes it is nested with a d > __metadata , sometimes it is just flat JSON structure.

Flat response enter image description here

Nested response enter image description here

I have created an if statement using response.hasOwnProperty to try and catch the variance. which works

    if (this.properties.columnTitle) {
        this.fetchFieldValue().then((response) => {
        console.log(response);            
        //console.log(Object.keys(response)); 

           if(response.hasOwnProperty(this.properties.columnTitle)){          
             this.properties.itemValue = response.RichTextField
           } else {
             this.properties.itemValue = response.d.RichTextField
           }    
   });
  //console.log("columnTitle changed")
}

The final step is how to set the this.properties.itemValue to the correct value using this.properties.columnTitle I have tried this without success

if(response.hasOwnProperty(this.properties.columnTitle)){          
    this.properties.itemValue = response.${this.properties.columnTitle}
} else {
    this.properties.itemValue = response.d.${this.properties.columnTitle}
}

Thanks again for all your help

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.