将Lightning Web Components开源转换为Salesforce

将Lightning Web Components开源转换为Salesforce – 使用Apex检索数据

使用Apex检索数据

您在上一个项目中构建的Node.js应用程序运行SOQL查询,以从Salesforce平台检索会话列表。为了在Salesforce上检索该数据,您需要将Node.js后端逻辑转换为Apex代码。Apex是一种强类型的,面向对象的编程语言,它使开发人员可以结合对API的调用在Salesforce服务器上执行流和事务控制语句。

注意

Apex仅在特定的用例中才需要,例如获取记录及其相关记录。与单个记录数据进行交互时,可以使用User Interface API的功能。这使您可以使用预构建的线适配器和函数仅通过JavaScript即可对记录执行CRUD操作,而无需编写任何Apex行。

在此步骤中,您将编写一个Apex控制器,该控制器执行SOQL查询并将其公开为可以由您的组件调用的端点。

创建一个Apex控制器

    1. 在VS Code中,右键单击该classes文件夹,然后单击SFDX:Create Apex Class
    2. 输入名称SessionController
    3. 如果VS Code询问,请选择force-app/main/default/classes作为要添加SessionController.cls到的目录。
    4. 在新打开的文件中,将默认代码替换为以下代码。
public with sharing class SessionController {
  @AuraEnabled(cacheable=true)
  public static List<Session__c> getSessions(String searchKey) {
    if (String.isBlank(searchKey)) {
      return [SELECT Id, Name, toLabel(Room__c), Description__c, format(Date_and_Time__c) dateTime,
      (SELECT Speaker__r.Id, Speaker__r.Name, Speaker__r.Description, Speaker__r.Email, Speaker__r.Picture_URL__c FROM Session_Speakers__r)
      FROM Session__c ORDER BY Date_and_Time__c LIMIT 100];
    } else {
      String key = '%' + searchKey + '%';
      return [SELECT Id, Name, toLabel(Room__c), Description__c, format(Date_and_Time__c) dateTime,
      (SELECT Speaker__r.Id, Speaker__r.Name, Speaker__r.Description, Speaker__r.Email, Speaker__r.Picture_URL__c FROM Session_Speakers__r)
      FROM Session__c WHERE Name LIKE :key ORDER BY Date_and_Time__c LIMIT 100];
    }
  }
  @AuraEnabled(cacheable=true)
  public static Session__c getSession(Id sessionId) {
    List<Session__c> sessions = [SELECT Id, Name, toLabel(Room__c), Description__c, format(Date_and_Time__c) dateTime,
      (SELECT Speaker__r.Id, Speaker__r.Name, Speaker__r.Description, Speaker__r.Email, Speaker__r.Picture_URL__c FROM Session_Speakers__r)
      FROM Session__c WHERE Id = :sessionId];
    if (sessions.size() != 1) {
      throw new AuraHandledException('Could not find session');
    }
    return sessions[0];
  }
}

@AuraEnabled(cacheable=true)声明将方法公开为端点,以便您的组件可以调用它们。它还支持对方法返回的数据进行客户端缓存。您在此处编写的代码比其Node.js等效代码短,因为您不必担心身份验证或异步运行查询。

  1. 保存SessionController.cls

使用电线检索数据

现在我们有了端点,让我们替换模拟数据实现,并使用Wire Service用真实数据检索会话记录。此服务是Salesforce平台上的特殊实现,它使用声明性方法提供了优化的读取操作和客户端缓存。让我们看看如何构建它。

    1. 打开sessionList.js
    2. 用以下代码替换前两行中的导入代码。
import { LightningElement, wire } from 'lwc';
import getSessions from '@salesforce/apex/SessionController.getSessions';

这将导入从您的Apex方法自动生成的电线适配器。 

    1. 在下面添加以下代码 sessions = [];
searchKey = '';
@wire(getSessions, { searchKey: '$searchKey' })
wiredSessions({ error, data }) {
  if (data) {
    this.sessions = data;
  } else if (error) {
    this.sessions = [];
    throw new Error('Failed to retrieve sessions');
  }
}

电线使用getSessions映射到我们的Apex端点的适配器。使用searchKey映射到searchKey属性的参数调用导线。请注意,参数值以带有$前缀的字符串形式传递。这意味着此参数是反应性的:每次searchKey更改时都会调用电线。

    1. 删除connectedCallback功能。
    2. handleSearchKeyInput以下代码替换该函数。
handleSearchKeyInput(event) {
  clearTimeout(this.delayTimeout);
  const searchKey = event.target.value;
  // eslint-disable-next-line @lwc/lwc/no-async-operation
  this.delayTimeout = setTimeout(() => {
      this.searchKey = searchKey;
  }, 300);
}

不再在客户端执行过滤。searchKey现在将其传递到线路,以便Apex返回已过滤的会话列表。您正在searchKey通过对更新应用300毫秒的延迟来取消更新属性。这是为了避免大量的Apex方法调用。

    1. 将该handleSessionClick函数替换为:
handleSessionClick(event) {
  const { sessionId } = event.currentTarget.dataset;
  const navigateEvent = new CustomEvent('navigate', {
    detail: {
      state: 'details',
      sessionId: sessionId
    }
  });
  this.dispatchEvent(navigateEvent);
}

现在,您可以使用会话记录ID而不是会话列表索引来导航到会话详细信息页面。

    1. 保存sessionList.js
    2. 打开sessionList.html
    3. 用以下代码替换文件内容。
<template>
  <div class="list">
    <input type="search" placeholder="Search sessions..."
     oninput={handleSearchKeyInput} />
    <template for:each={sessions} for:item="session">
      <a key={session.Id} class="session" data-session-id={session.Id} onclick={handleSessionClick}>
         <div>
           <p class="title">{session.Name}</p>
           <p class="icon time">{session.dateTime}</p>
           <p class="icon room">{session.Room__c}</p>
         </div>
         <template if:true={session.Session_Speakers__r}>
           <div class="speaker-pictures">
             <template for:each={session.Session_Speakers__r} for:item="speaker">
               <img key={speaker.Speaker__r.Id} src={speaker.Speaker__r.Picture_URL__c}
                  alt={speaker.Speaker__r.Name} title={speaker.Speaker__r.Name}>
              </template>
           </div>
       </template>
     </a>
    </template>
  </div>
</template>

模板结构基本保持不变,但是现在您使用Salesforce记录字段名称。就像您之前在Node.js后端中所做的那样,这省去了用JavaScript映射字段名称的工作。在真实的项目中,您将直接在组件模板中使用Salesforce字段名称。

    1. 保存 sessionList.html.
    2. 打开 sessionDetails.js.
    3. 将文件内容替换为:
import { LightningElement, api, wire } from 'lwc';
import getSession from '@salesforce/apex/SessionController.getSession';
export default class SessionDetails extends LightningElement {
  @api sessionId;
  session;
  @wire(getSession, { sessionId: '$sessionId' })
  wiredSession({ error, data }) {
    if (data) {
      this.session = data;
    } else if (error) {
      this.session = undefined;
      throw new Error('Failed to retrieve session');
    }
  }
  handleSessionsClick() {
    const navigateEvent = new CustomEvent('navigate', {
      detail: {
        state: 'list'
      }
    });
    this.dispatchEvent(navigateEvent);
  }  
}

就像for一样sessionList,您将getSessionApex方法连接到session属性。您将sessionId公共属性作为反应性参数传递给getSession

    1. 保存sessionDetails.js
    2. 打开sessionDetails.html
    3. 将文件内容替换为:
<template>
  <template if:true={session}>
    <h2><a href="#" onclick={handleSessionsClick}>Sessions</a> > {session.Name}</h2>
    <p class="icon time">{session.dateTime}</p>
    <p class="icon room">{session.Room__c}</p>
    <h3>Abstract</h3>
    <div class="abstract">{session.Description__c}</div>
    <h3>Speakers</h3>
    <div class="speaker-list">
      <template if:true={session.Session_Speakers__r}>
        <template for:each={session.Session_Speakers__r} for:item="speaker">
          <c-speaker-card key={speaker.Speaker__r.id} speaker={speaker.Speaker__r}>
          </c-speaker-card>
        </template>
      </template>
    </div>
  </template>
</template>
    1. 保存sessionDetails.html
    2. 打开speakerCard.html
    3. 用以下代码替换文件内容。
<template>
  <div class="card">
    <div class="header">
      <img src={speaker.Picture_URL__c} alt="Speaker picture">
      <div>
        <p class="title">{speaker.Name}</p>
        <p class="icon email">{speaker.Email}</p>
      </div>
    </div>
    {speaker.Description}
  </div>
</template>
  1. 保存speakerCard.html
  2. 通过右键单击force-app文件夹并单击SFDX:将源部署到组织来重新部署组件。

会话列表显示平台数据的完整应用程序。

项目总结

恭喜你!您已成功转换了Lightning Web Component开源应用程序并将其部署在Salesforce平台上。

您刚刚了解了Salesforce平台提供的强大声明功能,从而减少了构建应用程序所需实现的代码量。查看其他许多Lightning Web Component项目和模块,以了解有关使您更快地构建现代应用程序的技术的更多信息。

你可能也会喜欢...