完璧じゃなくてもとりあえず終わらせるブログ

主にSalesforceの悪夢を記録しています

ApexからJavaScriptに値を渡す、JavaScriptからApexに値を渡す

Visualforceに仕込んだJavaScriptと、VisualforceのcontrollerであるApexとで値の受け渡しをしたい場面があったのでメモしておきます。

ApexからJavaScriptに値を渡す

JavaScript側でApexが持つプロパティの値を使用したいとき、ですね。
これは単純。

Apex側でプロパティを定義
public with sharing class sample1{

    public String hoge {get; set;}    // このプロパティの値をJavaScriptで使用したい

    public sample1() {
        this.hoge = 'Apex側で値をセット';
    }
}
JavaScriptの変数にセット(Visualforce内)
<apex:page id="pg" docType="html-5.0" controller="sample1">
    <apex:form id="fm">
        -中略-
        <script>
            function () {
                let cHoge = '<apex:outputtext value="{!hoge}"></apex:outputtext>';
                console.log(cHoge);
            }
        </script>
    </apex:form>
</apex:page>

JavaScriptの中に直接Apexタグを埋め込んでしまう、というなんて素敵な渡し方。
要するにApexタグはコンパイル時に解釈されてhtmlに置き換わるので、結局は直接書いているのと同じになるということなんですね。はぇー。

apex:outputtextを使っているので、このタグの書式設定を利用してこんな書き方もできます。

let cHoge = '<apex:outputtext value="{0,date,yyyy/MM/dd}"><apex:param value="{!hoge}"/></apex:outputtext>';

使いどころがあんまり想像できないけど。


JavaScriptからApexに値を渡す

Apex側でJavaScriptが処理した値を使用したいとき、ですね。
こちらは少し工夫して頑張る。

Apex側でプロパティを定義
public with sharing class sample2{

    public Decimal fuga {get; set;}    // このプロパティに値を受け取りたい
    public Decimal inputValue {get; set;}    // 便宜上用意しただけのプロパティ

    public sample2() {
        // 処理なし
    }

    public void submit() {
        System.debug('fuga:' + fuga);
    }
}
JavaScript側でApexのプロパティにセット(Visualforce内)
<apex:page id="pg" docType="html-5.0" controller="sample2">
    <apex:form id="fm">
        <apex:inputHidden id="id_fuga" value="{!fuga}" />

        <apex:input id="theTextInput" value="{!inputValue}" type="number" />
        <apex:commandButton id="theButton" onclick="hundredfold(); return false;" value="JavaScriptCall" />
        <apex:commandButton id="theApexButton" action="{!submit}" value="ApexCall" />

        <script>
            function hundredfold() {    // inputを100倍にしてApexプロパティにセット
                let input = document.getElementById('{!$Component.pg.fm.theTextInput}');
                let fugaInput = document.getElementById('{!$Component.pg.fm.id_fuga}');
                fugaInput.value = input.value * 100;
            }
        </script>
    </apex:form>
</apex:page>

要するに、
inputHiddenで持っておいて、JavaScriptで適宜セットしておけば、ApexメソッドをCallしたときに参照できる
ということですね。

解説

[line:3]inputHiddenでApexプロパティを保持。
[line:5]入力ボックスを用意。
[line:6]JavaScriptをCallするためのボタン。commandButtonだと問答無用でsubmitされるため、"return false;"で抑止。
[line:7]ApexメソッドをCallするためのボタン。
[line:11]入力タグを取得。
[line:12]inputHiddenを取得 = Apexプロパティを取得。
[line:13]処理結果をApexプロパティのvalueにセット。

このサンプルではこんなことをして何が嬉しいのかさっぱりわからないですが、
イベントが発生する度にJavaScriptで処理を実行し、必要な値をApexに連携して使用する
という用途はありそうです。
最終的なvalidationはサーバーサイドで実行すべきですし。

それにしても、jQueryを使わずgetElementByIdでタグを取得するの面倒くさすぎるだろ。



よし、とりあえず終わらせたぞ