tyoshikawa1106のブログ

- Force.com Developer Blog -

SFDC:Lightningコンポーネント開発 - 地図アプリの開発を試してみました

Lightningコンポーネント開発-地図アプリの開発を試してみました。

f:id:tyoshikawa1106:20200525185912p:plain


開発と言ってもSalesforceが標準で用意しているlightning:mapタグを使って実装できます。地図系の開発にはGoogleMapのAPIの契約が必要だったり、フリーのライブラリ「leaflet」の利用を検討したりが必要になりますが、lightning:mapを利用すれば気軽にGoogleMapの地図表示が可能そうでした。

f:id:tyoshikawa1106:20200525190121p:plain

Component Library

開発してみてわかったこと

地図上にマーカーを表示にするには二種類の方法があります。

  • 住所情報をつかってマーカーを表示する
  • 緯度・経度の情報をつかってマーカーを表示する


はじめに利用を検討したのは住所情報をつかった実装です。緯度・経度の登録は住所情報とは別に行う必要があり、自動化を行う場合はGoogleのAPIの利用が必要になると思われるためです。


ところが住所情報をつかったマーカー表示には下記の制限がありました。

住所情報をつかってマーカーを配置できるのは10箇所まで


最終的にマーカー配置に必要なのは緯度・経度の情報で、住所情報をそのまま使うと変換処理が実行される仕組みのためです。10箇所より多く配置しようとすると下記のJSエラーが発生して処理が中断されます。

Google geocoder status is OVER_QUERY_LIMIT


マーカー配置したい場合はさすがに10箇所以内のケースはあまり無いと思います。基本的には緯度経度の情報が必要になることを認識しておくと良さそうでした。


ちなみに緯度・経度のデータは下記のように登録できます。(専用のデータ型があります。)
f:id:tyoshikawa1106:20200525190809p:plain


緯度・経度での管理の場合はマーカーの配置は100個を上限の目安と考えれば良いと開発者ガイドに記載がありました。無限には配置できないため、ある程度絞り込んで表示するケースを想定しておく必要がありそうです。


以下Google翻訳した内容です。(元のサイトのURLがどこだったか失念しました。)
f:id:tyoshikawa1106:20200525191124p:plain


マーカーの配置数を多くした場合ですが、地図の右側に表示できるリストビューが長くなり、それにより地図コンポーネントの高さも伸びてしまうことがわかりました。この挙動により、レイアウト崩れが発生します。


この問題を解決する方法ですが、下記のCSSを組み込むことで、リストビューのスクロールが可能になります。(Windowsでの挙動は未確認ですがmacで問題なく動いたのでたぶん大丈夫。)
f:id:tyoshikawa1106:20200525191823p:plain


また、マーカー情報の変数を格納するmapMarkersですが、値が存在しない場合はエラーが発生してしまうので、 aura:renderIf で表示判定しておくと良いと思います。

f:id:tyoshikawa1106:20200525192050p:plain


おまけとしてshowFooterをtrueにしたときの挙動ですが、地図の下にGoogleマップで表示のボタンが表示される仕組みでした。


以上がLightningコンポーネント開発での地図アプリの開発を試したときの記録です。

動画

サンプルコード (最初に公開した後にちょっと修正)

LightningMap.cmd
<aura:component controller="LighntingMapController" implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId,forceCommunity:availableForAllPageTypes,force:lightningQuickAction" access="global" >
    <aura:attribute name="mapMarkers" type="Map[]" />
    <aura:attribute name="center" type="Object"/>
    <aura:attribute name="zoomLevel" type="Integer" />
    <aura:handler name="init" value="{! this }" action="{! c.init }"/>
    
    <div class="slds-page-header">
    	<div class="slds-page-header__row">
        	<div class="slds-page-header__col-title">
          		<div class="slds-media">
		            <div class="slds-media__body">
        		    	<div class="slds-page-header__name">
							<div class="slds-page-header__name-title">
								<h1>
									<span class="slds-page-header__title slds-truncate">県庁</span>
								</h1>
							</div>
						</div>
					</div>
				</div>
			</div>
		</div>
    </div>
    <aura:renderIf isTrue="{! v.mapMarkers.length > 0}">
    	<lightning:map style="max-height: 1200px;" listView ="auto" mapMarkers="{! v.mapMarkers }" center="{!v.center}" zoomLevel="{!v.zoomLevel}" showFooter="false" />
    </aura:renderIf>
</aura:component>
LightningMapController.Js
({
    init: function (cmp, event, helper) {
        
        // センターセット
        cmp.set('v.center', {
            location: {
                State: '東京都',
                City: '新宿区',
                Street: '西新宿2-8-1',
                PostalCode: '163-8001',
        	},
		});
        // 拡大率セット
        cmp.set('v.zoomLevel', 7);
        
        
        // Apex実行
        var action = cmp.get("c.getPrefecturalOfficeList");
        action.setCallback(this, function(data) {
            // Apex実行結果取得
            var results = data.getReturnValue();
            // マーカーリスト
	        var mapMarkers = [];
            // マーカーリスト情報取得
            for (var i = 0; i < results.length; i++) {
                var result = results[i];
                // マーカー情報セット
                var marker = {
                    location: {
                        Latitude: result.AddressLatLng__Latitude__s,
    					Longitude: result.AddressLatLng__Longitude__s,
                    },
                    title: '■' + result.State__c + '庁' + '(' + result.Name + ')',
                    description: 'TEL:' + result.Phone__c,
                    'icon': 'standard:account',
            	};
                console.log(marker);
                // マーカー情報
                mapMarkers.push( marker );
            }
            // マーカーセット
	        cmp.set( 'v.mapMarkers', mapMarkers );
        });
        $A.enqueueAction(action);
    },
})
LightningMap.css
.THIS .slds-coordinates__list {
    height: 800px;
    overflow-y: auto;
}
Apex: LightningMapController.cls
public with sharing class LighntingMapController {
    
    /**
     * コンストラクタ
     */
    public LighntingMapController() {
        
    }
    
    /**
     * 県庁情報取得
     */
    @AuraEnabled
    public static  List<PrefecturalOffice__c> getPrefecturalOfficeList() {
        return [
            SELECT
            	 Id
            	,Name
            	,State__c
            	,Phone__c
            	,PostalCode__c
            	,Address__c
	            ,AddressLatLng__Latitude__s
            	,AddressLatLng__Longitude__s
            FROM
            	PrefecturalOffice__c
            WHERE
            	AddressLatLng__Latitude__s != null
            AND
            	AddressLatLng__Longitude__s != null
            ORDER BY Name ASC
            LIMIT 100
       	];
    }
}

SFDC:ファイルのライブラリ権限設定を試してみました

Lightning Experienceのファイルのライブラリ権限設定を試してみました。

f:id:tyoshikawa1106:20200516152923p:plain


ライブラリ権限設定ですが、コンテンツ権限の設定で行えばいいみたいです。
f:id:tyoshikawa1106:20200516153033p:plain

Help | Training | Salesforce


ただ、Lightning Experienceの設定メニューには見当たりませんでした。
f:id:tyoshikawa1106:20200516153142p:plain:w300


現時点でこの設定を行うにはClassicに切り替えて作業する必要があるみたいです。
f:id:tyoshikawa1106:20200516153225p:plain


こんな感じで権限を細かく設定できます。
f:id:tyoshikawa1106:20200516153258p:plain


設定後にライブラリのメンバー追加時に選択できるようになっていました。
f:id:tyoshikawa1106:20200516153329p:plain


ファイルのライブラリ権限設定はこんな感じでした。

SFDC:Salesforce Extensions for Visual Studio CodeでJavaエラーが発生したときの対処方法について

Salesforce Extensions for Visual Studio CodeでJavaエラーが発生したときの対処方法についてです。ちょっと前からプライベートのMacBookで用意した開発環境でJavaエラーが発生するようになりました。

f:id:tyoshikawa1106:20200324082546p:plain

エラーメッセージは下記のような感じ。

実行には Java 8 が必要です。


エラーが発生したこと自体はPCの設定をいろいろ触ってたうちにどこかミスって壊れただけですが、エラーの修正方法がわからなくて困っていました。


解決方法については公式のサイトで紹介されています。

f:id:tyoshikawa1106:20200324082838p:plain

https://developer.salesforce.com/tools/vscode/ja/getting-started/java-setup/


エラーメッセージではJava 8と記載がありますが、実際はJava 11もサポートされています。また、OracleのJavaではなくてもOpenJDKの方もサポートされています。今回はデータローダでも必要になったZuluを利用しています。

f:id:tyoshikawa1106:20200324083104p:plain

対応手順

Macの場合です。VSCodeを起動して「Code」→「Preferences」→「Settings」と選択します。
f:id:tyoshikawa1106:20200324083133p:plain


設定ページが表示されるので検索ボックスにapexと入力します。あとはSalesforcedx-vscode-apex › Java: Homeにパスを入力するだけです。

f:id:tyoshikawa1106:20200324083409p:plain

パスの指定例

/Library/Java/JavaVirtualMachines/zulu-11.jdk/Contents/Home


※パスの例についての詳細は公式サイトのものを参考にしてください。

エラー解決後

上記対応でエラーメッセージが表示されなくなりました。Javaエラー発生した状態ですが、テストクラスのテスト実行機能が利用できなくなる現象が発生していました。
(Run Testリンクが表示されなかった)

f:id:tyoshikawa1106:20200324083816p:plain


Javaエラーが発生したときは上記のように設定することで解決するかもしれません。

関連記事

SFDC:Spring'20の仕様変更に伴うサイトゲストユーザの作成権限への影響ついて検証しました

サイトゲストユーザと標準オブジェクトの作成権限についての検証を行いました。Spring'20でサイトゲストユーザの権限周りの仕様変更がありました。サポートに困りますと問い合わせしたりして、「この変更は絶対です。更新権限は付与できなくなります」と回答を確認したりしたあとに、さすがに無理か..とUPDATE権限については諦めることにしました。
(ちなみにSummer'20までは従来の権限仕様を引き続き適用できます。)


このときに考えたのはUPDATEはできなくなるのでINSERT処理のみで対処しようということです。というのも同じく仕様変更であった「ゲストユーザによって作成されたレコードのデフォルトの所有者への割り当て」という設定を見て作成権限は引き続き使えるんだなと判断したためです。


・・で、Summer'20に向けてゲストユーザに対しての非公開設定などの必要な設定を有効化してINSERT処理を実行した結果はこちらです。
f:id:tyoshikawa1106:20200318185445p:plain

DmlExcetpion = insufficient access rights on cross-reference id

ということで権限設定をしっかり調整しないとINSERT処理もできない状態でした。あっちを試してこっちを試してだと検証が大変なのでまず権限付与が一切無い状態を用意して検証することにしました。

権限付与なしの状態を作成

共有設定

取引先 / 取引先責任者 / 商談の権限を非公開寄りに設定しました。
f:id:tyoshikawa1106:20200318185725p:plain


ゲストユーザのレコードアクセス権を保護も有効化。
f:id:tyoshikawa1106:20200318185834p:plain


共有ルールも未設定の状態です。
f:id:tyoshikawa1106:20200318185934p:plain

サイト設定

「ゲストユーザによって作成されたレコードのデフォルトの所有者への割り当て」の機能もONにします。(設定ページではなぜか英語。割り当て先はシステム管理者ユーザをセット)
f:id:tyoshikawa1106:20200318190113p:plain

サイトゲストユーザのプロファイル設定

オブジェクトは参照権限から除外した状態にします。

項目レベルセキュリティ

必須項目以外の権限を除外した状態で確認します。
f:id:tyoshikawa1106:20200318190509p:plain

検証方法

ボタンクリック時に取引先の取引先名と都道県のみセットしてINSERTするシンプルな処理を実行して確認します。
f:id:tyoshikawa1106:20200318190643p:plain

検証結果

この状態の結果は最初に貼ったキャプチャの通りです。『insufficient access rights on cross-reference id』エラーが発生します。ここから検証を行っていきたいと思います。

オブジェクトの参照権限と作成権限を付与

サイトゲストユーザのプロファイル設定で取引先の作成権限を付与します。
f:id:tyoshikawa1106:20200318190739p:plain


項目レベルセキュリティもセット。
f:id:tyoshikawa1106:20200318191017p:plain


実行結果はこちら。権限エラーとなります。キャッシュとかあるかもしれないのでブラウザを変えてシークレットウィンドウで試しましたが解決せず。
f:id:tyoshikawa1106:20200318191203p:plain


どうやらオブジェクトの作成権限ではダメなようです。これはおそらく作成後の所有者がデフォルトで管理者ユーザになるためと思います。

共有ルールを付与

デフォルトセットされる所有者のアクセス権限があれば作成できると思ったため、共有ルールでユーザのアクセス権限を付与しました。警告メッセージが英語ですが、このDE組織の設定の問題と思います。(他の組織だとちゃんと日本語表示されてました。)
f:id:tyoshikawa1106:20200318192031p:plain


共有ルールが適用されるのを確認してから検証します。
f:id:tyoshikawa1106:20200318192217p:plain


実行結果はこちら。
f:id:tyoshikawa1106:20200318192246p:plain


所有者がシステム管理者で作成者がゲストユーザの取引先データが無事に登録できました。
f:id:tyoshikawa1106:20200318192438p:plain


全然関係ありませんが検証用にと取引先名にセットしたシステム日時が日本時間じゃないのがちょっと気になりました。ゲストユーザのページに行くとタイムゾーンがグリニッジ標準時になっていたのでそれが原因です。ゲストユーザ利用時には必要な場合は変更しておくと良さそうです。


タイムゾーンを直すとちゃんと日本時間で処理してくれます。
f:id:tyoshikawa1106:20200318192854p:plain


ひとまずこれでゲストユーザでもINSERT処理を実行できることを確認できました。つづいて他のオブジェクトも検証します。

・・・とその前に一点気になった箇所があるのでそちらを検証しました。オブジェクトの作成権限は必要あったのか?という点です。

オブジェクトの作成権限を除外

こんな感じで権限をOFF。
f:id:tyoshikawa1106:20200318193206p:plain


実行結果はこちら。
f:id:tyoshikawa1106:20200318193255p:plain


普通に作成できました。
f:id:tyoshikawa1106:20200318193331p:plain


本題では無いのでサラッと記載しますがApexの処理はシステム権限で実行されるためオブジェクトの権限はスルーされます。必要な場合は項目のアクセス権限などをチェックしてエラーにする判定処理を実装する必要があります。


ということでINSERT処理に必要なのはユーザのアクセス権限であることを確認できました。

取引先に紐付く取引先責任者の作成

続いて取引先に紐付く取引先責任者の作成です。確認したいのは親オブジェクトに紐付く子オブジェクトのデータ登録。
f:id:tyoshikawa1106:20200318193834p:plain


実行結果です。
f:id:tyoshikawa1106:20200318194011p:plain


001は取引先IDだったので、取引先のアクセス権限が無いとのことかと思います。取引先責任者の共有ルールは親レコードに紐付くなので取引先へのアクセス権限があれば問題ないはず。
f:id:tyoshikawa1106:20200318194204p:plain


取引先レコードのINSERTの検証で参照権限さえあれば問題ないことを確認しましたので、同様に取引先に共有ルールを付与します。条件は作成者IDです。所有者は内部ユーザにデフォルトセットされますが、作成者は変わりません。あまり好ましくないですが、IDの文字列を直接セットして対応しました。

f:id:tyoshikawa1106:20200318194556p:plain

f:id:tyoshikawa1106:20200318194607p:plain


実行結果です。・・・アクセス権限エラー解決せず。
f:id:tyoshikawa1106:20200318194844p:plain:w300


この場合はオブジェクトの権限設定が必要なのかもしれない。追加してみました。
f:id:tyoshikawa1106:20200318195007p:plain


・・・エラー。
f:id:tyoshikawa1106:20200318195043p:plain:w250


取引先の共有がうまく行っていないのかも。すべての取引先が条件に一致するように変更します。
f:id:tyoshikawa1106:20200318195252p:plain


エラー解決せず。。
f:id:tyoshikawa1106:20200318195400p:plain:w300


が一つ原因を思いつきました。プロセスビルダーの処理です。
f:id:tyoshikawa1106:20200318195630p:plain


DE組織だったので検証用のやつが有効化となってました。処理内容を見るとChatter投稿というゲストユーザじゃ実行できないやつ。取引先INSERTでは動かなかったけど取引先責任者のINSERT処理ではなぜか動いたのかも・・・。


と思い無効にした後に再度試してみました。
f:id:tyoshikawa1106:20200318195947p:plain


・・・・プロセスビルダー関係無し。。というかプロセスビルダーとかでエラーになるとすればトリガとかワークフローを今後追加していったらクラッシュするんじゃないかと思います。

※追記:取引先責任者責任者のINSERTはwithout sharingの宣言で正常に実行できました。権限を親レコードを引き継ぐだとうまくいくようです。ただ商談はやはりうまくいきませんでした。同じく抜け穴があるかもしれませんが、しんどいだけなので調査はこれで終了。

結論

サイトゲストユーザでは取引先責任者の登録ができない...ように見えます...。仮にできたとしてもトリガなどの追加時に影響反映が大きそうです。フォーム入力で取引先/取引先責任者/商談と必要なデータが一発でできるのは業務上すごく便利だったのですが、仕様変更後はそこも諦める必要がありそうに思いました。


アイデアとしてはカスタムオブジェクト(一レコードに収まる形)でデータ登録を行い、スケジュールバッチで取引先/取引先責任者/商談に変換するような処理を行うのが現実的な気がしました。ただスケジュールバッチを最短で動かしたとしても5分に一回ぐらいの実行となると思うのでリアルタイムでの作成ができません。すごく不便になるためできればこの手段は取りたくないと思いました。・・・ですが今回検証して権限設定でも解決できなそうなので、リアルタイム性を捨ててバッチ処理によるデータ変換が必要になるのかなと思います。

要望

この仕様変更やめてほしいです。


・・・はさすがに無理ですが正直代替案は欲しかった。UPDATE処理は諦めましたがINSERT処理はできてほしかったです。(トリガとかの影響は受けない形で実現してほしい)


それか非同期処理で良いのでゲストユーザ作成後に、内部ユーザの権限で処理を実行できるようにしてくれればなんとかなったんじゃないかと思います。(無茶振りですが..)


仕様変更に伴うサイトゲストユーザと標準オブジェクトの作成権限についての検証はこんな感じでした。

SFDC:Sandbox組織での開発とページレイアウトのメールコンポーネントについて

Sandbox組織での開発とページレイアウトのメールコンポーネントについてです。Salesforceには実際に業務で使用する本番組織とは別に開発を行うためのSandbox組織が用意されています。
f:id:tyoshikawa1106:20200317081126p:plain

Sandbox | セールスフォース・ドットコム


Salesforceでの開発は下記のフローで実施するのが一般的です。

  1. 本番環境の設定メニューからSandbox組織を作成
  2. Sandbox組織で開発を行う
  3. 本番環境にリリース


本番環境で直接開発を行うことは基本ありませんが、項目の追加やレイアウトの変更、レポートやダッシュボードの作成など一部の設定は本番環境で行う場合もあります。そのためSandbox組織作成後、時間が経過するととも本番組織とSandbox組織で設定情報に差分が出てくると思います。この問題は定期的にSandboxを更新(リフレッシュ)するか新しくSandbox組織を作成してそちらで開発を行う流れにすると本番組織との差分発生を解決できます。


Sandboxのリフレッシュにより本番組織との差分が無くすことで、Sandbox側の設定変更をに本番にリリースしても設定を壊われたりはしなくなります。(開発箇所は実装方法によるので除きますが..)


・・・基本的には上記の通りなのですが、一点要注意の箇所がありました。ページレイアウトに配置したメールコンポーネントです。
f:id:tyoshikawa1106:20200317082151p:plain



Sandbox組織でページレイアウトをカスタマイズ後に本番にリリースしたところ、メール送信機能が使えなくなったと連絡を受けました。本番リリース後のチェックが甘かったのが一番の問題なのですが、本番の設定情報を引き継いだ状態で作業したのになんでかなという疑問がありました。


この原因はおそらくSandbox組織リフレッシュ後のメール権限のデフォルト設定にあります。Sandboxをリフレッシュするとメールを送信するためのアクセス権が「システムメールのみ」で設定されます。システムメールのみの場合はSalesforceのメール送信機能が利用不可となり、ページレイアウト上からメールコンポーネントが除外された状態となります。
f:id:tyoshikawa1106:20200317082802p:plain


メールコンポーネントが除外された状態でそのページレイアウトを本番環境にリリースしてしまうと本番環境のレイアウト上でもメールコンポーネントがなくなってしまうと思われます。(最後まで検証してませんがおそらくこの挙動だと思います。)


ということでSandboxリフレッシュ直後でもページレイアウトのメールコンポーネントの配置設定には差分が発生するため、作業時には注意しておくのが良さそうです。


ちなみにメールを送信するためのアクセス権を「すべてのメール」にすると表示された状態に戻ります。問題がない状態であることを確認できていればSandbox組織作成後に切り替えておくと設定作業で予期せぬトラブルを回避できると思います。(ユーザのメールアドレスは自動でテストデータに差し替わります。それ以外のメール送信処理で外部や本番用メールアドレスの設定があるときにはそちらの設定を修正してから切り替える必要があります。)

SFDC:活動の日時項目にアップデートがありました

活動の日時項目にアップデートがありました。全然気づかなかったのですが時期的にSpring'20のアップデートで適用されていたのかなと思います。

f:id:tyoshikawa1106:20200313082658p:plain


活動の日時項目には開始時間または終了時間を変更時にもう片方が自動調整される機能があります。

f:id:tyoshikawa1106:20200313082806p:plain


例えば開始時間が10:00で終了時間が11:00の場合、開始時間を11:00に変更すると終了時間が12:00に自動的に変更されます。これは予定が変更されたときの入力作業の負担を減らす目的と思います。(Outlookカレンダーなども同様に自動調整されているのでカレンダー周りでは一般的な機能なのだと思います。)

f:id:tyoshikawa1106:20200313083044p:plain


ただちょっと不便な面もありました。開始時間と終了時間を同じ時間にしたい場面です。今までは開始時間と同様に、終了時間を変更すると開始時間が変更される仕組みがありました。そのため、開始と終了を同じ時間にしようと終了時間を変更すると開始時間がズレてしまい気づかず登録という入力ミスが発生することがありました。また同じ時間帯にはセットできないように制御されていたため、最低1分はズラす必要がありました。


今回アップデートで終了時間を変更しても開始時間が自動調整されることがなくなったようです。これにより同じ時間をセットすることも可能になりました。

f:id:tyoshikawa1106:20200313083517p:plain


開始時間の自動調整機能は引き続き利用可能です。個人的には嬉しいアップデートでした。

SFDC:Lightning Web コンポーネントの入力系のサンプルコードを試してみました

"この記事は Salesforce 開発者向けブログキャンペーンへのエントリー記事です。"
Lightning Web コンポーネントの入力系のサンプルコードを試してみました。開発者向けドキュメント『Component Library』のサイトに公開されているサンプルです。

f:id:tyoshikawa1106:20200313052501p:plain

Component Library Lighnting-Input

はじめに

Lightning Web コンポーネント開発の始め方はこちら。

つくってみたサンプル画面

実際に作ってみたのはこちらです。つくったLWCをLightningアプリケーションページに配置して表示しています。

f:id:tyoshikawa1106:20200313052330p:plain

コードのイメージ。(コードの全体は最後に記載します。)

f:id:tyoshikawa1106:20200313053042p:plain

lightning-accordion-section

今回のサンプルを試す際に画面が見づらくならないようにこちらの機能を利用しました。アコーディオンセクションはクリックでオープンとクローズを切り替えることができます。また常にひとつはオープンの状態にしている必要がありました。

f:id:tyoshikawa1106:20200313053417p:plain

lightning-input type="text"

通常のテキスト入力欄です。

f:id:tyoshikawa1106:20200313060009p:plain

lightning-input type="checkbox"

通常のチェックボックス入力欄です。

f:id:tyoshikawa1106:20200313060042p:plain

lightning-input type="checkbox-button"

LWCに用意されていたチェックボックスボタンです。チェックなしのときには+と表示されていました。

f:id:tyoshikawa1106:20200313060145p:plain

f:id:tyoshikawa1106:20200313060201p:plain

lightning-input type="color"

カレーパレットを表示できる仕組みです。設定ページをつくるときなどに便利そうでした。

f:id:tyoshikawa1106:20200313060556p:plain

lightning-input type="date"

日付の入力欄を表示できます。

f:id:tyoshikawa1106:20200313060757p:plain

lightning-input type="datetime"

日時の入力欄を表示できます。

f:id:tyoshikawa1106:20200313060853p:plain

lightning-input type="email"

メールアドレスの入力欄を表示できます。

f:id:tyoshikawa1106:20200313060940p:plain

lightning-input type="file"

ファイルアップロードの入力欄を表示できます。ドラッグ&ドロップによるアップロードの仕組みもセットで用意されていました。

f:id:tyoshikawa1106:20200313061036p:plain

lightning-input type="number"

数値入力欄です。

f:id:tyoshikawa1106:20200313061145p:plain

lightning-input type="password"

パスワードの入力欄を用意できます。

f:id:tyoshikawa1106:20200313061256p:plain

lightning-input type="radio"

ラジオボタンの入力欄を用意できます。今回のサンプルコードを試したときはちゃんと調べなかったので見せかけだけ表示しています。

f:id:tyoshikawa1106:20200313061422p:plain

lightning-input type="range"

レンジ入力のやつです。タグ一つで簡単に設置できます。便利そう。

f:id:tyoshikawa1106:20200313061518p:plain

lightning-input type="search"

検索用の入力欄を用意できます。通常のテキストボックスと違い虫眼鏡アイコンが表示されたり処理中アイコンを表示できたりします。

f:id:tyoshikawa1106:20200313061628p:plain

lightning-input type="tel"

電話番号の入力欄を用意できます。patternで入力時の形式も制御できるようです。便利。

f:id:tyoshikawa1106:20200313061734p:plain

lightning-input type="time"

日時型の時間部分の入力欄を用意できます。

f:id:tyoshikawa1106:20200313061845p:plain

lightning-input type="toggle"

トグルボタンを配置できます。

f:id:tyoshikawa1106:20200313061925p:plain

lightning-input type="url"

URLの入力欄を用意できます。httpの部分から入力しないとエラーになる制御があるようです。

f:id:tyoshikawa1106:20200313062039p:plain

lightning-input-address

住所用の入力欄を用意できます。国もセットでついてくるようです。(非表示オプションの有無はまだ未確認)

f:id:tyoshikawa1106:20200313062139p:plain

lightning-input-location

緯度経度の入力用。必要だけども普段はあまり使わなさそう。

f:id:tyoshikawa1106:20200313062239p:plain

lightning-input-name

名前入力用。敬称部分は選択リストになっています。

f:id:tyoshikawa1106:20200313062336p:plain

lightning-input-rich-text

リッチテキスト入力欄です。

f:id:tyoshikawa1106:20200313062453p:plain

デモ動画

サンプルコード

サンプルの構成は下記のとおり。

  • helloLwc.html
  • helloLwc.js
  • helloLwc.js-meta.xml
helloLwc.html
<template>
    <div>
        <lightning-accordion active-section-name="TextSection">
            <lightning-accordion-section name="TextSection" label="Text Section">
                <!-- TEXT -->
                <div class="slds-m-bottom_medium">
                    <div class="slds-m-bottom_small">
                        <lightning-input type="text" label="テキスト" data-id="inputName" onkeyup={onNameChanged}></lightning-input>
                    </div>
                    <div class="slds-box slds-theme_default">
                        <p class="slds-text-title">Hello {name}!</p>
                    </div>
                </div>
            </lightning-accordion-section>
            <lightning-accordion-section name="CheckboxSection" label="Checkbox Section">
                <!-- Checkbox -->
                <div class="slds-m-bottom_medium">
                    <div class="slds-m-bottom_small">
                        <lightning-input type="checkbox" label="チェックボックス" onchange={onCheckboxChanged} data-id="inputCheckbox" checked={isChecked}></lightning-input>
                    </div>
                    <template if:true={isChecked}>
                        <div class="slds-box slds-theme_default">Checkbox ON!</div>
                    </template>
                    <template if:false={isChecked}>
                        <div class="slds-box slds-theme_default">Checkbox OFF</div>
                    </template>
                </div>
            </lightning-accordion-section>
            <lightning-accordion-section name="CheckboxButtonSection" label="CheckboxButton Section">
                <!-- CheckboxButton -->
                <div class="slds-m-bottom_medium">
                    <div class="slds-m-bottom_small">
                        <lightning-input type="checkbox-button" label="チェックボックスボタン" onchange={onCheckboxButtonChanged} data-id="inutCheckboxButton" checked={isCheckboxButtonChecked}></lightning-input>
                    </div>
                    <template if:true={isCheckboxButtonChecked}>
                        <div class="slds-box slds-theme_default">Checkbox Button ON!</div>
                    </template>
                    <template if:false={isCheckboxButtonChecked}>
                        <div class="slds-box slds-theme_default">Checkbox Button OFF</div>
                    </template>
                </div>
            </lightning-accordion-section>
            <lightning-accordion-section name="ColorSection" label="Color Section">
                <!-- Color -->
                <div class="slds-m-bottom_medium">
                    <lightning-input type="color" label="Color" value="#EEEEEE"></lightning-input>
                </div>
            </lightning-accordion-section>
            <lightning-accordion-section name="DateSection" label="Date Section">
                <!-- Date -->
                <div class="slds-m-bottom_medium">
                    <div class="slds-m-bottom_small">
                        <lightning-input type="date" label="日付" onchange={onDateChanged} data-id="inputDate" value={birthday}></lightning-input>
                    </div>
                    <div class="slds-box slds-theme_default">
                        <p class="slds-text-title">Your Birthday = {birthday}</p>
                        <p><lightning-formatted-date-time value={birthday}></lightning-formatted-date-time></p>
                        <p><lightning-formatted-date-time value={birthday} year="2-digit" month="short" day="2-digit" weekday="narrow"></lightning-formatted-date-time></p>
                        <p><lightning-formatted-date-time value={birthday} year="2-digit" month="short" day="2-digit" weekday="long"></lightning-formatted-date-time></p>
                    </div>
                </div>
            </lightning-accordion-section>
            <lightning-accordion-section name="DateTimeSection" label="DateTime Section">
                <!-- DateTime -->
                <div class="slds-m-bottom_medium">
                    <div class="slds-m-bottom_small">
                        <lightning-input type="datetime" label="日付時間" onchange={onDateTimeChanged} data-id="inputDateTime" value={createdDateTime}></lightning-input>
                    </div>
                    <div class="slds-box slds-theme_default">
                        <p class="slds-text-title">CreatedDateTime = {createdDateTime}</p>
                        <p><lightning-formatted-date-time value={createdDateTime}></lightning-formatted-date-time></p>
                        <p><lightning-formatted-date-time value={createdDateTime} year="2-digit" month="short" day="2-digit" hour="2-digit" minute="2-digit" weekday="narrow"></lightning-formatted-date-time></p>
                        <p><lightning-formatted-date-time value={createdDateTime} year="2-digit" month="short" day="2-digit" hour="2-digit" minute="2-digit" weekday="long"></lightning-formatted-date-time></p>
                    </div>
                </div>
            </lightning-accordion-section>
            <lightning-accordion-section name="EmailSection" label="Email Section">
                <!-- Email -->
                <div class="slds-m-bottom_medium">
                    <div class="slds-m-bottom_small">
                        <lightning-input type="email" label="メール" onchange={onEmailChanged} data-id="inputEmail" value={email}></lightning-input>
                    </div>
                    <div class="slds-box slds-theme_default">
                        <p class="slds-text-title">Your Email = {email}</p>
                        <p>Default   = <lightning-formatted-email value={email}></lightning-formatted-email></p>
                        <p>Hide Icon = <lightning-formatted-email value={email} hide-icon></lightning-formatted-email></p>
                        <p>Label     = <lightning-formatted-email value={email} label="Email"></lightning-formatted-email></p>
                    </div>
                </div>
            </lightning-accordion-section>
            <lightning-accordion-section name="FileSection" label="File Section">
                <!-- File -->
                <div class="slds-m-bottom_medium">
                    <div class="slds-m-bottom_small">
                        <lightning-input type="file" label="ファイル" accept="image/png, .zip" onchange={handleFilesChange} data-id="inputFile" multiple></lightning-input>
                    </div>
                </div>
            </lightning-accordion-section>
            <lightning-accordion-section name="NumberSection" label="Number Section">
                <!-- Number -->
                <div class="slds-m-bottom_medium">
                    <div class="slds-m-bottom_small">
                        <lightning-input type="number" label="数値" onchange={onNumberChanged} data-id="inputNumber" value={number}></lightning-input>
                    </div>
                    <div class="slds-box slds-theme_default">
                        <p class="slds-text-title">Number = {number}</p>
                        <p>Default   = <lightning-formatted-number value={number}></lightning-formatted-number></p>
                        <p>Currency  = <lightning-formatted-number value={number} format-style="currency" currency-code="USD"></lightning-formatted-number></p>
                        <p>Percent   = <lightning-formatted-number value={number} format-style="percent"></lightning-formatted-number></p>
                    </div>
                </div>
            </lightning-accordion-section>
            <lightning-accordion-section name="PasswordSection" label="Password Section">
                <!-- Password -->
                <div class="slds-m-bottom_medium">
                    <div class="slds-m-bottom_small">
                        <lightning-input type="password" label="パスワード" onchange={onPasswordChanged} data-id="inputPassword" value={password}></lightning-input>
                    </div>
                    <div class="slds-box slds-theme_default">
                        <p class="slds-text-title">Password = {password}</p>
                    </div>
                </div>
            </lightning-accordion-section>
            <lightning-accordion-section name="RadioSection" label="Radio Section">
                <!-- Radio -->
                <div class="slds-m-bottom_medium">
                    <div class="slds-m-bottom_small">
                        <lightning-input type="radio" label="Red" value="red" checked></lightning-input>
                        <lightning-input type="radio" label="Blue" value="blue"></lightning-input>
                    </div>
                </div>
            </lightning-accordion-section>
            <lightning-accordion-section name="RangeSection" label="Range Section">
                <!-- Range -->
                <div class="slds-m-bottom_medium">
                    <div class="slds-m-bottom_small">
                        <lightning-input type="range" label="レンジ" min="0" max="100" onchange={onRangeChanged} data-id="inputRange" value={range}></lightning-input>
                    </div>
                    <div class="slds-box slds-theme_default">
                        <p class="slds-text-title">Range = {range}</p>
                    </div>
                </div>
            </lightning-accordion-section>
            <lightning-accordion-section name="SearchSection" label="Serach Section">
                <!-- Search -->
                <div class="slds-m-bottom_medium">
                    <div class="slds-m-bottom_small">
                        <lightning-input type="search" label="サーチ" data-id="inputSearch"></lightning-input>
                    </div>
                    <div class="slds-m-bottom_small">
                        <lightning-input type="search" label="サーチ" is-loading data-id="inputSearchIsLoading"></lightning-input>
                    </div>
                </div>
            </lightning-accordion-section>
            <lightning-accordion-section name="TelSection" label="Tel Section">
                <!-- Tel -->
                <div class="slds-m-bottom_medium">
                    <div class="slds-m-bottom_small">
                        <lightning-input type="tel" label="電話" onchange={onTelChanged} data-id="inputTel" value={phone} pattern="[0-9]{3}-[0-9]{3}-[0-9]{4}"></lightning-input>
                    </div>
                    <div class="slds-box slds-theme_default">
                        <p class="slds-text-title">Tel = {phone}</p>
                        <p>Default   = <lightning-formatted-phone value={phone}></lightning-formatted-phone></p>
                    </div>
                </div>
            </lightning-accordion-section>
            <lightning-accordion-section name="TimeSection" label="Time Section">
                <!-- Time -->
                <div class="slds-m-bottom_medium">
                    <div class="slds-m-bottom_small">
                        <lightning-input type="time" label="時間" onchange={onTimeChanged} data-id="inputTime" value={time}></lightning-input>
                    </div>
                    <div class="slds-box slds-theme_default">
                        <p class="slds-text-title">Time = {time}</p>
                        <p>Default   = <lightning-formatted-time value={time}></lightning-formatted-time></p>
                    </div>
                </div>
            </lightning-accordion-section>
            <lightning-accordion-section name="ToggleSection" label="Toggle Section">
                <!-- Toggle -->
                <div class="slds-m-bottom_medium">
                    <div class="slds-m-bottom_small">
                        <lightning-input type="toggle" label="トグル" onchange={onToggleChanged} data-id="inputToggle" checked={isToggleChecked}></lightning-input>
                    </div>
                    <template if:true={isToggleChecked}>
                        <div class="slds-box slds-theme_default">Toggle ON!</div>
                    </template>
                    <template if:false={isToggleChecked}>
                        <div class="slds-box slds-theme_default">Toggle OFF</div>
                    </template>
                </div>
            </lightning-accordion-section>
            <lightning-accordion-section name="UrlSection" label="URL Section">
                <!-- URL -->
                <div class="slds-m-bottom_medium">
                    <div class="slds-m-bottom_small">
                        <lightning-input type="url" label="URL" onchange={onUrlChanged} data-id="inputUrl" value={url}></lightning-input>
                    </div>
                    <div class="slds-box slds-theme_default">
                        <p class="slds-text-title">URL = {url}</p>
                        <p>Default   = <lightning-formatted-url value={url}></lightning-formatted-url></p>
                    </div>
                </div>
            </lightning-accordion-section>
            <lightning-accordion-section name="AddressSection" label="Address Section">
                <!-- Address -->
                <div class="slds-m-bottom_medium">
                    <div class="slds-m-bottom_small">
                        <lightning-input-address
                            address-label="Address"
                            street-label="Street"
                            city-label="City"
                            country-label="Country"
                            province-label="Province"
                            postal-code-label="PostalCode"
                            street="121 Spear St."
                            city="San Francisco"
                            country="US"
                            province="CA"
                            postal-code="94105"
                            required
                            field-level-help="Help Text for inputAddress field" ></lightning-input-address>
                    </div>
                </div>
            </lightning-accordion-section>
            <lightning-accordion-section name="LocationSection" label="Location Section">
                <!-- Location -->
                <div class="slds-m-bottom_medium">
                    <div class="slds-m-bottom_small">
                        <lightning-input-location label="No default coordinates" ></lightning-input-location>
                    </div>
                </div>
            </lightning-accordion-section>
            <lightning-accordion-section name="NameFieldsSection" label="Name Fields Section">
                <!-- Name -->
                <div class="slds-m-bottom_medium">
                    <div class="slds-m-bottom_small">
                        <lightning-input-name
                            label="Default Input Name Field"
                            first-name="John"
                            middle-name="Middleton"
                            last-name="Doe"
                            informal-name="Jo"
                            suffix="The 3rd"
                            salutation="Mr."
                            options={salutationOptions} ></lightning-input-name>
                    </div>
                </div>
            </lightning-accordion-section>
            <lightning-accordion-section name="RichTextSection" label="RichText Section">
                <!-- RichText -->
                <div class="slds-m-bottom_medium">
                    <div class="slds-m-bottom_small">
                        <lightning-input-rich-text onchange={onRichTextChanged} data-id="inputRichText" value={richText}></lightning-input-rich-text>
                    </div>
                    <div class="slds-box slds-theme_default">
                        <p class="slds-text-title">RichText = {richText}</p>
                        <p>Default   = <lightning-formatted-rich-text value={richText}></lightning-formatted-rich-text></p>
                    </div>
                </div>
            </lightning-accordion-section>
            <lightning-accordion-section name="ListSection" label="List Section">
                <!-- List -->
                <div class="slds-m-bottom_medium">
                    <div class="slds-box slds-theme_default">
                        <!-- List Sample 1 -->
                        <ul>
                            <template for:each={members} for:item="member" for:index="index">
                                <li key={member.id}>{index}. {member.name}</li>
                            </template>
                        </ul>
                    </div>
                    <div class="slds-box slds-theme_default">
                        <!-- List Sample 2 -->
                        <ul>
                            <template iterator:it={members}>
                                <li key={it.value.id}>{it.index}. {it.value.name}: {it.first} : {it.last}</li>
                            </template>
                        </ul>
                    </div>
                </div>
            </lightning-accordion-section>
        </lightning-accordion>
    </div>
</template>
helloLwc.js
import { LightningElement,track } from 'lwc';

export default class HelloLwc extends LightningElement {
    @track name = 'Lightning';
    @track isChecked = false;
    @track isCheckboxButtonChecked = false;
    @track birthday = null;
    @track createdDateTime = null;
    @track email = 'sample@example.com';
    @track number = null;
    @track password = '';
    @track range = 30;
    @track phone = '0X0-1234-1234';
    @track time = null;
    @track isToggleChecked = false;
    @track url = '';
    @track richText = '';
    @track members = [
        {
            id: "1",
            name: "Sato"
        },
        {
            id: "2",
            name: "Suzuki"
        },
        {
            id: "3",
            name: "Tanaka"
        }
    ];

    onNameChanged() {
        this.name = this.template.querySelector('[data-id="inputName"]').value;
    }

    onCheckboxChanged() {
        this.isChecked = this.template.querySelector('[data-id="inputCheckbox"]').checked;
    }

    onCheckboxButtonChanged() {
        this.isCheckboxButtonChecked = this.template.querySelector('[data-id="inutCheckboxButton"]').checked;
    }

    onDateChanged() {
        this.birthday = this.template.querySelector('[data-id="inputDate"]').value;
    }

    onDateTimeChanged() {
        this.createdDateTime = this.template.querySelector('[data-id="inputDateTime"]').value;
    }

    onEmailChanged() {
        this.email = this.template.querySelector('[data-id="inputEmail"]').value;
    }

    handleFilesChange() {
        console.log('Files OK!');
        console.log(this.template.querySelector('[data-id="inputFile"]'));
    }

    onNumberChanged() {
        this.number = this.template.querySelector('[data-id="inputNumber"]').value;
    }

    onPasswordChanged() {
        this.password = this.template.querySelector('[data-id="inputPassword"]').value;
    }

    onRangeChanged() {
        this.range = this.template.querySelector('[data-id="inputRange"]').value;
    }

    onTelChanged() {
        this.phone = this.template.querySelector('[data-id="inputTel"]').value;
    }

    onTimeChanged() {
        this.time = this.template.querySelector('[data-id="inputTime"]').value;
    }

    onToggleChanged() {
        this.isToggleChecked = this.template.querySelector('[data-id="inputToggle"]').checked;
    }

    onUrlChanged() {
        this.url = this.template.querySelector('[data-id="inputUrl"]').value;
    }

    onRichTextChanged() {
        this.richText = this.template.querySelector('[data-id="inputRichText"]').value;
    }
}
helloLwc.js-meta.xml
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>47.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__HomePage</target>
        <target>lightning__AppPage</target>
    </targets>
</LightningComponentBundle>


上記コードをコピペすればそのまま動くと思います。LWCコンポーネントの入力系のサンプルコードはこんな感じでした。