Lightning Web Components（JS）

###プロパティ（属性）定義
内部で使用する属性には @track を付ける。@trackを付けないと、変数の内容が変更されても画面が再描画されないことに注意。
外部に公開したいpublicな属性に対しては @api を付ける。
なお、JSコード内で属性を参照する場合は ES6の記法に従って this.属性名 でアクセスする。
属性として定義できるのは、Primitive型、連想配列({})、配列（[]）の3種類。

```js
import { LightningElement, track, api} from 'lwc';

export default class lwc_OppList extends LightningElement {
    attribute1;          //ただの変数 (省略可）
    @track attribute2;   //変数の内容が変更された時にHTMLが再描画される
    @api attribute3;     //属性を外部に公開する(public）

```
※ 変数が定義されると、プリコンパイル後に自動的に constructor関数内で this.xxx = void 0; に展開される。 

###JSとHTMLの変数名の差異
JS内の変数名はCamel case（先頭小文字、単語の切れ目で大文字）、HTML内の変数名とコンポーネント名は Kebab case（単語を-で区切る）で定義する。

```js
//JS内の変数名は Camel case
@api itemName

//HTMLでの参照時は Kebab case
<c-lwc_opp-list item-name="123" ...

```

####getter/setter
プロパティの代わりに getter/setter を定義することもできる。@apiを付ければ外部に公開可能。@apiはgetter/setterの両方に付ける必要はなく通常はgetterのみ付ける。JSコード内から参照する場合は属性と同じようにthisを付けて参照する。

```js
export default class TodoItem extends LightningElement {

    //HTMLから参照するgetter
    get record() {
        return this.records[0];
    }

    //Publicなgetter
    @api
    get itemName() {
        return this._itemName;
    }

    set itemName(value) {
       this._itemName = value.toUpperCase();
    }

・・・・
   //JSコードから参照する場合
   it (this.itemName == 'xxxx') {

}
```
###静的リソースの利用
import 任意の名前 from '@salesforce/resourceUrl/静的リソースの名前'

```javascript
import trailheadLogoUrl from '@salesforce/resourceUrl/trailheadLogo';
```

###ラベルの利用
import 任意の名前 from '@salesforce/label/c.ラベルのAPI名';
'c.' は自分の組織を表すnamespace.

```javascript
import greeting from '@salesforce/label/c.greeting';

export default class aComponent extends LightningElement {

  //HTMLから参照できるように属性として定義する
  label = {
    greeting,
    ・・・
  };
```
```js
#HTMLファイルからラベルを参照する
 {label.greeting}
```

###レコードIDの取得
コンポーネントをレコードページに配置した時に、当該レコードのIDを取得するには、recordId 属性をpulic属性として定義する。自動的にIDがセットされる。

```javascript
import { LightningElement, api } from 'lwc';
export default class TestClass extends LightningElement {
    @api recordId;
}
```

### コンポーネントの横幅の取得
Lightning Pageにコンポーネントを配置すると、コンポーネントの横幅は自動的に調整される。この自動設定される横幅を flexipageRegionWidth 属性で取得できる。

```js
 @api flexipageRegionWidth;
```

### オブジェクト名の取得
Lightning Record Pageにコンポーネントを配置すると、配置元のオブジェクトのAPI名をobjectApiName 属性で取得できる。

```js
 @api objectApiName;
```

###Apexメソッドの呼出し

####Apexメソッドのimport
import apexMethod from '@salesforce/apex/Namespace.Classname.apexMethod';

自分の組織上のクラスの場合、Namespece の 'c.'は付けない。

```javascript
import retrieveOpps from '@salesforce/apex/LWC_OpportunityListController.retrieveOpps';
```

サーバー側コントローラの実装は、Auraコンポーネントの時と同じで staticメソッドに @AuraEnabled を付ける。 クライアント側で@Wireする場合は サーバー側コントローラメソッドには(Cacheable=true）は必須であることに注意する。

```java
/*
 * 指定された企業に紐付く商談の一覧を返す
 *  accountId 取引先ID
 */
@AuraEnabled(cacheable=true)
public static List<Opportunity> retrieveOpps(Id accountId){
    Opportunity[] opps =
        [SELECT Id, Name, StageName, Amount
            FROM Opportunity
            WHEREAccountId = :accountId
            ORDER BY Name ];
    return opps;
}
```
```java
/*
 * ユーザーのデータを返す
 *  userId ユーザーID
 */
 @AuraEnabled(cacheable=true)
 public static User retrieveUserInfo(Id userId){
     User record =
            [SELECT Id,
                      Username,
                      Name,
                      Profile.Name,
                FROM User
                WHERE Id = :userId ];
        return record;
    }
```

#### Apexメソッドのコール
LWCでは複数の手段でApexメソッドをコールすることができる。

#####A. プロパティへのWire
コンポーネントのロード時にApexメソッドがコールされ、取得した値が変数にセットされる。
注意：この方式は開発時のデバッグが難しいこと、サーバー側のApexメソッド呼出時のエラー処理をカスタマイズできないため、BまたはCの実装方法をお薦めします。

```js
@wire(retrieveUserInfo, { 'userId': userid })
record;

//引数がない場合
@wire(retrieveCurrentUserInfo)
record;
```

取得したデータは data属性に、エラー情報はerror属性にセットされる。

```html
<lightning-formatted-text value={record.data.Username} ></lightning-formatted-text>
```

#####B. メソッドへのWire
コンポーネントのロード時にApexメソッドがコールされ、メソッドが呼び出される。取得したデータは 引数dataに、エラー情報は引数errorにセットされる。

```js
@wire(retrieveUserInfo, {'userId': userid})
wiredUserInfo({ error, data }) {
    if (data) {
        this.record = data;
    } else if (error) {
        this.showToast(error.details.body.message);
    }
}
```

```html
<lightning-formatted-text value={record.Username}></lightning-formatted-text>
```

#####C. コード内での呼出し
メソッドからの戻り値のデータ型の制限は従来のAuraコンポーネントと同じ。
従来のAuraコンポーネントでのApexメソッドのコールと同じく、任意のタイミングでコードから呼び出す。
取得したデータは thenメソッドの引数dataに、エラー情報はcatchメソッドの引数errorにセットされる。

```js
retrieveUserInfo({ 'userId' : userid })
    .then(data => {
        record = result;
    })
    .catch(error => {
        this.showToast(error.body.message);
    });
```

```html
<lightning-formatted-text value={record.Username}></lightning-formatted-text>
```

###トーストメッセージの表示
画面上にトーストメッセージを表示する。

```js
import { ShowToastEvent } from 'lightning/platformShowToastEvent'

/*
 *トーストによるメッセージ表示
 */
showToast(message) {
    const event = new ShowToastEvent({
        title: 'Sending Toasts is a Blast!',
        message: message,
        variant: 'error', //info/success/warning/error
        mode: 'sticky'  //sticky クローズボタンを押すまで表示
                        //pester 3秒間表示
                        //dismissable sticky+pester
    });
    this.dispatchEvent(event);
}
```
<img width="591" alt="Screen Shot 2019-01-29 at 22.15.54.png" src="https://qiita-image-store.s3.amazonaws.com/0/161463/69f99bd8-5f0a-03e9-95b0-f4c750536864.png">

[開発ガイド（英語）](https://developer.salesforce.com/docs/component-library/documentation/lwc/use_toast)

###JSコードの共有化
JSコードを共有化したい場合は、新しくLWCコンポーネントを作成し、htmlファイルを削除する（jsとメタデータのみ残す）。ES6の文法に従って、メソッドをexportする。

共有コードの定義

```js
import { ShowToastEvent } from 'lightning/platformShowToastEvent'

/*
 *トーストによるメッセージ表示
 * that this をセットする
 * message メッセージ
 * mode (オプション)  sticky|pester|dismissal
 */
const showToast = (that, message, mode) => {
    const modevalue = mode != null ? mode : 'dismissable';
    const event = new ShowToastEvent({
        title: 'エラーが発生しました',
        message: message,
        variant: 'error',
        mode: modevalue
    });
    that.dispatchEvent(event);
};

//メソッドをexport する
export { showToast };
```

<img width="342" alt="Screen Shot 2019-01-29 at 23.41.21.png" src="https://qiita-image-store.s3.amazonaws.com/0/161463/3e31bbc5-9327-d0b6-c0c0-1feb7075d2f6.png">

呼出側のコード

```js
//c は同じ組織であることを示す
import { showToast } from 'c/lwc_CommonUtils';
//複数のメソッドをimport する場合は列挙する
import { showToast, xx, xx } from 'c/lwc_CommonUtils';
//ファイル内の全てのメソッドをimportする
import * from 'c/lwc_CommonUtils';

・・・
//importしたメソッドは自由に呼び出せる
showToast(this, error.body.message);

```

[開発ガイド（英語）](https://developer.salesforce.com/docs/component-library/documentation/lwc/lwc.create_javascript_share_code)

###外部JS/CSSファイルの読み込み
jqueryなどの外部JSファイルやCSSファイルを使い対場合は、jsファイルを静的リソースとして登録した後にplatform-resource-loaderを使用する。

```js
import { loadStyle, loadScript } from 'lightning/platformResourceLoader';
import leaflet from '@salesforce/resourceUrl/leaflet';

・・・

connectedCallback() {
    Promise.all([
      loadStyle(this, leaflet + '/leaflet.css'),
      loadScript(this, leaflet + '/leaflet.js')
    ]).then(() => {
        //リソースロード後の処理を記述
        ・・・
    });
  }

```

[リファレンス](https://developer.salesforce.com/docs/component-library/bundle/lightning-platform-resource-loader/documentation)