2018.05.17

別Windowを開いて登録(編集)をして閉じたら、画面を自動更新するAppComponentを作ってみた!

皆様、GWはいかがお過ごしでしたでしょうか?リフレッシュできましたでしょうか?
さあ!連休は終わりましたよ、気持ちを切り替えて頑張っていきましょう!(自分にも言い聞かせています…。)

では早速、今回紹介するのはこちら!「別Windowを開いて登録(編集)をして閉じたら、画面を自動更新するAppComponentを作ってみた!」と題しまして、よく開発をする際に別ウィンドウを開いてレコードの新規登録や編集など行うことがあるかと思います、そのあと開いたWindowを閉じるのですが、呼び出し元の画面はF5キーなどで更新しないと内容が反映されない!こんなことよくあるかと思います。今回はその問題を解決でき、且つ、SkyVisualEditorで作成したいろいろ画面で使いまわすことができるようにAppComponentにしてみようという内容で記事を書きたいと思います。

AppComponentを作成してみよう

Visualforceコンポーネント(以下、VFコンポーネントとします。)を作成しましょう!
今回は2つのVFコンポーネントを作成したいと思います。

1.Salesforce標準の新規画面を呼び出すカスタムボタンのAppComponent
2.SkyVisualEditorで作成したVisualforceページを呼び出すカスタムボタンのAppComponent

使用目的(どんな時につかえる?)

例えば、このような場合に要件として上がることが多いです。

【主オブジェクトを編集したい場合】
・項目数が非常に多いような画面で、画面の1部だけを抜き出して編集したい。
(セクションで分けている部分単位で編集したい)

【関連オブジェクトを登録・編集する場合】
・新規登録や編集をしたいが遷移はしたくない。
・新規登録したいが項目数が多いので別Windowで開きたい。
 ※テーブルには表示しきれていないが、その他の項目も登録する必要がある場合
・新規登録の際にパラメータを渡したい。
 ※ 例)登録するレコードごとにレコードタイプが分かれている場合

Salesforce標準の新規画面を呼び出すカスタムボタンのAppComponent作成

コンポーネントの作成(1)

1つ目の「Salesforce標準の新規画面を呼び出すカスタムボタンのVFコンポーネント」から作っていきましょう。Developer組織をご用意いただいて、【開発】から【Visualforceコンポーネント】で新規作成します。

表示ラベル:別WindowOPEN(標準画面)とでもしときます。※任意
名前:OpenWindow_Standard ※任意
説明:省略

Visualforceコンポーネントの内容

【コンポーネントの前提条件】
 「取引先」から「取引先責任者」を新規登録する画面を開く
<apex:component>

    <!-- ボタンの表示ラベル:デフォルトは新規追加としておきます -->
    <apex:attribute name="ButtonLabel" type="String" default="新規追加" description="ボタン名" />
    
    <!-- オブジェクト:追加・編集対象となるオブジェクトのAPI参照名を指定 -->
    <apex:attribute name="ObjectName" type="String" description="オブジェクト名" />
    
    <!-- レコードId:レコードのIdをコンポーネントに受け取ります -->
    <apex:attribute name="RecordId" type="String" description="レコードId" />
    
    <!-- ウィンドウの幅: デフォルトで開くWindowの幅を指定します -->
    <apex:attribute name="WindowWidth" type="String" description="ウィンドウの幅" />
    
    <!-- ウィンドウの高さ: デフォルトで開くWindowの高さを指定します -->
    <apex:attribute name="WindowHeight" type="String" description="ウィンドウの高さ" />
    

    <!-- 以下ボタンクリック時に呼び出すJavaScript -->
    <script>
        function winOpen_Standard(){
            var urlStr = "{!URLFOR($Action[ObjectName].NewContact, null, [accid=RecordId,isdtp='vw'])}";
            var Win = window.open(urlStr,"",'width={!WindowWidth},height={!WindowHeight}');
            var interval = setInterval(function(){ 
                // 子ウィンドウが閉じられた際にウィンドウを更新する
                if(Win.closed){
                    location.reload();
                } 
            },1000);
        }
    </script>
    <apex:commandButton id="opwBtn" onclick="winOpen_Standard();" value="{!ButtonLabel}" reRender="opwBtn" rendered="{!NOT(ISBLANK(RecordId))}" />
</apex:component>
OpenWindow_Standard
URLFOR関数で指定しているActionは取引先責任者専用です。
こちらif文でオブジェクトがContactだったらなどで分けると汎用性が上がって良いかもしれません。
例)
var urlStr = '';
if('{!ObjectName}' === 'Contact'){
urlStr = "{!URLFOR($Action.Contact.NewContact, null, [accid=RecordId,isdtp='vw'])}";
}
※他のオブジェクトでは「$Action.【オブジェクト名】.New」で新規が開くのですが取引先責任者のみ「$Action.Contact.NewContact」となるそうです。
※Visualforce開発者ガイドには記載がなく少しはまりました。

【$Actionについては以下を参考にしてください】
https://developer.salesforce.com/docs/atlas.ja-jp.pages.meta/pages/pages_variables_global_action_valid_values.htm

※ URLFOR関数のパラメータの「accid=RecordId」この部分ですが「accid」これは標準画面に取引先のIdを渡しています。
※ URLFOR関数のパラメータに 「isdtp='vw' 」こちらは標準画面を別Windowで開く際にヘッダーとサイドバーを非表示にするためのパラメータです。

【JavaScriptの解説】
今回は「Win」こちらの変数で「Window .open」をし、「setInterval」で1秒ごとに監視します。
Window が閉じられると「location.reload();」で再描画させます。

AppComponent.xmlファイルの作成

VFコンポーネントも完成したので、SkyVisualEditorのStudioで使えるように、AppComponent.xmlファイルの作成を行いましょう。

以下のページからCDKをダウンロードし、AppComponent.xmlファイルを編集すると容易に作成できます。
https://info.skyvisualeditor.com/developer/develop/
<?xml version="1.0" encoding="UTF-8"?>
<ComponentDefinition xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="AppComponent_Schema.xsd" version="1.0">
        <Title>別WindowOPEN_AppCom</Title>
        <Description>別WindowOPEN_AppComponent</Description>
        <Publisher>TerraSky Co.,Ltd.</Publisher>
        <WebSite>http://www.terrasky.co.jp/</WebSite>
        <AppComponents>

                <AppComponent name="OpenWindow_Standard">
                        <Title>別WindowOPEN(標準画面)</Title>
                        <Description>別WindowでVFページを開き、閉じたら更新がかかります</Description>
                        <HelpURL>http://www.terrasky.co.jp/</HelpURL>

                        <Layout>block</Layout>
                        <Height value="18" resizable="true"/>
                        <Width value="120" resizable="true"/>

                        <!-- すべての場所に配置可能 -->
                        <PutablePlaces anyPlace="true">
                        </PutablePlaces>
                        
                        <!-- "OpenWindow_Standard"という名前のComponentを呼び出す -->
                        <ApexComponent componentName="OpenWindow_Standard">
                                <!-- スタジオで設定した変数の値を、指定したAttribute名でコンポーネントに渡す設定 -->
                                <ApexAttribute name="ButtonLabel" var="ButtonLabel"/>
                                <ApexAttribute name="ObjectName" var="ObjectName"/>
                                <ApexAttribute name="RecordId" var="RecordId"/>
                                <ApexAttribute name="WindowHeight" var="WindowHeight"/>
                                <ApexAttribute name="WindowWidth" var="WindowWidth"/>
                        </ApexComponent>
                        <!-- スタジオにおいて、ユーザーが値を設定できるようプロパティを設定 -->
                        <Properties>
                                <String name="ButtonLabel" label="ボタンラベル" defaultValue="新規登録" isRequired="true"/>
                                <String name="ObjectName" label="オブジェクト名" isRequired="true"/>
                                <String name="RecordId" label="親レコードId" defaultValue="{!record.id}" isRequired="true"/>
                                <String name="WindowHeight" label="window高さ" defaultValue="400" isRequired="false"/>
                                <String name="WindowWidth" label="window幅"  defaultValue="600" isRequired="false"/>
                        </Properties>
                </AppComponent>

        </AppComponents>

</ComponentDefinition>
AppComponent.xml

静的リソースにアップロードする

静的リソースに「AppComponent」という名前で作成して、xmlファイルをアップロードしてください。完了しましたら、SkyVisualEditorのStudioを起動し、組織に接続してください。

SkyVisualEditor Studioでの配置

Studioでの配置と設定

【AppComponentの読み込みに失敗する場合】
・XMLファイルが不正
 SkyVisualEditorスタジオからSalesforceに接続後にダイアログでエラーが表示されます。
 ※この場合は、XMLファイルを修正し、静的リソースに再アップロードして、
  SkyVisalEditorの「ツール」メニューから「オブジェクト再取得」をクリックしてください。

【配置場所】
 今回は「取引先責任者」のデータテーブルもはページブロックの中に配置しています。
 ページブロックの「ボタン表示領域」の中に配置します。
 ※XMLファイル作成時に配置できる場所は指定も可能です。

【プロパティの設定】
 今回設定は以下のようにしました。
 幅[px]    :120
 高さ[px]   :18
 ボタンラベル   :新規登録(デフォルトのまま)
 オブジェクト名  :Contact ※Api参照名で指定します
 親レコードId    :{!record.id}
           ※この書き方で主レコードのIdをVFコンポーネントへ渡しています。
 window高さ    :400
 window幅     :700
 

デプロイ後の動作確認

デプロイ後の動作確認

開いたページで新規登録して保存したあと、開いてあるWindowを閉じると、自動で更新がかかり、データテーブルに1件の取引先責任者レコードが追加されたことが確認できます。

※今回の例では、レコードタイプの選択画面を開いています。例えば商品ごとにレコードタイプが変わる。もしくは、経費レコード登録の際にレコードタイプで経費の種別が分かれている場合などに利用できるかとおもいます。

SVEで作成したVFページを開くためのカスタムボタンAppComponentの作成

コンポーネントの作成(2)

2つ目のコンポーネントです。今度はSkyVisualEditorをつかって、取引先責任者を一括登録・編集する画面を作ってみたいと思います。

【前提】
 取引先責任者は、参照で表示している項目より、登録・編集する場合では入力すべき項目が
 多いので別Window を開いて登録・編集する

【呼び出し元画面作成のPOINT!】
・親オブジェクトとして取引先を選択し、ページブロックテーブルで取引先責任者を指定
・新規登録ボタンはこれから作成するSVEで作成したVFページを開くためのカスタムボタン
 AppComponentを配置する

SVEで作成した取引先責任者の登録・修正用VFページ

SkyVisualEditorで作成した画面「SVE_ContactMultiEdit」

【呼び出し画面作成のPOINT!】
・別Windowで開くため、ヘッダー・サイドバーを非表示に設定
・参照用ページを作成しておき、保存後・編集後には遷移先に参照用ページを指定する
・カスタムボタンを配置し、ラベルは「閉じる」としておき、OnClickで「window.close();」を実行する

Visualforceコンポーネントの作成(VFページを開く用ボタン)

表示ラベル:別WindowOPEN(SVE)とでもしときます。※任意
名前:OpenWindow_Sve ※任意
説明:省略
<apex:component >

    <!-- ボタンの表示ラベル:デフォルトは新規追加としておきます -->
    <apex:attribute name="ButtonLabel" type="String" default="新規追加" description="ボタン名" />
    
    <!-- ボタン押下時に開くVisualforceページ名を指定します -->
    <apex:attribute name="VfPageName" type="String" description="Visualforceページ名" />
    
    <!-- レコードId:レコードのIdをコンポーネントに受け取ります -->
    <apex:attribute name="RecordId" type="String" description="レコードId" />
    
    <!-- ウィンドウの幅: デフォルトで開くWindowの幅を指定します -->
    <apex:attribute name="WindowWidth" type="String" description="ウィンドウの幅" />
    
    <!-- ウィンドウの高さ: デフォルトで開くWindowの高さを指定します -->
    <apex:attribute name="WindowHeight" type="String" description="ウィンドウの高さ" />

    <!-- 以下ボタンクリック時に呼び出すJavaScript -->
    <script>
        function winOpen_Standard(){
            var urlStr ='';

            urlStr = "{!URLFOR($Page[VfPageName], null, [id=RecordId])}";

            var Win = window.open(urlStr,"",'width={!WindowWidth},height={!WindowHeight}');
            var interval = setInterval(function(){ 
                // 子ウィンドウが閉じられた際にウィンドウを更新する
                if(Win.closed){
                    location.reload();
                } 
            },1000);
        }
    </script>
    <apex:commandButton id="opwBtn" onclick="winOpen_Standard();" value="{!ButtonLabel}" reRender="opwBtn" rendered="{!NOT(ISBLANK(RecordId))}" />
</apex:component>
OpenWindow_Sve
ほぼ先ほどのコンポーネントと同じですが、2番目の属性として
<apex:attribute name="VfPageName" type="String" description="Visualforceページ名" />
開きたいVisualforceページ名を指定できるようにします。

【JavaScriptの解説】
 urlStr = "{!URLFOR($Page[VfPageName], null, [id=RecordId])}";

 URLFOR関数を使い「$Page」でVisualforceページのURLを取得します
 パラメータとして親のレコードidを受け取るように「id=RecordId」としておきます。

AppComponent.xmlファイルの作成

一部分だけ抜粋して掲載します。
<?xml version="1.0" encoding="UTF-8"?>
<ComponentDefinition xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="AppComponent_Schema.xsd" version="1.0">
        <Title>別WindowOPEN_AppCom</Title>
        <Description>別WindowOPEN_AppComponent</Description>
        <Publisher>TerraSky Co.,Ltd.</Publisher>
        <WebSite>http://www.terrasky.co.jp/</WebSite>
        <AppComponents>

                <AppComponent name="OpenWindow_Sve">
                        <Title>別WindowOPEN(SVE)</Title>
                        <Description>別WindowでVFページを開き、閉じたら更新がかかります</Description>
                        <HelpURL>http://www.terrasky.co.jp/</HelpURL>

                        <Layout>inline</Layout>
                        <Height value="18" resizable="true"/>
                        <Width value="120" resizable="true"/>

                        <!-- すべての場所に配置可能 -->
                        <PutablePlaces anyPlace="true">
                        </PutablePlaces>
                        
                        <!-- "OpenWindow_Standard"という名前のComponentを呼び出す -->
                        <ApexComponent componentName="OpenWindow_Sve">
                                <!-- スタジオで設定した変数の値を、指定したAttribute名でコンポーネントに渡す設定 -->
                                <ApexAttribute name="ButtonLabel" var="ButtonLabel"/>
                                <ApexAttribute name="VfPageName" var="VfPageName"/>
                                <ApexAttribute name="RecordId" var="RecordId"/>
                                <ApexAttribute name="WindowHeight" var="WindowHeight"/>
                                <ApexAttribute name="WindowWidth" var="WindowWidth"/>
                        </ApexComponent>
                        <!-- スタジオにおいて、ユーザーが値を設定できるようプロパティを設定 -->
                        <Properties>
                                <String name="ButtonLabel" label="ボタンラベル" defaultValue="責任者登録・編集" isRequired="true"/>
                                <String name="VfPageName" label="Visualforceページ名" defaultValue="{$Page.[VisualforcePage名]}" isRequired="true"/>
                                <String name="RecordId" label="親レコードId" defaultValue="{!record.id}" isRequired="true"/>
                                <String name="WindowHeight" label="window高さ" defaultValue="400" isRequired="false"/>
                                <String name="WindowWidth" label="window幅"  defaultValue="600" isRequired="false"/>
                        </Properties>
                </AppComponent>
        </AppComponents>

</ComponentDefinition>
AppComponent.xml
完成しましたら、静的リソースにアップロードします。

SkyVisualEditorのStudioで作成したAppComponentのボタンを配置しデプロイしてください。

デプロイ後の動き

デプロイ後の動き

Lightning Experienceでの利用

おまけになりますが、Lightning Experienceの標準の新規登録画面では、一度に複数件のレコードを登録したり、一括で編集したりすることができません。ですが、SkyVisualEditorを利用いただければ、一括登録や一括編集の画面も簡単に作成することができます。以下はSkyVisualEditorで作成したVisualforceページの利用例になります。

※今回実装していませんが、SkyVisualEditorから出力する画面は、LightningDesignSystemのスタイル適用することもできます。

SkyVisualEditor V8.0 ヘルプドキュメント - Salesforce Lightning Design Systemの適用サンプル -
https://doc.terrasky.com/pages/viewpage.action?pageId=12752951

LEXでの利用

45 件
     
  • banner
  • banner

関連する記事