#author("2017-07-10T13:53:13+09:00","default:wikiwriter","wikiwriter")
#author("2018-07-27T13:42:41+09:00","default:wikiwriter","wikiwriter")
&tag(Rails/ビューヘルパー);
*目次 [#oc9a944f]
#contents
*関連ページ [#j3830015]
-[[Rails]]
*参考情報 [#jc95aec1]
-[[ActionView::Helpers::FormTagHelper:http://api.rubyonrails.org/classes/ActionView/Helpers/FormTagHelper.html]] //tag系のドキュメント。
^

*リンク [#wa110665]
**別ウィンドウで開く [#zf89a9be]
-targetを指定する
 <%= link_to("外部サイト", 'http://example.com/', target:  '_blank') %>


**link_toでfont-awesomeのアイコンを使用する [#hcbcfd89]
-いろいろな方法があるらしいけどrawを使うのが簡単。
 <%= link_to(raw("<i class='fa fa-home' title='配布元'></i>"), 'http://example.com/', target:  '_blank') %>

*form  [#n6e1c166]

**form_for [#r2a2c009]

-form_forでモデル連携型のフォームが生成できる。
#pre{{
<%= form_for(@book) do |f| %>
タイトル: <%= f.text_field(:title, {:size => 40}) %>
<%= f.submit %>
<%= end %>
}}
-@bookが保存されているかどうかで、呼ばれるアクションが自動的に変わる。

**form_tag [#ie01aa9d]
-form_tagでもモデル連動は可能。
#pre{{
<%= form_tag({ :controller => 'books', :action => 'create'}) do %>
タイトル: <%= text_field(:book , :title, {:size => 40}) %>
<%= f.submit %>
<% end %>
}}

*ラベル [#yfcfee16]
**f.label [#hafa02c3]
-プロパティ名と実際に表示する文字列を併記する場合(プロパティ名は対応するコントロールにフォーカスを移すために必要)
#pre{{
<%= f.label :title, 'タイトル' %>
}}
*セレクト [#y126c61a]
tag系とそれ以外で最後のオプションの渡し方がことなるので注意。

**f.select [#x39e66c8]
-配列から生成。
 <%= f.select(:object_field, ['Item 1', ...], {}, { class: 'my_style_class' }) %>
-オブジェクトの配列から生成。
  <%= f.select(:category_id, Category.all.map{|category| [category.title, category.id]}, {include_blank: '選択'}, {class: 'form-control'} ) %>
**select_tag [#c1f82df1]

-options_for_selectを使えばオブジェクトの配列から生成することができる。
 select_tag 'xxx', options_for_select(@objects.map{|obj| [obj.title, obj.id]})
 
**options_for_select注意点 [#o1eaa616]
-ハッシュを渡してもいいけど、順番が保証されない。
-配列の配列を渡すのがいいらしい。
-もしくはオブジェクトの配列で上のようにmapする。

*チェックボックス [#k2aba0ff]

**f.check_box [#u6203188]
-プロパティ名、HTMLオプション、チェック値、非チェック値の順に渡す。
 f.check_box(accepted:, {class: 'my-checkbox'}, 'yes', 'no');
-チェックしてないときにnilを渡したい場合、nilを指定する。
 f.check_box(accepted:, {class: 'my-checkbox'}, 'yes', nil);

**複数のチェックボックスの値を送信 [#b006fabe]
-Railsではチェックボックスの名前の後ろに括弧を追加してマークアップすると、サーバー側で配列として取り扱うことができる。
-例えば以下のように。
 <%= check_box_tag "todo_ids[]", todo.id %>
-しかしこのままだと複数存在するinputタグのidが"todo_ids_"で全て同じになってしまう。[[ajax - How do I set a unique ID for checkboxes in a multi-record Rails form? - Stack Overflow:https://stackoverflow.com/questions/992094/how-do-i-set-a-unique-id-for-checkboxes-in-a-multi-record-rails-form]]
-これを回避するためには、:idを明示するしかないかもしれない。
 <%= check_box_tag "todo_ids[]", todo.id, false, :id => "todo_id_#{todo.id}" %>
*サブミット [#l6587f05]

**確認メッセージを表示する [#lf4d256a]
-submit_tagで確認メッセージを表示する。
#pre{{
  <%= submit_tag('削除',  {name: 'delete', class: 'btn btn-danger', data: {confirm: '削除しますか?'} } ) %>
}}

*hidden [#d11f3985]

**f.hidden_field [#i686a02b]
-通常はプロパティ名のみ
 <%= f.hidden_field(:folder_id) %>
-値を指定する場合
 <%= f.hidden_field(:folder_id, value: 9) %>

*Bootstrap3との連携 [#oc8fcf22]
-[[twbs/bootstrap-sass:https://github.com/twbs/bootstrap-sass]]を使って、rails4とbootstrap3を連携している場合を考える。


**メッセージの表示 [#ce35795a]
-application_helper.rbに以下を追加
#pre{{
  def bootstrap_class_for flash_type
    { success: "alert-success", error: "alert-danger", alert: "alert-warning", notice: "alert-info" }[flash_type.to_sym] || flash_type.to_s
  end

  def flash_messages(opts = {})
    flash.each do |msg_type, message|
      concat(content_tag(:div, message, class: "alert #{bootstrap_class_for(msg_type)} alert-dismissible", role: 'alert') do
               concat(content_tag(:button, class: 'close', data: { dismiss: 'alert' }) do
                        concat content_tag(:span, '&times;'.html_safe, 'aria-hidden' => true)
                        concat content_tag(:span, 'Close', class: 'sr-only')
                      end)
               concat message
             end)
    end
    nil
}}
-application.html.erbに以下を追加
#pre{{
<div class="container">
    <!-- flash message -->
    <%= flash_messages %>

    <%= yield %>

    <hr>
    <footer>
        <p>&#169; src256</p>
    </footer>

</div>
}}
-controllerで以下のように設定すると、画面の上部にBootstrap風のエラー画面が表示される。
#pre{{
    msg = "保存しました"
    flash[:notice] = msg
    redirect_to(software_path(id, take_params))
}}


**一覧画面 [#v38f039a]
-Bootstrap3を使ってテーブルを一覧表示(index.html.erb)
#pre{{
<h1>アイテム一覧</h1>

<table class="table">
    <tr>
        <th class="col-xs-3">カテゴリ</th>
        <th class="col-xs-3">タイトル</th>
        <th class="col-xs-3">コンテンツ</th>
        <th class="col-xs-3">操作</th>
    </tr>

    <% @items.each do |item| %>
        <tr>
            <td><%= item.category_id %></td>
            <td><%= item.title %></td>
            <td><%= item.content %></td>
            <td><%= link_to 'Show', item %></td>
            <td><%= link_to 'Edit', edit_item_path(item) %></td>
            <td><%= link_to 'Destroy', item, method: :delete, data: { confirm: 'Are you sure?' } %></td>
        </tr>
    <% end %>
</table>

<br>

<%= link_to 'アイテム追加', new_item_path %>

}}

**追加・編集画面 [#za2fee55]
-form-horizontalでラベルとコントロールを横に並べる。
-labelはインライン要素だが"display: inline-block"が指定されているので幅が指定できる(divで囲む必要がない)
-control-labelを指定すれば、右寄せ垂直方向中心となる。
#pre{{
<%= form_for(@item, html: {class: 'form-horizontal'}) do |f| %>
    <% if @item.errors.any? %>
        <div id="error_explanation">
            <h2>エラーが発生しました :</h2>
            <ul>
                <% @item.errors.full_messages.each do |msg| %>
                    <li><%= msg %></li>
                <% end %>
            </ul>
        </div>
    <% end %>

    <div class="form-group">
        <%= f.label(:category_id, 'カテゴリ', class: 'col-xs-2 control-label') %>
        <div class="col-xs-10">
            <%= f.select(:category_id, Category.all.map{|category| [category.title, category.id]}, {include_blank: '選択'}, {class: 'form-control'} ) %>
        </div>
    </div>
    <div class="form-group">
        <%= f.label(:folder_id, 'フォルダ', class: 'col-xs-2 control-label') %>
        <div class="col-xs-10">
            <%= f.select(:folder_id, Folder.all.map{|folder| [folder.title, folder.id]}, {include_blank: '選択'}, {class: 'form-control'} ) %>
        </div>
    </div>
    <div class="form-group">
        <%= f.label(:title, 'タイトル', class: 'col-xs-2 control-label') %>
        <div class="col-xs-10">
            <%= f.text_field(:title, class: 'form-control') %>
        </div>
    </div>
    <div class="form-group">
        <%= f.label(:content, 'コンテンツ', class: 'col-xs-2 control-label') %>
        <div class="col-xs-10">
            <%= f.text_area(:content, rows: 14, cols: 20, class: 'form-control') %>
        </div>
    </div>
    <div class="form-group">
        <div class="col-xs-12">
            <%= f.submit('保存', class: 'btn btn-primary') %>
        </div>
    </div>
<% end %> 
}}


*Tips [#c0cc0501]

**検索条件を引き回す [#z52a197b]
-よくある一覧画面から詳細画面へ遷移するような例を考える。
-一覧画面で検索条件が指定されていたりページングによってフィルタリングされている場合、この検索条件を詳細画面にもっていかないと戻ってこれない。
-[[&#187; URL パラメータの一部を遷移先に引き継ぐ TECHSCORE BLOG:http://www.techscore.com/blog/2012/12/10/url-%E3%83%91%E3%83%A9%E3%83%A1%E3%83%BC%E3%82%BF%E3%81%AE%E4%B8%80%E9%83%A8%E3%82%92%E9%81%B7%E7%A7%BB%E5%85%88%E3%81%AB%E5%BC%95%E3%81%8D%E7%B6%99%E3%81%90/]]にあるtake_paramsを使うと便利。
#pre{{
  def default_take_param_keys
    %w(page per_page)
  end 
 
 def take_params(*param_keys)
    overwrites = param_keys.extract_options!
    param_keys = default_take_param_keys if param_keys.blank?
    params.dup.extract!(*param_keys).update(overwrites)
  end 
  helper_method :take_params
}}
-オリジナルの記事で紹介されているのは、検索ページから検索条件を詳細画面に引き継ぎ、詳細画面のビュー元の検索画面に戻ってくるような事例。どちらもlink_toでtake_paramsを指定する。これによってparams[:page]やparams[:q]のような情報を簡単に引き継ぐことが可能となる。
-その他のバリエーションとして詳細画面がフォームになっていて、登録後検索画面に戻るときは、controllerのredirect_toでtake_paramsを指定する。

トップ   編集 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS