Posted at

Formtasticでオリジナルinputを作ってみた

More than 3 years have passed since last update.


シチュエーション

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属性が被ってしまうので、それを避けること