0

I'm trying to create multiple lightning data tables containing book records, organized by published date. The books in each table will have the same published date.

I am having an issue converting the returned map from apex into a usable object so that i can populate the data table.

I'm looking for help, and/or suggestions on how i can better convert the Apex map into a Javascript object, and then ultimately fill the tables with records. I'll leave notes in my code and towards the end of what I tried and what I am trying to achieve

getBooks.apxc

@AuraEnabled(cacheable=true)
public static Map<Date, List<Books__c>> getBooks(Id recordId) {
   Map<Date, List<Books__c>> bookMap = new Map<Date, List<Books__c>>();
    
   List<Books__c> books = new List<Books__c>([SELECT Name, Author__c, PublishedDate__c FROM Books__c WHERE Genre__c = :recordId ORDER BY PublishedDate__c DESC]);
    
    for (Books__c book : books) {
        if (!bookMap.containsKey(book.PublishedDate__c)) {
            bookMap.put(book.PublishedDate__c,new List<Books__c>());    
        }
        bookMap.get(book.PublishedDate__c).add(book); 
    }
   
    return bookMap;
}

BookComponent.js

import { LightningElement } from 'lwc';
import GetBooks from '@salesforce/apex/BooksController.getBooks';

export default class BookComponent extends LightningElement {

  @api recordId;
  @api publishedDate;

  mainBookObj = [];

  @wire(GetBooks, { recordId: '$recordId'})
  loadBooks(books) {
    
    
    // I tried to reference books.data in my template iteration but I was getting a "e[Yn] is not a function" error. 
    // This is what I eventually got working, not sure if there is a better way?
    

    let tempBookObj = books.data
    for (var key in tempBookObj) {
      let value = [];
      for (var innerkey in tempBookObj[key]) {
        value.push({ key: innerkey, value: tempBookObj[key][innerkey] });
      }
      this.mainBookObj.push({ key: key, value: value })
    }
  }
}

BookComponent.html

<template>
  <template for:each={mainBookObj} for:item="book">
    <lightning-card key={book.key}>
      <lightning-accordion>
        <lightning-accordion-section name={book.key} label={book.key}>

         <c-book-datatable book-data={book}> </c-book-datatable>

        </lightning-accordion-section>
        </lightning-accordion>
      </div>
    </lightning-card>
   </template>
  </template>

BookDatatable.js (this is where im stuck)

 export default class BookDatatable extends LightningElement {
   @api recordId;
   @track bookList = [];
   @track columns = [{ Label: 'Name', fieldName: 'BookName__c'},{Label: 'Author', fieldName: 'Author__c'}];

   connectedCallback() {
     this.loadBooks(JSON.stringify(this.bookData));
   }

   loadBooks(taskObject) {
    const obj = (JSON.parse(taskObject));
    console.log(obj);      
   }
  }
}

BookDatatable.html

<template>
    <div style="height: 300px;">
        <lightning-datatable
                key-field="id"
                data={bookList}
                columns={columns}>
        </lightning-datatable>
    </div>
</template>

Each iteration of the data table in BookComponent.html will give me an object with a key of the date and an inner array of the books of the same date. Which is what I want

I'm stuck in BookDatatable.js trying to figure out how to put that object in bookList which is the array on the data table that will hold the records. I think I need to iterate into the object somehow to grab the array of records.

I almost feel as if the object created from the apex map back in BookComponent.js was done incorrectly. Any suggestions welcome

1 Answer 1

0

You have two problems. First, @api bookData is not defined in your component controller. Second, you never assign the value to bookList. Until you get to some weird edge cases, I'd suggest you avoid this extra step anyways, and just set the list to the table directly:

export default class BookDatatable extends LightningElement {
   @api bookData;
   @track columns = [{ label: 'Name', fieldName: 'BookName__c'},{ label: 'Author', fieldName: 'Author__c'}];
  }
}
<template>
    <div style="height: 300px;">
        <lightning-datatable
                key-field="id"
                data={bookData}
                columns={columns}>
        </lightning-datatable>
    </div>
</template>
1
  • Sorry about that, it is actually defined in my component but I missed it when i copy and pasted it over. I get can't get the data to display in the table and I think it's because the object has an array inside of it. The array are the records I need to display in @api bookData. Appreciate all your help! Apr 25 at 9:57

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .