0

I'm working on a very simple project that uses google books API and I have a problem. I want to save all search history in an object in database and all works fine when I'm logged in my account and all history records to a base, but when random user want to find some books I have this error:

enter image description here

How I can fix this?

My code:

searchList.html

<template>
    <lightning-card>
        <article class="slds-card">
            <div class="slds-card__header slds-grid">
                <header class="slds-media slds-media_center slds-has-flexi-truncate">
                    <div class="slds-media__body">
                      <h2 class="slds-card__header-title">
                          <span class="slds-text-heading_small slds-truncate slds-align_absolute-center">Books</span>
                      </h2>
                    </div>
                </header>
            </div>
            <div class="slds-card__body slds-card__body_inner">
                <div class="slds-m-bottom_x-small slds-wrap slds-grid slds-gutters">
                    <lightning-input type="text"
                        value={searchTitleValue}
                        label="Book title"
                        onchange={updateSearchTitleValue}
                        class="slds-col"
                    ></lightning-input>
                    <lightning-input type="text"
                        value={searchAuthorValue}
                        label="Author"
                        onchange={updateSearchAuthorValue}
                        class="slds-col"
                    ></lightning-input>
                </div>
                <button class="slds-button slds-button_brand slds-button_stretch" onclick={findBooks}>Find Book(s)</button>
                <lightning-layout class="slds-p-around_xx-small slds-grid slds-grid_pull-padded slds-wrap slds-grid_align-center">
                    <template for:each={Books} for:item='Book'>
                            <lightning-layout-item class="slds-m-around_xx-small slds-size_3-of-12 slds-box" key={Book.id} data-id={Book.id}>
                                <h2 class="slds-text-align_center"><b>{Book.volumeInfo.title}</b></h2>
                                <p class="slds-text-align_center">{Book.volumeInfo.authors}</p>
                                <img class="slds-align_absolute-center" src="">
                                <a target="_blank" rel="noopener noreferrer" href="" class="slds-align_absolute-center slds-m-around_x-small">
                                    <button class="slds-button slds-button_success">Go to shop</button> 
                                </a>
                            </lightning-layout-item>
                    </template>
                </lightning-layout> 
            </div>
        </article>
    </lightning-card>
</template>

searchList.js

import { LightningElement, track } from 'lwc';
import addBookRecord from '@salesforce/apex/searchListController.addBookRecord';
export default class BooksSearch extends LightningElement {
    
    @track Books;
    searchTitleValue = '';
    searchAuthorValue = '';

    async findBooks()
    {
        if(this.searchTitleValue !== '')
        {   
            addBookRecord({title: this.searchTitleValue, author: this.searchAuthorValue});
            let tempTitle = this.searchTitleValue.replace(/ /g, '_');
            let tempAuthor = '';
            if(this.searchAuthorValue !== '')
            {
                let tempList = this.searchAuthorValue.split(' ');
                tempAuthor = '+inauthor:' + tempList[tempList.length - 1];
            }
            let url = 'https://www.googleapis.com/books/v1/volumes?q=' + tempTitle + tempAuthor +'&maxResults=40&key=[myKey]'
            let fetchResult = await fetch(url);
            let jsonString = await fetchResult.json();
            this.Books = jsonString.items;
            console.log(jsonString);
        }
        setTimeout(() => { 
            let size = this.Books.length;
            for(let i = 0; i < size; i++)
            {
                let bookImage;
                let shopLink;
                
                if(this.Books[i].saleInfo.saleability == "FOR_SALE"){
                    shopLink = this.Books[i].saleInfo.buyLink;
                } else {
                    shopLink = this.Books[i].volumeInfo.canonicalVolumeLink;
                }
                if(this.Books[i].volumeInfo.hasOwnProperty('imageLinks')) {
                    bookImage = this.Books[i].volumeInfo.imageLinks.thumbnail;
                } else {
                    bookImage = 'https://i.postimg.cc/RZ3rrN0Y/noBook.png'
                }                
                //let bookId = this.Books[i].id;
                this.template.querySelector('[data-id="' + this.Books[i].id + '"]').querySelector("a").setAttribute("href", shopLink);
                this.template.querySelector('[data-id="' + this.Books[i].id + '"]').querySelector("img").setAttribute("src", bookImage);
                //element.setAttribute("src", bookImage);
            }
        } , 500);
    }

    updateSearchTitleValue(event)
    {
        this.searchTitleValue = event.target.value;
    }

    updateSearchAuthorValue(event)
    {
        this.searchAuthorValue = event.target.value;
    }
}

meta file

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>51.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__AppPage</target>
        <target>lightning__RecordPage</target>
        <target>lightning__HomePage</target>
        <target>lightningCommunity__Page</target>
    </targets>
</LightningComponentBundle>

And my Apex class

public without sharing class searchListController {
    @AuraEnabled
    public static void addBookRecord(String title, String author){
        if(String.isNotBlank(title) && author != null)
        {
            book_query__c newQuery = new book_query__c();
            newQuery.title_query__c = title;
            newQuery.author_query__c = author;
            newQuery.title_and_author__c = title + author;
            upsert newQuery title_and_author__c;
        }
    }
}

meta

<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>51.0</apiVersion>
    <status>Active</status>
</ApexClass>
1

You need to grant Profile access to the Apex class searchListController. If, as sounds to be the case, you're intending to expose this functionality to unauthenticated users through a public Community, you'd need to add it to the Site Guest User profile for that Community.

1
  • Thank you so much! – senoron Apr 6 at 15:16
0

Your random user's community profile needs to have access to your apex class, searchListController. Do the same for your guest user's community profile as well if unauthenticated users need to run this component as well.

1
  • Thank you so much! – senoron Apr 6 at 15:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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