import関連
Apexを読み込む際
import メソッド名 from '@salesforce/apex/Apexクラス名.メソッド名
import getBoatTypes from '@salesforce/apex/BoatDataService.getBoatTypes';
wire, track, api
import { LightningElement, wire } from 'lwc';
参考:
[LWC] 変数宣言時のデコレータ (@api, @track, @wire) | Salesforceのはじめ
wire
@wire
は、組織からデータを取得できるデコレータ.- コンポーネントが読み込まれた場合に処理される
- ボタンなどの処理によってイベント的に、故意にApexを呼び出したい場合はImperative Apexを検討する
@wire
を使ってメソッドを呼び出す場合は下記の文法となる.
@wire(getRecord, { recordId: '$recordId', fields: FIELDS }) wiredMethodName({error, data}) { if(error) { // error logic } else if(data) { // expected logic } }
- apex classを呼び出す場合は、Apex側の引数(
param1
)とJs側の変数(val1
)を下記のように記載.
@wire(someApexMethod, { param1: '$val1', param2: '$val2' }) wiredMethod({error, data}) { // ... }
参考: Wire Apex Methods to Lightning Web Components
※ Imperative apexの場合は someApexMethod({ param1: val1, param2: val2 })
でcallする。
Call Apex Methods Imperatively
getFieldValue
- wireで取得した後に値を取得する標準関数
- 参考: getFieldValue
- 引数はレコードと項目名
import { getRecord, getFieldValue } from 'lightning/uiRecordApi'; import { LightningElement, api, wire } from 'lwc'; import { getRecord, getFieldValue } from 'lightning/uiRecordApi'; import REVENUE_FIELD from '@salesforce/schema/Account.AnnualRevenue'; import CREATED_FIELD from '@salesforce/schema/Account.CreatedDate'; import EXP_FIELD from '@salesforce/schema/Account.SLAExpirationDate__c'; const fields = [REVENUE_FIELD, CREATED_FIELD, EXP_FIELD]; export default class WireGetValue extends LightningElement { @api recordId; @wire(getRecord, { recordId: '$recordId', fields }) account; get revenue() { return getFieldValue(this.account.data, REVENUE_FIELD); } // ... }
track
子要素のみを変更した際に値を再描画させるデコレータ
ちなみに@trackは特に指定しなくても良くなったっぽい(Summer'20から)
Lightning Web コンポーネントで不要になった @track デコレータ
api
@api
を用いると、外部に変数や関数を公開するデコレータ.
要はデコレートした変数をpublic扱いにして、他コンポーネントからも参照・変更を可能にすることが可能.
基本的には親コンポーネントから子コンポーネントへの値の受け渡しで使われる.
refreshApex
cacheable=true
になっているApexメソッド、かつLWCから呼び出した際にキャッシュクリアさせる場合に使用- importして、キャッシュされている変数に対して実行
import { refreshApex} from '@salesforce/apex'; await refreshApex(this.data);
参考: Client-Side Caching of Apex Method Results
async/await
- 非同期でLWCからApexを実行させる場合
import ApexMethod1 from '@salesforce/apex/ApexClass.ApexMethod1'; import ApexMethod2 from '@salesforce/apex/ApexClass.ApexMethod2'; import ApexMethod3 from '@salesforce/apex/ApexClass.ApexMethod3'; async handleOKClick(event) { // Apexクラスのメソッドを呼び出す const result1 = await ApexMethod1({param: 1}); const result2 = await ApexMethod2({param: 2}); const result3 = await ApexMethod3({param: 3}) }
- 参考
note.com
静的リソースを読み込む際
import myResource from '@salesforce/resourceUrl/resourceReference';
resourceReference
がアップロードしたファイル名.
静的リソースにJavascriptやcssがある場合
loadScript()
、loadStyle()
という関数が用意されている.- ちなみに返却されるのはそれぞれPromiseになる.
- 例えば上記の通り、
myResource
をimportした場合の例.
import { loadStyle, loadScript } from 'lightning/platformResourceLoader'; // ... Promise.all([ loadScript(this, myResource + '/sample.js'), loadStyle(this, myResource + '/sample.css') ]).then(() => { // logic }) .catch(error => { const toast = new ShowToastEvent({ title: ERROR_TITLE, message: error.message, variant: ERROR_VARIANT, }); this.dispatchEvent(toast); }); }
カスタム表示ラベル
- Apexなどから呼び出せるカスタムラベルで、翻訳も可能なもの
- help: カスタム表示ラベル
import labelSample from '@salesforce/label/c.Sample';
SLDS (HTML)
combobox
- いわゆる選択リストコンポーネント
HTMLに記述する例:
- value
: 選択された値
- options
: 選択できる値
- onchange
: Jsに発火するイベント
<template> <lightning-combobox name="progress" label="Status" value={value} placeholder="Select Progress" options={options} onchange={handleChange} ></lightning-combobox> <p>Selected value is: {value}</p> </template>
選択された値は下記で取得
handleChange(event) { this.value = event.detail.value; }
Formatted Number
- 小数点の桁数を指定.
<p><lightning-formatted-number value="1234.5678" maximum-fraction-digits="2"></lightning-formatted-number></p>
spinner
- いわゆるクルクルのLoadingアイコン.
- Spinner
<div class="exampleHolder"> <lightning:spinner alternativeText="Loading" size="small" /> </div>
Tabset
- LWC上のタブを生成する
variant
を指定することが可能で、scoped
に指定した場合デザインが変わる- 標準
- Scoped
<template> <lightning-tabset variant="scoped"> <lightning-tab label="Item One"> One Content ! </lightning-tab> <lightning-tab label="Item Two" title="2nd tab extended title"> Two Content ! </lightning-tab> <lightning-tab label="Item Three"> Three Content ! </lightning-tab> </lightning-tabset> </template>
参考: lightning-tabset
Datatable
- データテーブルを作成する
- 保存時にJavaScriptへのアクションを行いたい際は
onsave={functionName}
としておく - インライン編集を有効化したい場合は
column
で指定した値にeditable : 'true'
を指定しdraft-values={draftValues}
を指定
const columns = [ { label: 'Name', fieldName: 'Name', editable: true }, { label: 'Description', fieldName: 'Description__c'}, ];
<lightning-datatable key-field="Id" data={data} columns={columns} draft-values={draftValues} onsave={handleSave} hide-checkbox-column></lightning-datatable>
詳しいやり方はこちら: Display Data in a Table with Inline Editing
仕様についてはこちらのWorking with Inline Editing
章を確認
lightning card / button & slot
slot
とかいうのがいきなりでてきたのでよくわからずだったのですが.
lightning-cardの中でbuttonを使用する際に slot="actions"
と指定するとボタンがタイトルの反対側に配置されるようです.
これはplaygroundでやってみたらわかりやすいかと.
<lightning-card title="Hello"> <lightning-button label="New" slot="actions"></lightning-button> <p class="slds-p-horizontal_small">Card Body (custom component)</p> <p slot="footer">Card Footer</p> </lightning-card>
参考: lightning-card
参考: lightning-button
<lightning-button label="Submit" type="submit" icon-name="utility:save"></lightning-button>
ページの遷移
ページの遷移はURLを直接指定ではなく、NavigationMixin
を使用してURL生成や遷移を行うようです.
navigation
例えば、レコードページに遷移させる場合は下記:
optionはview
、new
、home
などがあるっぽい.
<lightning-card title="Test"> <lightning-button label="Test" onclick={createNewData} slot="actions"></lightning-button> </lightning-card>
import { NavigationMixin } from 'lightning/navigation'; export default class MyCustomElement extends NavigationMixin(LightningElement) { // logic createNewData() { this[NavigationMixin.Navigate] ({ type: 'standard__objectPage', attributes: { objectApiName: 'Data__c', actionName: 'view' }, }); } }
参考: Basic Navigation
あるレコードの値をリンクにしたい場合
- HTML側から
data-record-id
属性でリンクしたいレコードを指定 - JavaScript側で
event.target.dataset.recordId
を指定してHTML側から指定された値を取得する
<a title="Test" onclick={navigateToRecord} data-record-id={Data.CreatedBy.Id}>
navigateToRecord(event) { this[NavigationMixin.Navigate] ({ type: 'standard__ recordPage', attributes: { recordId: event.target.dataset.recordId, objectApiName: 'User', actionName: 'view' }, }); }
公式のやり方は見つからず...
Record View Form
いつもレコードを見ているあのデザインをサクッと
参考: Record View Form
<lightning-record-view-form record-id={recordId} object-api-name={objectApiName} density="compact"> <template if:true={showFields}> <lightning-output-field field-name="Name"></lightning-output-field> <lightning-output-field field-name="Industry"></lightning-output-field> </template> </lightning-record-view-form>
Record Edit Form
参考: Record Edit Form
lightning-record-edit-form
はFormを描画し、例えばボタンでレコードのsubmitを行う場合はlightning-button
のtype="submit" とすること- defaultではsubmitはonclickで行うが、その処理をカスタマイズすることも可能
- 上記の
Overriding Default Behaviors
章を参照 - onsubmitにて、
handleSubmit
を行い、デフォルトのsubmitをevent.preventDefault();
で防止している - onsucessにて、
handleSucess
内でレコードの変更を処理
- 上記の
handleSubmit(event){ event.preventDefault(); // stop the form from submitting const fields = event.detail.fields; fields.Street = '32 Prince Street'; this.template.querySelector('lightning-record-edit-form').submit(fields); } handleSucess(event){ const updatedRecord = event.detail.id; console.log('onsuccess: ', updatedRecord); }
- formのリセットは下記の通りで,
lightning-input-field
に対して値を取得してresetする
handleReset(event) { const inputFields = this.template.querySelectorAll('lightning-input-field'); if (inputFields) { inputFields.forEach(field => { field.reset(); }); } }
Form
参考: Form Elements
- Formエレメントは、slds-form-element
によって初期化される
- 3つの要素で構成される;
- label slds-form-element__label
- form control container slds-form-element__control
- form input element, i.e.
Input Field
<div class="slds-form-element"> <label class="slds-form-element__label" for="account">Test</label> <div class="slds-form-element__control"> <lightning-input-field field-name="account" variant="label-hidden" required></lightning-input-field> </div> </div>
スクロール
要素をスクロールさせたい時。Auto、x軸(横スクロール)、y軸(縦スクロール)が存在する
<div class="slds-scrollable_y" style="height:5rem;width:24rem">
要素を真ん中に
<div class="slds-align_absolute-center" style="height:5rem">This content will be positioned in the absolute center of its container</div>
Lightning Layout Item
- これをやりたい場合
- レコードを表示させたい場合は、
key
attributeにレコードIdを渡す。
<lightning-layout-item key={data.Id} padding="around-small" size="12" small-device-size="6" medium-device-size="4" large-device-size="4">
参考: Layout Item
Javascript
カスタムイベントの作成
detail
のプロパティ名はきまっているらしい
// カスタムイベントの作成 const event = new CustomEvent('eventname', { detail: 'Hello world' }); // カスタムイベントをListenする elem.addEventListener('eventname', function(e) { console.log(e.detail); }); // カスタムイベントを発行する elem.dispatchEvent(event); // -> 'Hello world'
ブラウザから位置情報を取得する
- JavaScriptの標準機能を使用する.
syncer.jp - 端末がGeolocation APIに対応しているか確認.
if( navigator.geolocation ) { // }
navigator.geolocation.getCurrentPosition()
を使用する。引数は3つで必須は1つ。成功時に何をするのかの関数.- 成功した場合のデータは指定した
関数名.coords
に格納されている。- 例えば
position.coords.latitude
.
- 例えば
if(navigator.geolocation) { navigator.geolocation.getCurrentPosition(postion => { this.latitude = position.coords.latitude; this.longitude = position.coords.longitude; }); }
unshift関数
arrayの先頭に要素を追加する.
LWC
要素のループ
- JavaScipt側の変数名を指定
- 例だとJavaSciprt側に
vals
変数が存在
- 例だとJavaSciprt側に
<template>
にLoop文法を記述
<template for:each={vals} for:item="val">
参考: Render Lists
HTML側での条件分岐
<template if:true={isLoading}> <lightning-spinner alternative-text="Loading" variant="brand" size="large"></lightning-spinner> </template>
LWCの背景を画像にする
- 静的リソースのURLを
background-image:url()
で返せばよい。 - 参考: setting background image in lightning web component - Salesforce Stack Exchange.
<template> <div style={backgroundStyle}> </div> </template>
import { LightningElement } from 'lwc'; import backgroundUrl from '@salesforce/resourceUrl/background'; export default class Poc extends LightningElement { get backgroundStyle() { return `background-image:url(${backgroundUrl})`; } }
Component同士の通信
Component Namespace
- 他コンポーネントを参照する際に、いくつかルールがあるようなのでメモ
参考: Component Folder - component名はキャメルケースを使用する
- 参照する際はキャメルケースで区切られた名前を
-
で区切る
例:myComponent.html
がある場合
<c-my-component></c-my-component>
Custom Event
- 基本的には 子 → 親にイベントを飛ばしたいときに行う
JavaScriptだとListenerを明記するが、LWCの場合は下記となる
const customEventTest = new CustomEvent('customeventtest', { detail: {dataId: this.selectetDataId} });
- 上記の子側JavaScriptで明記されたイベント名
'customeventtest'
に対して、親側のhtml側でon + イベント名
とする
<c-custom-event-created oncustomeventtest={eventHandle}></c-custom-event-created
eventHandle(event) { this.data = event.detail; }
詳しくは下記(めっちゃわかりやすい)
参考(英語):
参考(公式): Create and Dispatch Events
@api
(親コンポーネント → 子コンポーネントの通信)
@api
を使う.- public propertyにする方法と、public methodにする方法がある.
public property
- 子側のJavaScriptで
@api
でデコレータされた値がmyVariable
だった場合 - かつ子側のコンポーネント名が
myCoponent.html
だった場合- 親側での参照は下記のようになる
<c-my-component my-variable="Test"></c-my-component>
参考: Set Properties on Child Components
public method
- 親コンポーネントから子コンポーネントのJavascriptメソッドを直接callすることが可能になる.
Call Methods on Child Components
親側から子コンポーネントメソッドを呼び出す例:this.template.querySelector('')
を使用する.
this.template.querySelector('c-video-player').play();
※ちなみに、public (@api) のgetter/setterを呼び出す場合は普通にmethod名をそのままコールできるよう.
<c-sample getter-name={data}></c-sample>
Lightning Message Service
- LWC/Aura/Visualforce間でのPublish <-> Subscribeでの通信が可能となる.
Lightning message channelを作成
- 参考: Create a Message Channel
force-app/main/default/messageChannels/
ディレクトリにxmlファイルを作成する.- Subscribeする側のJsファイルから定義したMessage Channelをimportする.
import channelName from '@salesforce/messageChannel/channelReference';
channelName
は任意.channelReference
は作成したxmlファイルの名前 +__c
.
Subscribeする
@wire
でMessege ServiceのmessageContext
を初期化する.
@wire(MessageContext) messageContext;
- subscribeメソッドを記述.
- 参考: Subscribe and Unsubscribe from a Message Channel
- Message Sreviceの詳しい値の説明: Message Service Reference
subscribeToMessageChannel() { if (!this.subscription) { this.subscription = subscribe( this.messageContext, channelName, (message) => {this.dataId = message.recordId}, { scope: APPLICATION_SCOPE } ); } } // Standard lifecycle hooks used to subscribe and unsubsubscribe to the message channel connectedCallback() { this.subscribeToMessageChannel(); }
publishする
- publishメソッドは3つの引数
messageContext
,Message Service
,Message
const payload = {recordId: dataId}; publish(this.messageContext, MC, payload);
ToastMessage (UIにメッセージを表示)
- 下記のようなポップアップメッセージ的なやつ.
- Platform Show Toast Event
import {ShowToastEvent} from 'lightning/platformShowToastEvent'; // ... const event = new ShowToastEvent({ title: ERROR_TITLE, message: error.message, variant: ERROR_VARIANT }); this.dispatchEvent(event);
Lightning Map & MapMarkers
- makerに値をセット.
<template> <lightning-map map-markers={mapMarkers}> </lightning-map> </template>
import { LightningElement } from 'lwc'; export default class LightningMapExample extends LightningElement { mapMarkers = [ { location: { Latitude: '37.790197', Longitude: '-122.396879', }, }, ]; }
getterとsetter
参考: Use Getters and Setters to Modify Data
- 関数名の最初に
get
やset
を付けることを忘れずに!
get sampleGetter() { return this.data ? "Yes" : "No"; } set itemName(value) { this.data = true; }
- publicなSetterを作成する場合は、getterも必ず作成する必要がある
- その場合、どちらかのmethodを
@api
デコレーションはしておくこと
metaデータ関連
Configuration タグ
- 重要なのは: