0

Creating a custom SPfx Webpart. I'd like to read in some data from a Sharepoint list - I can do that. Issue I am running into is that some of that data includes variables. When it gets loaded it's being interpreted as literal strings.

For example if I hardcode this into my ts file it works fine, the ${styles.*} get loaded from the .scss file and it all works :

public render(): void {
    this.domElement.innerHTML = `<div class="${ styles.domsopTable }" id="myTable">
    <table id="${ styles.sopMenu }">
    <tr class="${ styles.sopR1 }">....</tr></table></div>`;}

The html generated looks like this:

enter image description here

When I change to read the table in from a SharePoint List it doesn't treat any of the variables ($styles.domsopTable}, ${styles.sopR1}) as variables - it just outputs them as strings.

    private _renderListAsync(): void {    
      if (Environment.type == EnvironmentType.SharePoint || 
               Environment.type == EnvironmentType.ClassicSharePoint) {
       this._getListData()
         .then((response) => {
           this._renderList(response.value);
         });
     }
   }
    private _renderList(items: ISPList[]): void {
      let html: string = '';
      items.forEach((item: ISPList) => {
        html += `${item.Data}`;
      });
  
      const listContainer: Element = this.domElement.querySelector('#myTable');
      listContainer.innerHTML = html;
    }
      
  public render(): void {
        this.domElement.innerHTML = `<div class="${ styles.domsopTable }" id="myTable">Loading Data...</div>`;
      this._renderListAsync();
  }

And the html code generated looks like this:

enter image description here

What am I missing?

I used this tutorial to load the data in from SharePoint List: https://www.spguides.com/retrieve-sharepoint-list-items-using-sharepoint-framework/

1
  • 1
    Looking at your code, it seems like each list item from SharePoint has a Data field that contains the HTML you want to render? In the example you link to, the HTML structure of the table is being built in the _renderList function, only the data for each of the table cells is coming from the SP list item. The way your code looks, it seems like you have put all of the HTML structure into the SP list item itself in a text field or something? Aug 3, 2022 at 20:41

1 Answer 1

1

Even though you haven't answered my question in the comments, I'm going to go ahead and post an answer anyway...

Yes, what used to be variables are now being treated like strings because to your Javascript code, they are strings, because the variable in your code is item and its property Data, and the (string) contents of that property is just being added into the html variable.

In order to understand what's going on, you may want to learn about the mechanism that's allowing for the replacement of those variables within the string, and that is called "Template literals".

Here's the article on that on MDN, and you could also just search the web for "javascript template literals" and you'll get tons of stuff to read.

Essentially what's happening is that when you use backticks (`) to define a string, instead of regular single or double quotes, you can then use ${ } to insert expressions into the string. The expression will be evaluated by Javascript, so therefore you can use Javascript variables in there and what will end up in the string is the contents of that variable.

Personally, I think of it as switching back and forth between being "in" a string and being "in" Javascript-land.

var something = `In here we are in a string, but ${ between the brackets here we are back in Javascript land } and now outside we are back in the string.`

So that lets whatever is between the brackets get evaluated as Javascript, and then the result of that evaluation gets inserted into the string. For instance

var item = {
    one: 1,
    two: 2
};

// we know that in javascript, if we do this

var sum = item.one + item.two;

// then "sum" will have a value of 3, and if we

console.log(sum);  // 3

// so similarly, you can put that as the expression to be evaluated:

var statement = `item.one + item.two = ${item.one + item.two}`;

console.log(statement);  // "item.one + item.two = 3"

So if you go back and look at the example code you linked to, the _renderList function uses a string template literal to be able to easily insert the values of the SP list item fields into the HTML string it's building (and also build that as a multi line string - another capability of template literals):

items.forEach((item: ISPList) => {
    // the backtick starts the string definition, but then they're putting
    // it on multiple lines of code to make it easier to read and see how the HTML
    // structure is getting built. but in each case, they are just taking the values
    // of the fields on the item and putting that as the contents of the table cell
    html += `
    <tr>            
        <td>${item.Title}</td>
        <td>${item.Conros_ProductCode}</td>
        <td>${item.Conros_ProductDescription}</td>
    </tr>
    `;
});

But in your re-interpretation of the code, rather than building the HTML table structure in code, and using the expression replacement to insert values into the table cells, you've just put the entire HTML table structure into a SharePoint field called Data, and you're just appending that as a raw string value into your html variable:

items.forEach((item: ISPList) => {
    html += `${item.Data}`;
});

So yes, the contents of item.Data is being treated as a raw string, you don't even really need the backticks and template literal there, you could probably just do:

items.forEach((item: ISPList) => {
    html += item.Data;
});

Even though you are using a template literal, the template literal system doesn't know how to look within that string to do more expression replacements.

1
  • I'm slowly reading through this, and re-reading, and looking into template literals. I wanted to at least say a few quick thank yous - 1) for giving me the right key words to google for more info and 2) for clearly restating the issue I am having. Aug 4, 2022 at 14:33

Your Answer

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

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