Salesforce LWC學習(四十) dynamic interaction 淺入淺出 Salesforce LWC學習(三十) lwc superbadge項目實現

本篇參考:

Configure a Component for Dynamic Interactions in the Lightning App Builder - Salesforce Lightning Component Library

Salesforce Help | Article

GitHub - trailheadapps/dreamhouse-lwc: Sample application for Lightning Web Components on Salesforce Platform. Part of the sample gallery. Real estate use case. Get inspired and learn best practices.

Salesforce LWC學習(三十) lwc superbadge項目實現

背景描述: 我們今天看的demo是salesforce的dream house的UI,這個demo在 salesforce developer gallary中可以查詢到,上述的git hub是它的源代碼。主要功能是一個賣房的應用,可以通過條件查詢需要的房源,點擊房源可以查看到房源詳情以及中介詳情等信息,和我們之前做的superbadge整體功能很相似,使用到的技術以及排版等基本相同,即一個 lightning app builder中有幾個 lwc component,通過message channel進行組件間通訊。大概UI如下圖所示

本來這個是一個沒啥好說的demo,但是眼神好的我看到了右側的詳情頁面是可以編輯的。因爲詳情頁的組件使用的 lightning-record-form,只要有權限,就會展示編輯頁面。問題就來了。

1. 如果右側的信息更改了,中間的內容是否可以動態改變呢? 

2. 如果中間內容不能級聯改變的話,需要什麼樣的交互方式可以通知他進行動態改變呢?

針對以上的兩個問題,第一個是當前的代碼肯定沒法動態改變,所以我們需要改變我們的代碼。第二個問題,我們可以使用message channel,但除了 message channel以外,我們還有沒有其他的方式進行跨組件交互呢? 這裏引出了我們今天的主角: Dynamic Interaction.

一. Dynamic Interaction

我們應該在今年年初的新聞中,就可能看到過salesforce針對 lightning app builder要推出一個low code工具用來實現不同組件之間的交互。使用Dynamic Interaction,Lightning頁面上某個組件中發生的事件,例如用戶單擊列表視圖中的某個item,可以更新頁面上的其他組件。Dynamic Interactions允許管理員使用基於用戶交互的組件創建應用程序,所有這些組件都在Lightning App Builder UI中進行通信和轉換。官方的demo中,舉得是列表點擊,詳情頁展示的demo,類似於了 message channel的功能。那Dynamic Interaction 有什麼需要考慮的?

  • 當目標組件的屬性顯示在事件屬性編輯器中時,將忽略目標組件中的信息組件。
  • 如果爲包含動態交互的頁面切換頁面模板,則可用模板列表僅顯示支持動態交互的模板。
  • 當觸發以Aura Component爲目標的交互時,Aura Component會重新渲染。
  • 在富文本編輯器中輸入表達式時,autocomplete不起作用。
  • 組件的事件元數據在Lightning頁面上使用或作爲託管包的一部分發布後,不允許進行某些破壞性更改,例如刪除事件、重命名屬性或更改屬性類型。

 有什麼限制呢?

  • Dynamic interaction 目前只支持在 app page
  • 只有LWC自定義組件可以是事件源,但頁面上出現的任何組件(Aura或LWC)都可以是目標組件。
  • 基於自定義頁面模板的頁面不支持Dynamic Interaction(目前只能使用官方的那幾個標準的 app template)。
  • 只有String和Rich Text類型的屬性可以使用表達式來定義它們的值。
  • Event是交互中表達式支持的唯一上下文。
  • 只能對String、Integer和Boolean類型的屬性使用表達式。
  • 不能將目標屬性值設置爲數組或列表,例如多選選擇列表。
  • 可以使用metadata API將String屬性的目標屬性值設置爲空,但不能在Lightning App Builder UI中設置。
  • Dynamic Interaction在Salesforce移動應用程序或傳統平板電腦移動體驗中的Mobile Only應用程序中不起作用。
  • 當依賴屬性根據所做的選擇或在另一個屬性中輸入的值自動填充時,除非通過單擊或tab 去 focus在依賴屬性字段,否則不會保存自動填充的值。

所以使用之前需要注意瞭解這些限制,否則配置完成以後很容易產生困惑爲什麼不生效。

二. Dynamic Interaction的使用方法

我們以下面的demo進行講解,下圖是 Dream House的組件組成部分。我們所需要用到以及改動的是propertyTileList以及 proprtySummary

我們先修改一下 propertySummary的代碼。

 propertySummary.html: lightning-record-form 增加了 onsuccess邏輯

<lightning-record-form
      object-api-name="Property__c"
      record-id={propertyId}
      fields={propertyFields}
      columns="2"
      onsuccess={handleSuccessAction}
>
</lightning-record-form>

propertySummary.js:  增加這個方法,創建一個自定義的事件。

handleSuccessAction(event) {
        let updatePropertyId = JSON.stringify(new Date());
        const itemUpdated = new CustomEvent('itemUpdated', {
            detail: {updateTimeStamp: updatePropertyId}
        });
        this.dispatchEvent(itemUpdated);
}

propertySummary.js-meta.xml:在 targetConfig 爲 lightning_AppPage下,增加以下粗體的 event屬性以及schema屬性。其中 property內容設置我們要傳遞的參數

<?xml version="1.0" encoding="UTF-8" ?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>55.0</apiVersion>
    <isExposed>true</isExposed>
    <masterLabel>Property Summary</masterLabel>
    <targets>
        <target>lightning__AppPage</target>
        <target>lightning__RecordPage</target>
    </targets>
    <targetConfigs>
        <targetConfig targets="lightning__AppPage">
            <supportedFormFactors>
                <supportedFormFactor type="Large" />
                <supportedFormFactor type="Small" />
            </supportedFormFactors>
            <event name="itemUpdated" label="Item Updated" description="This event fires when an item is Updated.">
                <schema>
                    {
                        "type": "object",
                        "properties": {
                            "updateTimeStamp": {
                                "type": "string",
                                "title": "Update timestamp",
                                "description": "changed time stamp value"
                            }
                       }
                    }
                </schema>
            </event>
            
        </targetConfig>
        <targetConfig targets="lightning__RecordPage">
            <objects>
                <object>Property__c</object>
            </objects>
            <supportedFormFactors>
                <supportedFormFactor type="Large" />
                <supportedFormFactor type="Small" />
            </supportedFormFactors>
        </targetConfig>
    </targetConfigs>
</LightningComponentBundle>

propertyTileList.js: 

import { LightningElement, wire,track,api } from 'lwc';
import {
    publish,
    subscribe,
    unsubscribe,
    MessageContext
} from 'lightning/messageService';
import FILTERSCHANGEMC from '@salesforce/messageChannel/FiltersChange__c';
import PROPERTYSELECTEDMC from '@salesforce/messageChannel/PropertySelected__c';
import getPagedPropertyList from '@salesforce/apex/PropertyController.getPagedPropertyList';
import { refreshApex } from '@salesforce/apex';

const PAGE_SIZE = 9;

export default class PropertyTileList extends LightningElement {
    pageNumber = 1;
    pageSize = PAGE_SIZE;

    searchKey = '';
    maxPrice = 9999999;
    minBedrooms = 0;
    minBathrooms = 0;

    @track clickedPropertyId;

    @track previousTimeStamp;

    @api set updateTimeStamp(value) {
        if(this.previousTimeStamp != value) {
            refreshApex(this.properties);
            this.previousTimeStamp = value;
        }
    }

    get updateTimeStamp() {
        return this.previousTimeStamp;
    }


    @wire(MessageContext)
    messageContext;

    properties;

    @wire(getPagedPropertyList, {
        searchKey: '$searchKey',
        maxPrice: '$maxPrice',
        minBedrooms: '$minBedrooms',
        minBathrooms: '$minBathrooms',
        pageSize: '$pageSize',
        pageNumber: '$pageNumber'
    })
    wiredProperties(result) {
        this.properties = result;
    }

    

    connectedCallback() {
        this.subscription = subscribe(
            this.messageContext,
            FILTERSCHANGEMC,
            (message) => {
                this.handleFilterChange(message);
            }
        );
    }



    disconnectedCallback() {
        unsubscribe(this.subscription);
        this.subscription = null;
    }

    handleFilterChange(filters) {
        this.searchKey = filters.searchKey;
        this.maxPrice = filters.maxPrice;
        this.minBedrooms = filters.minBedrooms;
        this.minBathrooms = filters.minBathrooms;
    }

    handlePreviousPage() {
        this.pageNumber = this.pageNumber - 1;
    }

    handleNextPage() {
        this.pageNumber = this.pageNumber + 1;
    }

    handlePropertySelected(event) {
        const message = { propertyId: event.detail };
        this.clickedPropertyId = message;
        this.updateTimeStamp = message;
        publish(this.messageContext, PROPERTYSELECTEDMC, message);
    }
}

propertyTileList.js-meta.xml

<?xml version="1.0" encoding="UTF-8" ?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>55.0</apiVersion>
    <isExposed>true</isExposed>
    <masterLabel>Property Tile List</masterLabel>
    <targets>
        <target>lightning__AppPage</target>
    </targets>
    <targetConfigs>
        <targetConfig targets="lightning__AppPage">
            <property name="updateTimeStamp" type="String"></property>
            <supportedFormFactors>
                <supportedFormFactor type="Large" />
                <supportedFormFactor type="Small" />
            </supportedFormFactors>
        </targetConfig>
    </targetConfigs>
</LightningComponentBundle>

以上是代碼改動部分。接下來是配置部分。因爲這個是自定義的 template的 lightning app page,所以並不支持 dynamic interaction。

我們使用標準的 template,然後將這兩個組件拖動出來。這裏選中了 propertyTileSummary組件以後,右側就可以顯示 Interaction 這個 Tab,我們就可以點擊 Add Interaction去設置 dynamic interaction.

這裏source以及event是沒法更改的,目前 interaction只支持Update Properties,後續有可能會新增。updateTimeStamp使用 {!event.}的方式進行動態的賦值。實現propertySummary的事件註冊以後,就會將變量動態交互賦值給 propertyTileList的updateTimeStamp變量。我們將這個字段設置了set,只要有變量,就refreshApex,從而實現只要右側組件更新,左側的列表也會自動的更新。

至此配置完成。結果展示如下:

1. 我們點擊了一個item,右側進行編輯,將3更改成2.

2. save以後,左側的列表也會自動的變更。

總結: dynamic interaction目前支持性還是有限,但是salesforce按照目前的情況後續還會不斷的增強。瞭解目前的限制以及如何實現就OK,期待後續可以更多的使用場景以及更少的限制。篇中有錯誤歡迎指出,有不懂歡迎留言。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章