0

I'm working on a web part using the SharePoint Framework, and my code is basically calling two methods to get information from SharePoint Online, when I call these methods on my render() method, I'm getting something like the following:

--- RENDER START ---

--- RENDER DONE ---

  • GetItems() => ID: 1 Title: New Office
  • GetItems() => ID: 2 Title: Mid-Term Reviews
  • GetItems() => ID: 3 Title: DevOps Training
  • GetItems() => ID: 4 Title: Work with us!

    - GetAttachments() => ID: 2 FileName: reviews.jpeg

    - GetAttachments() => ID: 1 FileName: new-office.jpg

    - GetAttachments() => ID: 3 FileName: devops.jpeg

    - GetAttachments() => ID: 4 FileName: careers.png

I was expecting to call these methods and have their results returned to me, and from there use them on my custom HTML rendering, the expected result would be something like this:

--- RENDER START ---

  • GetItems() => ID: 1 Title: New Office

    - GetAttachments() => ID: 1 FileName: reviews.jpeg

  • GetItems() => ID: 2 Title: Mid-Term Reviews

    - GetAttachments() => ID: 2 FileName: new-office.jpg

  • GetItems() => ID: 3 Title: DevOps Training

    - GetAttachments() => ID: 3 FileName: devops.jpeg

  • GetItems() => ID: 4 Title: Work with us!

    - GetAttachments() => ID: 4 FileName: careers.png

--- RENDER DONE ---

// uses the returned results in custom HTML for the rendering

Right now the code is running "wild", the htmlAttachments variable is receiving no results, and the rendering is completely blank, what should I do to get the results before the rendering?

Here it is my code:

public async GetItems() : Promise<IListItems>
  {
    let formattedResponse: IListItems = {value: []};

    await pnp.sp.web.lists.getByTitle('LIST').items.select('Id, Title, Body, Link').get().then( response => {
      response.map( (object: any, i: number) => {
        formattedResponse.value.push( {Id : object.Id, Title: object.Title, Body: object.Body, Link : object.Link.Url} );
      });      
    });

    return formattedResponse;
  }

  public async GetAttachments(itemId: number) : Promise<IFileItems>
  {
    let formattedResponse: IFileItems = {value: []};

    await pnp.sp.web.lists.getByTitle('LIST').items.getById(itemId).attachmentFiles.get().then( response => {
      response.map( (object: any, i: number) => {
        formattedResponse.value.push( {Id : itemId, FileName: object.ServerRelativeUrl} );
      });
    });

    return formattedResponse;
  }

  public render() : void
  {
    let htmlAttachments: string = '';

    htmlAttachments += '<ul>';

    this.GetItems().then( (responseItems: IListItems) => {
      responseItems.value.forEach( elementItems => {
        console.log("GetItems() ==> ", elementItems.Id, elementItems.Title);
        this.GetAttachments(elementItems.Id).then( (responseAtt: IFileItems) => {
          responseAtt.value.forEach( elementAtt => {
            console.log("\t GetAttachments() ==> ", elementAtt.Id, elementAtt.FileName);
            htmlAttachments += '<li>' + 'ID: ' + elementAtt.Id + ' - Title: ' + elementAtt.FileName + '</li>';
          });
        });
      });
    });

    htmlAttachments += '</ul>';

    this.domElement.innerHTML = htmlAttachments;
  }
Mr. Dr. Sushi
  • 469
  • 8
  • 22
  • Currently you'r `GetItems()` call fetching all items and after that you are fetching attachment for each item. If you want fetch attachment for each item then move get attachment in GetItems() call. – Mahesh Jul 18 '18 at 02:59
  • originally GetItems() was a complete method querying the ITEMS and on the .THEM( value => { ... } ) I had another query for the attachments - but it doesn't work... the code pass through this point and I need to have it returning to the original caller all the results (ITEMS + ATTACHMENTS) – Mr. Dr. Sushi Jul 18 '18 at 04:34

1 Answers1

0

A little late to this, but you can get rid of the GetAttachments method itself.

In the first call, GetItems itself you can get the attachment files and then use them in your HTML.

You can modify from below sample code:

public async GetItems() : Promise<IListItems>
{
    let formattedResponse: IListItems = {value: []};

    await pnp.sp.web.lists.getByTitle("LIST")
          .items
          .select("Id", "Title", "Body", "Link","AttachmentFiles")
          .expand("AttachmentFiles")
          .get()
          .then(response => {
          response.map((object: any, i: number) => {
            formattedResponse.value.push({
                Id : object.Id, 
                Title: object.Title, 
                Body: object.Body, 
                Link : object.Link.Url, 
                FileName: object.AttachmentFiles[0].FileName, 
                FileUrl : object.AttachmentFiles[0].ServerRelativeUrl
            });
          });
    });

    return formattedResponse;
}

Reference - Working with List Items in PnP JS

Gautam Sheth
  • 2,442
  • 1
  • 17
  • 16