シチュエーション
Formtasticは最初から多数のinput形式が利用可能で、大半の要件はその範囲内で片付きますが、たまにその範囲を逸脱したい場合があり、そのために自作inputを作れるようになっています。この機能を使って、「textareaが2つあるinput」を作ってみました。
実装
app/inputs/double_text_input.rb
class DoubleTextInput < Formtastic::Inputs::TextInput
def to_html
# FIXME: gemとかに切り出すときは width:calc(40% - 22pt) というstyleを適用させる
input_wrapping do
label_html <<
builder.text_area(method, input_html_options) <<
build_second_text_area
end
end
private
def build_second_text_area
original_method = method
self.method = :"#{original_method}_2"
text_area = builder.text_area(method, input_html_options)
self.method = original_method
text_area
end
end
呼ぶときは f.input :description, as: :double_text
という感じで呼びます。そうすると
<li class="double_text input optional" id="item_description_input">
<label for="item_description" class="label">Description</label>
<textarea rows="20" id="item_description" name="item[description]">
</textarea>
<textarea rows="20" id="item_description_2" name="item[description_2]">
</textarea>
</li>
こんな感じのhtmlが出力されます。見ての通り、2つ目のtextareaのnameに_2をつけてるだけなので、受け取る方が_2をつけた項目を受け取れるようになっている必要があります。
解説
概要
READMEに記載の通り、to_htmlメソッドで返す文字列がそのinputの部分htmlとして使用されるので、ここをいじります。
今回は普通のTextInputのtextareaのうしろに2つ目のtextareaを追加しています。
Formtasticのメソッドの切り方に起因して、ちょっと追加する修正でも親クラスのメソッドをコピーして修正するようなやり方が必要になるケースがままあります。
build_second_text_areaメソッドの処理内容
一時的にmethodというインスタンス変数(Inputクラス共通でattr_accessorが定義してあります)の内容を書き換えています。これには以下の2つの目的があります。
- textareaのname属性(builder.text_areaの第1引数が使われる)が被らないようにすること
- input_html_optionsメソッドの中でmethod変数をtextareaのid属性を構成するのに使っていて、そのままtextareaを出力してしまうと、2つのtextareaのid属性が被ってしまうので、それを避けること