Vue.jsの`ref`属性を使ってVisualforceの要素を取得する
JavaScriptからVisualforceの要素を取得するのってめんどくさいなーって思います。
Visualforceでは設定したidの前にj_id
という生成されるidが付与されるため、
既存プロジェクトでは、jQueryを使って$('[id$=name]').val();
と後方一致を使って取得していました。
しかし、上記の方法でも後方の文字列が重複した場合100%欲しい要素が返ってくるとも限りません。
また、Visualforceのグローバル変数で$Componentを使った参照方法もありますが、 参照する際DOMの階層構造を辿って行かないといけないので使いやすさはないかも。
そこでVue.jsでref
属性でサクッと参照する方法を書いてみます。
(Vue.jsの使い方はここ)。
IdAttributeTest.cls
public with sharing class IdAttributeTest {
public String m_send_text { get; set; }
public String m_receive_text { get; set; }
public IdAttributeTest() {
m_send_text = 'init';
}
public void SaveForm() {
m_receive_text = m_send_text;
}
}
id_attribute_test.page
<apex:page controller="IdAttributeTest">
<div id="app">
<apex:form id="form">
<div>送信テキスト:<apex:inputText id="send_text" html-ref="send_text" value="{!m_send_text}" /></div>
<div>受信テキスト:<apex:outputText value="{!m_receive_text}" /></div>
<apex:commandButton action="{!SaveForm}" value="保存" />
<apex:commandButton onclick="window.ClearSendText(); return false;" value="送信テキストを空にする" />
</apex:form>
</div>
<script src="{!URLFOR($Resource.Vue_js_2_5_9, '/vue-2.5.9/dist/vue.min.js')}"></script>
<script>
var v = new Vue({
el: '#app',
mounted: function() {
alert(this.$refs.send_text.value);
this.$refs.send_text.value = 'mounted';
}
});
function ClearSendText() {
v.$refs.send_text.value = '';
}
</script>
</apex:page>
コントローラ側は、送信するテキストを入れるm_send_text
と受け取ったテキストを入れるm_receive_text
を用意します。
あとは、送信ボタン押されたときに詰め替えてページ側でテキストが送られたことを確認します(オブジェクトの保存はめんどくさいのでやらない)。
ページ側では、ref
参照したい要素が必ずVueのel
で指定したid要素より子要素になるようにDOMを構成します。
そして、参照したい要素にref
を指定するだけです(apexタグはhtml-
を付与してパススルーする)。
画面を読み込みVueのインスタンスを生成し、DOM読み込み後にインスタンスの$refs
を参照することで送信テキストを取得しています(コントローラ側のコンストラクタで文字列をセットしているのでinit
が入ってくる)。
その後、送信テキストにセットしてmounted
に書き換えています。
new Vue();
で返ってくるインスタンスは、Vueの関数内でthis
を扱うように操作できるので
好きなイベントのタイミングでVueインスタンスを参照して値を書き換えることも可能です。