Skip to content

Instantly share code, notes, and snippets.

@andyyou
Last active August 29, 2015 14:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save andyyou/5ce254c5d1f8aa3e29e2 to your computer and use it in GitHub Desktop.
Save andyyou/5ce254c5d1f8aa3e29e2 to your computer and use it in GitHub Desktop.

問題 原本 simple_form 的 datetime <%= f.input :date_at, label: "日期" %> 會自動幫您把一個 datetime 欄位在前端 view 的部分分拆為 5 個 select,且 name 和 id 都用特殊的慣例處理過

<div class="form-group datetime optional date_at">
  <label class="datetime optional control-label" for="model_date_at_1i">日期</label>
  <select id="model_date_at_1i" name="model[date_at(1i)]" class="datetime optional form-control">
    <option value="2010">2010</option>
    ...
    <option value="2015" selected="selected">2015</option>
    <option value="2016">2016</option>
    ...
  </select>
  <select id="model_date_at_2i" name="model[date_at(2i)]" class="datetime optional form-control">
    <option value="1">January</option>
    <option value="2">February</option>
    <option value="3" selected="selected">March</option>
    <option value="4">April</option>
    <option value="5">May</option>
    ...
  </select>
  <select id="model_date_at_3i" name="model[date_at(3i)]" class="datetime optional form-control">
    <option value="1">1</option>
    <option value="2">2</option>
    ...
  </select><select id="model_date_at_4i" name="model[date_at(4i)]" class="datetime optional form-control">
    <option value="00">00</option>
    <option value="01">01</option>
    ...
  </select>
 : 
 <select id="model_date_at_5i" name="model[date_at(5i)]" class="datetime optional form-control">
    <option value="00">00</option>
    <option value="01">01</option>
    <option value="02">02</option>
    <option value="03">03</option>
    ...
  </select>
</div>

需求為想要客製 DateTimeInput 從本來的

.form-group
  label
  select
  select
  select
  select
  select

換成

.form-group
  label
  .row
    .col-md-2
      select
    .col-md-2
      select
    .col-md-2
      select
    .col-md-2
      select
    .col-md-2
      select

透過自訂 Input 的方式,但問題是不明白 Rails 預設的 @builder.date_select 是怎麼將單一個 datetime column 在前端拆成 5 個 select 然後 save 的時候又會合併成一個 datetime 的 value

# 自訂 DateTimeInput
class CustomDatetimeInput < SimpleForm::Inputs::Base
  def input
    template.content_tag(:div, class: 'row') do
      template.concat year
      template.concat month
      template.concat day
      template.concat hour
      template.concat minute
    end
  end

  def year
    template.content_tag(:div, class: 'col-md-2') do
      template.concat @builder.date_select(attribute_name, { discard_day: true, discard_month: true}, class: "form-control")
      template.concat "<span>年</span>".html_safe
    end
  end 

  def month
    template.content_tag(:div, class: 'col-md-2') do
      template.concat @builder.select(attribute_name, (1..12).to_a, {}, { class: "datetime optional form-control" })
      template.concat "<span>月</span>".html_safe
    end
  end

  def day
    template.content_tag(:div, class: 'col-md-2') do
      template.concat @builder.select(attribute_name, (1..31).to_a, {}, { class: "datetime optional form-control" })
      template.concat "<span>日</span>".html_safe
    end
  end

  def hour
    template.content_tag(:div, class: 'col-md-2') do
      template.concat @builder.select(attribute_name, (0..23).to_a.map!{ |n| n.to_s.rjust(2, '0') }, {}, { class: "datetime optional form-control" })
      template.concat "<span>時</span>".html_safe
    end
  end

  def minute
    template.content_tag(:div, class: 'col-md-2') do
      template.concat @builder.select(attribute_name, (0..59).to_a.map!{ |n| n.to_s.rjust(2, '0')  }, {}, { class: "datetime optional form-control" })
      template.concat "<span>分</span>".html_safe
    end
  end

  protected
  def get_attr_name
    position = case input_type
    when :date, :datetime
      date_order = input_options[:order] || I18n.t('date.order')
      date_order.first.to_sym
    else
      :hour
    end
    position = ActionView::Helpers::DateTimeSelector::POSITION[position]
    "#{attribute_name}_#{position}i".to_sym
  end
end

另外一個髒髒的解法發現 day 會相依 month

class CustomDatetimeInput < SimpleForm::Inputs::Base
  def input
    template.content_tag(:div, class: 'row') do
      template.concat year
      template.concat month
      template.concat day
      template.concat hour
      template.concat minute
    end
    
    
  end

  def year
    template.content_tag(:div, class: 'col-md-2') do
      template.concat @builder.date_select(attribute_name, { discard_month: true, discard_day: true }, class: "form-control")
      template.concat "<span>年</span>".html_safe
    end
  end 

  def month
    template.content_tag(:div, class: 'col-md-2') do
      template.concat @builder.date_select(attribute_name, { discard_year: true, discard_day: true }, class: "form-control")
      template.concat "<span>月</span>".html_safe
    end
  end

  def day
    template.content_tag(:div, class: 'col-md-2') do
      template.concat @builder.date_select(attribute_name, {  discard_year: true, discard_month: false, discard_day: false }, class: "form-control")
      template.concat "<span>日</span>".html_safe
    end
  end

  def hour
    template.content_tag(:div, class: 'col-md-2') do
      template.concat @builder.time_select(attribute_name, { discard_minute: true }, class: "form-control")
      template.concat "<span>時</span>".html_safe
    end
  end

  def minute
    template.content_tag(:div, class: 'col-md-2') do
      template.concat @builder.time_select(attribute_name, { discard_hour: true }, class: "form-control")
      template.concat "<span>分</span>".html_safe
    end
  end
end

相關參考文章 API1 API2 API3 API4 API5 API6 stackoverflow-1 google-group-ask API

@calvertyang
Copy link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment