Lightning Web Components由浅入深


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332907/a1ddd1dd-5393-8a5b-e725-b66154313a78.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332907/cf4f2087-8ec9-6b7f-9080-8ea5cc30ea08.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332907/7721091d-c07a-f21f-2ccf-a80d1b4eb89a.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332907/cb674290-1a72-a741-b746-37d1d4659a1c.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332907/38b1354f-bbf6-f0f1-4792-4e35c256a678.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332907/0f777550-06e0-95fb-5bc2-0149c6a3e874.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332907/bc5d524c-10f1-b6c0-eba0-4e96e254e5b1.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332907/65b51ff3-9f75-5c4b-762a-8c31f8b53721.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332907/bcf0bac0-6e73-8f89-5b2a-05963de6b702.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332907/0452c048-a85e-0c78-2eef-522e30bd793c.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332907/debe4c93-1951-75a9-cdd1-1f696d894f6c.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332907/43f308f9-14fb-b6b4-ffff-ad1748046188.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332907/57ff0ce6-5314-a0dc-ec99-c701ee0471b9.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332907/d176df7a-d76b-7261-dae6-d6916c5445ba.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332907/800974a7-a59e-8a39-e071-dd228d0abc7d.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332907/cd71b10e-1f67-8841-6125-7c51db6b0953.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332907/4b41259a-03e8-4945-d9ac-ff8bb7b8c3f4.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332907/239c9f32-e4e7-7ce2-374a-cc851a27c5dc.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332907/00f6bd7f-53a9-881c-da8f-f8883276f73b.png)

#实例学习
##1.dataTableComponent
通过该实例练习，我们会掌握下面相关知识点的运用：

- lightning-datatable 的使用
- Popup Modal画面
- 子通知父（子→父）：CustomEvent
- 共享JS代码

```java:dataTableLWC.cls
public with sharing class dataTableLWC {
	@AuraEnabled(cacheable = true)
	public static List<Account> fetchAccounts(){
		return [SELECT Id,Name,Phone,Type,Industry,Rating,Website FROM Account LIMIT 100];
	}
}
```

```javascript:commonUtils.js
import {ShowToastEvent} from 'lightning/platformShowToastEvent'
const showToastInfo = (that, message, mode) => {
	const modevalue = (mode != null ? mode : 'dismissable');
	const event = new ShowToastEvent({
		title: 'info',
		message: message,
		variant: 'info', //info/success/warning/error
		mode: modevalue //sticky：クローズボタンを押すまで表示　pester：3秒間表示　dismissable：sticky+pester
	});
	that.dispatchEvent(event);
};
const showToastSuccess = (that, message, mode) => {
	const modevalue = (mode != null ? mode : 'dismissable');
	const event = new ShowToastEvent({
		title: 'success',
		message: message,
		variant: 'success', //info/success/warning/error
		mode: modevalue //sticky：クローズボタンを押すまで表示　pester：3秒間表示　dismissable：sticky+pester
	});
	that.dispatchEvent(event);
};
const showToastWarning = (that, message, mode) => {
	const modevalue = (mode != null ? mode : 'dismissable');
	const event = new ShowToastEvent({
		title: 'warning',
		message: message,
		variant: 'warning', //info/success/warning/error
		mode: modevalue //sticky：クローズボタンを押すまで表示　pester：3秒間表示　dismissable：sticky+pester
	});
	that.dispatchEvent(event);
};
const showToastError = (that, message, mode) => {
	const modevalue = (mode != null ? mode : 'dismissable');
	const event = new ShowToastEvent({
		title: 'error',
		message: message,
		variant: 'error', //info/success/warning/error
		mode: modevalue //sticky：クローズボタンを押すまで表示　pester：3秒間表示　dismissable：sticky+pester
	});
	that.dispatchEvent(event);
};
export {showToastInfo,showToastSuccess,showToastWarning,showToastError};
```
```xml:commonUtils.js-meta.xml
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
	<apiVersion>48.0</apiVersion>
	<isExposed>false</isExposed>
</LightningComponentBundle>
```
```html:modalLwc.html
<template>
	<section role="dialog" tabindex="-1"
		aria-labelledby="modal-heading-01"
		aria-modal="true"
		aria-describedby="modal-content-id-1"
		class="slds-modal slds-fade-in-open">
		<div class="slds-modal__container">
			<header class="slds-modal__header">
				<button class="slds-button slds-button_icon slds-modal__close slds-button_icon-inverse" title="Close" onclick={closeModal}>
					<lightning-icon icon-name="utility:close" alternative-text="close" variant="inverse" size="small" ></lightning-icon>
				</button>
				<h2 id="modal-heading-01" class="slds-text-heading_medium slds-hyphenate">Record Detail</h2>
			</header>
			<div class="slds-modal__content slds-p-around_medium" id="modal-content-id-1">
				<dl class="slds-list_horizontal slds-wrap">
					<dt class="slds-item_label slds-truncate" title="Name">Name:</dt>
					<dd class="slds-item_detail slds-truncate">{record.Name}</dd>
					<dt class="slds-item_label slds-truncate" title="Phone">Phone:</dt>
					<dd class="slds-item_detail slds-truncate">{record.Phone}</dd>
					<dt class="slds-item_label slds-truncate" title="Type">Type :</dt>
					<dd class="slds-item_detail slds-truncate">{record.Type}</dd>
					<dt class="slds-item_label slds-truncate" title="Industry">Industry :</dt>
					<dd class="slds-item_detail slds-truncate">{record.Industry}</dd>
					<dt class="slds-item_label slds-truncate" title="Website">Website :</dt>
					<dd class="slds-item_detail slds-truncate">{record.Website}</dd>
					<dt class="slds-item_label slds-truncate" title="Rating">Rating :</dt>
					<dd class="slds-item_detail slds-truncate">{record.Rating}</dd>
				</dl>
			</div>
			<footer class="slds-modal__footer">
				<lightning-button variant="brand" label="Close" title="Close" onclick={closeModal}></lightning-button>
			</footer>
		</div>
	</section>
	<div class="slds-backdrop slds-backdrop_open"></div>
</template>
```
```javascript:modalLwc.js
import {LightningElement,track,api} from 'lwc';
export default class ModalLwc extends LightningElement {
	@api record = {};
	closeModal() {
		const selectEvent = new CustomEvent('close', {});
		this.dispatchEvent(selectEvent);
	}
}
```
```xml:modalLwc.js-meta.xml
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
	<apiVersion>48.0</apiVersion>
	<isExposed>false</isExposed>
</LightningComponentBundle>
```

```html:dataTableComponent.html
<template>
	<lightning-datatable 
		key-field="id"
		data={dataList}
		onrowaction={handleRowAction}
		row-number-offset={rowOffset}
		hide-checkbox-column="true"
		columns={columns}>
	</lightning-datatable>
	<template if:true={bShowModal}>
		<c-modal-lwc record={record} onclose={closeModal}></c-modal-lwc>
	</template>
</template>
```
```javascript:dataTableComponent.js
import {LightningElement,wire,track} from 'lwc';
import {showToastSuccess,showToastError} from 'c/commonUtils';
import fetchAccounts from '@salesforce/apex/dataTableLWC.fetchAccounts';
const columns = [
	{
		label: 'Name',
		fieldName: 'Name'
	},
	{
		label: 'Phone',
		fieldName: 'Phone'
	},
	{
		label: 'Type',
		fieldName: 'Type'
	},
	{
		label: '',
		type: 'button-icon',
		initialWidth: 75,
		typeAttributes: {
			iconName: 'action:preview',
			title: 'Preview',
			variant: 'border-filled',
			alternativeText: 'View'
		}
	}
];
export default class DataTableComponent extends LightningElement {
	@track columns = columns;
	@track record = {};
	@track rowOffset = 0;
	@track dataList = {};
	@track bShowModal = false;
	@wire(fetchAccounts)
	wiredFetchAccounts({error, data}) {
		if (data) {
			this.dataList = data;
			showToastSuccess(this, '処理を正常に完了しました。');
		} else if (error) {
			showToastError(this, error.body.message);
		}
	}
	handleRowAction(event) {
		const row = event.detail.row;
		this.record = row;
		this.bShowModal = true;
	}
	closeModal(event) {
		this.bShowModal = false;
	}
}
```
```xml:dataTableComponent.js-meta.xml
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
	<apiVersion>48.0</apiVersion>
	<isExposed>false</isExposed>
	<targets>
		<target>lightning__Tab</target>
	</targets>
</LightningComponentBundle>
```
##2.customSearch
通过该实例练习，我们会掌握下面相关知识点的运用：

- Html的入力数据传递到Js里面
- Apex方法的调用：Call a method imperatively
- 用单纯html结合SLDS，一览数据表示

```java:customSearchController.cls
public with sharing class customSearchController { 
	@AuraEnabled(cacheable=true)
	 public static list<contact> getContactList(string searchKey) {
		string sTempSearchKey = '%' + searchKey + '%';
		list<contact> lstContact = new list<contact>();
		for(contact oCon : [Select id,Name,Email,FirstName,LastName,Phone
							From Contact
							WHERE name LIKE : sTempSearchKey]){
			lstContact.add(oCon);
		}
		if(lstContact.size() == 0){
			throw new AuraHandledException('No Record Found..'); 
		}
		return lstContact;
	}
}
```
```html:customSearch.html
<template>
	<div class="slds-m-around_medium">
		<div class="slds-m-bottom_small">
			<lightning-input type="text" value={sVal} label="Contact Name" onchange={updateSeachKey}></lightning-input>
		</div>
		<lightning-button label="Search" onclick={handleSearch} variant="brand"></lightning-button>
		<table class="slds-table slds-table_cell-buffer slds-table_bordered slds-m-top_small">
			<thead>
				<tr class="slds-line-height_reset">
					<th class="" scope="col">
						<div class="slds-truncate" title="First Name">First Name</div>
					</th>
					<th class="" scope="col">
						<div class="slds-truncate" title="Last Name">Last Name</div>
					</th>
					<th class="" scope="col">
						<div class="slds-truncate" title="Phone">Phone</div>
					</th>
					<th class="" scope="col">
						<div class="slds-truncate" title="Email">Email</div>
					</th>
				</tr>
			</thead>
			<tbody>
				<template for:each={contacts} for:item="contact">
					<tr class="slds-hint-parent" key={contact.Id}>
						<td>
							<div class="slds-truncate">{contact.FirstName}</div>
						</td>
						<td>
							<div class="slds-truncate">{contact.LastName}</div>
						</td>
						<td>
							<div class="slds-truncate">
								<lightning-formatted-phone value={contact.Phone}></lightning-formatted-phone>
							</div>
						</td>
						<td>
							<div class="slds-truncate">
								<lightning-formatted-email value={contact.Email}></lightning-formatted-email>
							</div>
						</td>
					</tr>
				</template>
			</tbody>
		</table>
	</div>
</template>
```
```javascript:customSearch.js
import {LightningElement,track} from 'lwc';
import {showToastError} from 'c/commonUtils';
import getContactList from '@salesforce/apex/customSearchController.getContactList';
export default class customSearch extends LightningElement {
	@track contacts;
	sVal = '';
	updateSeachKey(event) {
		this.sVal = event.target.value;
	}
	handleSearch() {
		if (this.sVal !== '') {
			getContactList({searchKey: this.sVal})
				.then(result => {
					this.contacts = result;
				})
				.catch(error => {
					showToastError(this, error.body.message);
					this.contacts = null;
				});
		} else {
			showToastError(this, 'Search text missing..');
		}
	}
}
```
```xml:customSearch.js-meta.xml
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>48.0</apiVersion>
    <isExposed>false</isExposed>
    <targets>
       <target>lightning__Tab</target>
   </targets>
</LightningComponentBundle>
```
##3.datatableUpdateExample
该实例是 **Developer Guide** 里面的一个Sample。

- [Create a Data Table with Inline Editing](https://developer.salesforce.com/docs/component-library/documentation/en/lwc/data_table_inline_edit)

```java:ContactController.cls
public with sharing class ContactController {
	@AuraEnabled(cacheable=true)
	public static List<Contact> getContactList() {
		return [
			SELECT Id, FirstName, LastName, Title, Phone, Email
			FROM Contact
			WITH SECURITY_ENFORCED
			LIMIT 10
		];
	}
}
```
```html:datatableUpdateExample.html
<template>
	<lightning-card title="Datatable Example" icon-name="custom:custom63">
		<div class="slds-m-around_medium">
			<template if:true={contact.data}>
				<lightning-datatable
					key-field="Id"
					data={contact.data}
					columns={columns}
					onsave={handleSave}
					draft-values={draftValues}>
				</lightning-datatable>
			</template>
			<template if:true={contact.error}>
				<!-- handle Apex error -->
			</template>
		</div>
	</lightning-card>
</template>
```
```javascript:datatableUpdateExample.js
import { LightningElement, wire, track } from 'lwc';
import getContactList from '@salesforce/apex/ContactController.getContactList';
import { updateRecord } from 'lightning/uiRecordApi';
import { refreshApex } from '@salesforce/apex';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
const COLS = [
	{ label: 'First Name', fieldName: 'FirstName', editable: true },
	{ label: 'Last Name', fieldName: 'LastName', editable: true },
	{ label: 'Title', fieldName: 'Title' },
	{ label: 'Phone', fieldName: 'Phone', type: 'phone' },
	{ label: 'Email', fieldName: 'Email', type: 'email' }
];
export default class DatatableUpdateExample extends LightningElement {
	@track error;
	@track columns = COLS;
	@track draftValues = [];
	@wire(getContactList)
	contact;
	handleSave(event) {
		const recordInputs =  event.detail.draftValues.slice().map(draft => {
			const fields = Object.assign({}, draft);
			return { fields };
		});
		const promises = recordInputs.map(recordInput => updateRecord(recordInput));
		Promise.all(promises).then(contacts => {
			this.dispatchEvent(
				new ShowToastEvent({
					title: 'Success',
					message: 'Contacts updated',
					variant: 'success'
				})
			);
			this.draftValues = [];
				return refreshApex(this.contact);
		}).catch(error => {
			// Handle error
		});
	}
}
```
```xml:datatableUpdateExample.js-meta.xml
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
	<apiVersion>48.0</apiVersion>
	<isExposed>false</isExposed>
	<targets>
		<target>lightning__Tab</target>
	</targets>
</LightningComponentBundle>
```