6-1 情境准备
这一章我们要示范如何在表单实作一个单选的UI,单选的选项是固定的,不需要额外建立Model 来存选项。例如活动(Event)需要一个状态字段,有多少种「状态」是固定的、有限的。在后台可以编辑,前台可以显示。或是活动可以选择固定种类的分类等等,都属于这种UI。
首先,在资料库新增一个字段来存这个状态,我们会用字串代号来代表不同状态,而不直接存给用户看的中文:
- draft 代表草稿活动
- public 代表公开活动
- private 代表私密活动
这个范例使用字串来代表不同状态,有些程序员喜欢用数字。用字串的优点是一目了然,可读性高。用数字的优点是资料库占的空间较少效能较高一些,但是缺点是光看数字是不懂意义的。
这是因为:
- 要显示给用户的的中文,可能会因为需求而改变。但是资料库的资料不会改。
- 多国语系的支援,实际显示给用户的会依照用户语系而改变
- 程序可能会依赖这个代码,写程序时一律写英文比较一致,例如
if event.status == 'draft'
请执行rails g migration add_status_to_events
编辑20170414072940_add_status_to_events.rb
class AddStatusToEvents < ActiveRecord::Migration[5.0]
def change
+ add_column :events, :status, :string, :default => "draft"
end
end
执行bin/rails db:migrate
可以编辑app/models/event.rb,加上资料验证
class Event < ApplicationRecord
+ STATUS = ["draft", "public", "private"]
+ validates :status, inclusion: { in: STATUS }
6-2 显示输出
资料库存的是代码而已,实际显示给用户时,需要转换成中文,作法有两种:
方法一:用Helper
编辑app/helpers/events_helper.rb
module EventsHelper
+ def display_event_status(event)
+ case event.status
+ when "draft"
+ "草稿"
+ else
+ ""
+ end
+ end
end
编辑app/views/events/show.html.erb
+ <h2><%= display_event_status(@event) %></h2>
方法二:用I18n
如果已经配置了多国语系,可以改用i18n,以下我们会用这种做法。
编辑app/views/events/show.html.erb
+ <h2><%= t(@event.status, :scope => "event.status") %></h2>
编辑config/locals/zh-CN.yml
"zh-CN":
+ event:
+ status:
+ draft: 草稿
+ public: 公開
+ private: 私密
如果只做中文版,就不编辑 en.yml 也没关系。
6-3 使用Select 下拉选单
接着我们编辑后台的表单,加一个下拉选单来选择状态:
编辑app/views/admin/events/_form.html.erb
+ <div class="form-group">
+ <%= f.label :status %>
+
+ <%= f.select :status, Event::STATUS.map{ |s| [t(s, :scope => "event.status"), s] }, {}, :class => "form-control" %>
+ </div>
其中第二个参数 Event::STATUS.map{ |s| [t(s, :scope => "event.status"), s] } 是一个二维阵列,表示下拉的选项、第三个和第四个参数都是Hash,为了顺利让第四个参数(设置Bootstrap 样式需要的class)传进去,所以要补一个空的Hash 在第三个参数。详见Rails select 文档。
编辑app/controllers/admin/events_controller.rb
def event_params
- params.require(:event).permit(:name, :description, :friendly_id)
+ params.require(:event).permit(:name, :description, :friendly_id, :status)
end
这样就可以选择状态了:
6-4 改用Radio Button UI
如果选项是3 个以下,可以考虑改用Radio Button,对用户会更方便(鼠标只要点一次就可以选择):
再次编辑app/views/admin/events/_form.html.erb,把 f.select :status 改成:
<% Event::STATUS.each do |status| %>
<label>
<%= f.radio_button :status, status %>
<%= t(status, :scope => "event.status") %>
</label>
<% end %>
用label 标签包起来的话,点选文字才会有选radio 的效果
6-5 使用Radio Button 加上Bootstrap Button 样式
Radio Button UI 也可以考虑搭配Bootstrap 按钮样式,请修改成:
<div class="btn-group" data-toggle="buttons">
<% Event::STATUS.each do |status| %>
<label class="btn btn-default <%= (status == f.object.status)? 'active' : '' %>">
<%= f.radio_button :status, status %>
<%= t(status, :scope => "event.status") %>
</label>
<% end %>
</div>
这样就很漂亮了。