#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, '×'.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>© 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] -よくある一覧画面から詳細画面へ遷移するような例を考える。 -一覧画面で検索条件が指定されていたりページングによってフィルタリングされている場合、この検索条件を詳細画面にもっていかないと戻ってこれない。 -[[» 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を指定する。