Rails,简单形式的 flatpickr 不工作

Rails, flatpickr in simple-form not working

首先让我快速解释一下上下文。我创建了这个应用程序,用户可以在其中组织音乐即兴表演。所以基本上他们有可能创造这样的事件。系统会提示他们输入日期和当天的时间范围。 在我的数据库中,即兴演奏有一个 start_date 和一个 end_date,它们都是日期时间格式。这可能会让我的生活变得更艰难,因为有一个日期 (y-m-d) 以及 start_time 和 end_time 会更合乎逻辑。 也许一个新的迁移来改变是最好的解决方案,但让我问一下我是否可以像现在这样绕过它。

到目前为止,我设法让它工作(有点),但没有用 flatpickr。

这是与此问题相关的代码:

1/ 在我的 app/javascript/packs/application.js 中我有这个(TimePicker 在另一个页面上用于搜索,顺便说一下它工作正常。在这里我尝试使用 datepicker):

import "bootstrap";
import "../plugins/flatpickr";

import flatpickr from "flatpickr";
import rangePlugin from "flatpickr/dist/plugins/rangePlugin";
import 'flatpickr/dist/flatpickr.min.css'

import 'mapbox-gl/dist/mapbox-gl.css'; // <-- you need to uncomment the stylesheet_pack_tag in the layout!
import { initMapbox } from '../plugins/init_mapbox';

flatpickr(".datepicker", {
  minDate: new Date,
  altInput: true,
});

flatpickr(".TimePicker", {
    // enableTime: true,
    minDate: new Date,
    altInput: true,
    plugins: [new rangePlugin({ input: ".timePicker-end"})]
  });

initMapbox();

2/ schema.rb 文件(仅涉及即兴演奏 table 的部分):

  create_table "jam_sessions", force: :cascade do |t|
    t.string "title"
    t.string "description"
    t.string "genre"
    t.datetime "starts_at"
    t.datetime "ends_at"
    t.string "location"
    t.bigint "user_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.float "latitude"
    t.float "longitude"
    t.index ["user_id"], name: "index_jam_sessions_on_user_id"
  end

3/表格所在的新文件:

<% music_genre = ["Acapella", "Accoustic", "Blues", "Classical", "Country", "Electronic", "Folk", "Funk", "Heavy Metal", "Hip Hop", "Jazz", "Latin", "Other", "Pop", "Reggae", "Rock", "World"] %>

<div class="container h-100">
  <div class="row justify-content-center align-items-center mt-3">
    <div class="col col-6">

      <h2>Create your own Jam Session</h2>

      <%= simple_form_for [@jam_session] do |f| %>
      <% f.error_notification %>
      <%= f.error_notification message: f.object.errors[:base].to_sentence if f.object.errors[:base].present? %>

        <div class="form-inputs">
          <%= f.input :title %>
          <%= f.input :description %>
          <%= f.input :genre, collection: music_genre %>
          <div class="row justify-content-center align-items-center mt-3">
            <%= f.input :starts_at, as: :string, required: true, input_html: {class: "datepicker"} %>
            <%= f.input :starts_at, as: :time, :minute_step => 15, required: true %>
            <%= f.input :ends_at, as: :time, :minute_step => 15, required: true %>
          </div>
          <%= f.input :location %>
        </div>

        <div class="d-flex justify-content-end">
          <%= f.button :submit, "GO !", class: 'big-button block' %>
        </div>
      <% end %>
    </div>
  </div>
</div>

4/ jam_sessions 控制器

class JamSessionsController < ApplicationController
  def index
    # @jam_sessions = JamSession.search_by_location(params[:query])

    @jam_sessions = JamSession.includes(:spots, :instruments)
    # @jam_sessions = @jam_sessions.where(instruments: { id: jam_session_params[:instrument_id] }) if jam_session_params[:instrument_id].present?
    @jam_sessions = @jam_sessions.where(instruments: { id: params["jam_session"]["instrument_id"] }) if params["jam_session"]["instrument_id"].present?
    @jam_sessions = @jam_sessions.where(genre: params["jam_session"]["genre"]) if params["jam_session"]["genre"].present?
    @jam_sessions = @jam_sessions.search_by_location(params["jam_session"]["location"]) if params["jam_session"]["location"].present?


    if params[:jam_session] && params[:jam_session][:starts_at]
      x = params[:jam_session][:starts_at]

      @start_date = x&.split("to")[0]&.strip
      @end_date = x&.split("to")[1]&.strip

      @jam_sessions = @jam_sessions.where("starts_at > ?", @start_date) if @start_date.present?
      @jam_sessions = @jam_sessions.where("starts_at < ?", @end_date) if @end_date.present?
    end

    # -------- access input from user ---------
    # @location_input = params["jam_session"]["location"]
    # @starts_at_input = params["jam_session"]["starts_at"]
    # @ends_at_input = params["jam_session"]["ends_at"]
    # @instrument_input = Instrument.find(params["jam_session"]["instrument_id"]).name if params["jam_session"]["instrument_id"].present?
    geocode(@jam_sessions)
    # access id of instruments
    @session_instruments_id = Instrument.all
  end

  def show
    @jam_session = JamSession.find(params[:id])
    @markers = [{
      lat: @jam_session.latitude,
      lng: @jam_session.longitude,
      infoWindow: render_to_string(partial: "info_window", locals: { jam_session: @jam_session }),
      image_url: helpers.asset_url("custom_marker.png"),
    }]
    @messages = JamSession.includes(messages: :user).find(params[:id])
  end

  def new
    @jam_session = JamSession.new
  end

  def create
    @jam_session = JamSession.new(jam_session_params)
    @jam_session.user = current_user
    if @jam_session.save
      redirect_to jam_session_path(@jam_session)
    else
      render "new"
    end
  end

  private

  def geocode(jam_sessions)
    @jam_sessions = @jam_sessions.geocoded #returns jam_sessions with coordinates

    @markers = @jam_sessions.map do |jam_session|
      {
        lat: jam_session.latitude,
        lng: jam_session.longitude,
        infoWindow: render_to_string(partial: "info_window", locals: { jam_session: jam_session }),
        image_url: helpers.asset_url("custom_marker.png"),
      }
    end


  end

  def jam_session_params
    params.require(:jam_session).permit(:title, :description, :genre, :starts_at, :ends_at, :location, :instrument_id)
  end
end

但是没用。视觉上确实如此,这意味着日历出现并且用户似乎输入了正确的日期,但最后,该日期被忽略,而是默认情况下将当天的日期记录在数据库中。

它以简单形式使用此代码,但它很丑陋,而且只有我将日期字段放在小时字段之后,这是违反直觉的:

<div class="row justify-content-center align-items-center mt-3">
  <%= f.input :starts_at, as: :time, :minute_step => 15, required: true %>
  <%= f.input :ends_at, as: :time, :minute_step => 15, required: true %>
  <%= f.input :starts_at, as: :date, required: true %>
</div>

想知道如何使用 flatipckr 来完成这项工作吗?

这里有两个版本的表格。

使用日期选择器(不工作):

只是简单的形式(工作但丑陋):

这是我创建 JAM 会话时的日志。第一部分(在 ^[[B^[[B 之前是加载新页面时,表单所在的位置。之后是提交表单后的日志。要清楚,我输入的开始日期是 28 日但它记录了今天的日期 buy defautl)

Started GET "/jam_sessions/new" for ::1 at 2020-04-08 09:54:14 +0200
Processing by JamSessionsController#new as HTML
  User Load (0.3ms)  SELECT  "users".* FROM "users" WHERE "users"."id" =  ORDER BY "users"."id" ASC LIMIT   [["id", 1], ["LIMIT", 1]]
  ↳ /home/olivier/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/activerecord-5.2.4.1/lib/active_record/log_subscriber.rb:98
  Rendering jam_sessions/new.html.erb within layouts/application
  Rendered jam_sessions/new.html.erb within layouts/application (41.1ms)
  ActiveStorage::Attachment Load (0.3ms)  SELECT  "active_storage_attachments".* FROM "active_storage_attachments" WHERE "active_storage_attachments"."record_id" =  AND "active_storage_attachments"."record_type" =  AND "active_storage_attachments"."name" =  LIMIT   [["record_id", 1], ["record_type", "User"], ["name", "photo"], ["LIMIT", 1]]
  ↳ app/views/shared/_navbar.html.erb:19
  ActiveStorage::Blob Load (0.4ms)  SELECT  "active_storage_blobs".* FROM "active_storage_blobs" WHERE "active_storage_blobs"."id" =  LIMIT   [["id", 1], ["LIMIT", 1]]
  ↳ app/views/shared/_navbar.html.erb:19
  Rendered shared/_navbar.html.erb (5.0ms)
[Webpacker] Everything's up-to-date. Nothing to do
  Rendered shared/_footer.html.erb (0.3ms)
Completed 200 OK in 67ms (Views: 63.4ms | ActiveRecord: 1.0ms)


^[[B^[[B
Started POST "/jam_sessions" for ::1 at 2020-04-08 09:54:59 +0200
Processing by JamSessionsController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"rA4WsBD2H9qDMp9/Jt/kxvJ6sJ+cHnRLByH0yFJlO/dm7EbNeuCtV3DK25pKVvb0RyaTWz2cUDhxWukL3HGMWQ==", "jam_session"=>{"title"=>"Let's play", "description"=>"sdfkjqsdhflkjshdflkjqs", "genre"=>"Country", "starts_at"=>"2020-04-28", "starts_at(1i)"=>"2020", "starts_at(2i)"=>"4", "starts_at(3i)"=>"8", "starts_at(4i)"=>"07", "starts_at(5i)"=>"00", "ends_at(1i)"=>"2020", "ends_at(2i)"=>"4", "ends_at(3i)"=>"8", "ends_at(4i)"=>"09", "ends_at(5i)"=>"00", "location"=>"Berlin"}, "commit"=>"GO !"}
  User Load (0.4ms)  SELECT  "users".* FROM "users" WHERE "users"."id" =  ORDER BY "users"."id" ASC LIMIT   [["id", 1], ["LIMIT", 1]]
  ↳ /home/olivier/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/activerecord-5.2.4.1/lib/active_record/log_subscriber.rb:98
   (0.3ms)  BEGIN
  ↳ app/controllers/jam_sessions_controller.rb:50
  JamSession Create (0.8ms)  INSERT INTO "jam_sessions" ("title", "description", "genre", "starts_at", "ends_at", "location", "user_id", "created_at", "updated_at", "latitude", "longitude") VALUES (, , , , , , , , , , ) RETURNING "id"  [["title", "Let's play"], ["description", "sdfkjqsdhflkjshdflkjqs"], ["genre", "Country"], ["starts_at", "2020-04-08 07:00:00"], ["ends_at", "2020-04-08 09:00:00"], ["location", "Berlin"], ["user_id", 1], ["created_at", "2020-04-08 07:54:59.230840"], ["updated_at", "2020-04-08 07:54:59.230840"], ["latitude", 52.5170365], ["longitude", 13.3888599]]
  ↳ app/controllers/jam_sessions_controller.rb:50
   (0.8ms)  COMMIT
  ↳ app/controllers/jam_sessions_controller.rb:50
Redirected to http://localhost:3000/jam_sessions/22
Completed 302 Found in 191ms (ActiveRecord: 2.3ms)


Started GET "/jam_sessions/22" for ::1 at 2020-04-08 09:54:59 +0200
Processing by JamSessionsController#show as HTML
  Parameters: {"id"=>"22"}
  JamSession Load (0.5ms)  SELECT  "jam_sessions".* FROM "jam_sessions" WHERE "jam_sessions"."id" =  LIMIT   [["id", 22], ["LIMIT", 1]]
  ↳ app/controllers/jam_sessions_controller.rb:33
  Rendered jam_sessions/_info_window.html.erb (0.7ms)
  CACHE JamSession Load (0.0ms)  SELECT  "jam_sessions".* FROM "jam_sessions" WHERE "jam_sessions"."id" =  LIMIT   [["id", 22], ["LIMIT", 1]]
  ↳ app/controllers/jam_sessions_controller.rb:40
  Message Load (0.3ms)  SELECT "messages".* FROM "messages" WHERE "messages"."jam_session_id" =   [["jam_session_id", 22]]
  ↳ app/controllers/jam_sessions_controller.rb:40
  Rendering jam_sessions/show.html.erb within layouts/application
  User Load (0.3ms)  SELECT  "users".* FROM "users" WHERE "users"."id" =  LIMIT   [["id", 1], ["LIMIT", 1]]
  ↳ app/views/jam_sessions/show.html.erb:12
  User Load (0.2ms)  SELECT  "users".* FROM "users" WHERE "users"."id" =  ORDER BY "users"."id" ASC LIMIT   [["id", 1], ["LIMIT", 1]]
  ↳ app/views/jam_sessions/show.html.erb:12
  Spot Load (0.3ms)  SELECT "spots".* FROM "spots" WHERE "spots"."jam_session_id" =   [["jam_session_id", 22]]
  ↳ app/views/jam_sessions/show.html.erb:13
  User Exists (0.6ms)  SELECT  1 AS one FROM "users" INNER JOIN "participations" ON "users"."id" = "participations"."user_id" INNER JOIN "spots" ON "participations"."spot_id" = "spots"."id" WHERE "spots"."jam_session_id" =  AND "users"."id" =  LIMIT   [["jam_session_id", 22], ["id", 1], ["LIMIT", 1]]
  ↳ app/models/jam_session.rb:35
  Rendered shared/_chat-messages.html.erb (4.2ms)
  Spot Exists (0.4ms)  SELECT  1 AS one FROM "spots" LEFT OUTER JOIN "participations" ON "participations"."spot_id" = "spots"."id" WHERE "spots"."jam_session_id" =  AND "participations"."spot_id" IS NULL LIMIT   [["jam_session_id", 22], ["LIMIT", 1]]
  ↳ app/views/jam_sessions/show.html.erb:86
  CACHE User Exists (0.0ms)  SELECT  1 AS one FROM "users" INNER JOIN "participations" ON "users"."id" = "participations"."user_id" INNER JOIN "spots" ON "participations"."spot_id" = "spots"."id" WHERE "spots"."jam_session_id" =  AND "users"."id" =  LIMIT   [["jam_session_id", 22], ["id", 1], ["LIMIT", 1]]
  ↳ app/models/jam_session.rb:35
  SQL (0.5ms)  SELECT "spots"."id" AS t0_r0, "spots"."jam_session_id" AS t0_r1, "spots"."instrument_id" AS t0_r2, "spots"."created_at" AS t0_r3, "spots"."updated_at" AS t0_r4, "participations"."id" AS t1_r0, "participations"."spot_id" AS t1_r1, "participations"."user_id" AS t1_r2, "participations"."created_at" AS t1_r3, "participations"."updated_at" AS t1_r4 FROM "spots" LEFT OUTER JOIN "participations" ON "participations"."spot_id" = "spots"."id" WHERE "spots"."jam_session_id" =  AND "participations"."spot_id" IS NULL  [["jam_session_id", 22]]
  ↳ app/views/jam_sessions/show.html.erb:95
  Rendered jam_sessions/show.html.erb within layouts/application (14.5ms)
  ActiveStorage::Attachment Load (0.4ms)  SELECT  "active_storage_attachments".* FROM "active_storage_attachments" WHERE "active_storage_attachments"."record_id" =  AND "active_storage_attachments"."record_type" =  AND "active_storage_attachments"."name" =  LIMIT   [["record_id", 1], ["record_type", "User"], ["name", "photo"], ["LIMIT", 1]]
  ↳ app/views/shared/_navbar.html.erb:19
  ActiveStorage::Blob Load (0.3ms)  SELECT  "active_storage_blobs".* FROM "active_storage_blobs" WHERE "active_storage_blobs"."id" =  LIMIT   [["id", 1], ["LIMIT", 1]]
  ↳ app/views/shared/_navbar.html.erb:19
  Rendered shared/_navbar.html.erb (4.2ms)
[Webpacker] Everything's up-to-date. Nothing to do
  Rendered shared/_footer.html.erb (0.3ms)
Completed 200 OK in 41ms (Views: 32.3ms | ActiveRecord: 3.9ms)

谢谢! 奥利维尔

好的,你有两个字段都是“starts_at”,所以第二个会覆盖第一个。

我不确定 flatpickr 是否也可以在小弹出窗口中设置结束时间。我知道它可以在一个弹出窗口中有开始和结束日期以及时间,但我不确定结束时间。因此,您可能想要做的是在一个字段中只 select 日期,然后是您已经准备好的两个时间字段。然后在创建操作的控制器中,在创建新的即兴会话之前将所有内容放在一起

因此其中一个“starts_at”字段,您需要重命名。 Simple_form 不会喜欢这样,因为它会查看即兴会话对象,而不仅仅是另一个日期列。所以在这里我们需要稍微欺骗一下,只需在计划 html 中或使用来自 rails.

的助手编写输入字段

您可以只在表单中包含一个输入字段,它将与表单一起提交,但我们要确保信息在参数中的正确位置。 你知道关于即兴表演的所有信息都嵌套在参数散列中的键 "jam_session" 下。

params = {..., "jam_session"= {"title"=>"Let's play", ... }... }

它是如何嵌套在那里的?那是因为你的简单形式中的每一行,一旦被渲染成 html,都有一个 name 属性,它决定了 params 散列的结构。 (在浏览器中检查表单的每个输入字段)。它看起来像这样:

<input class="form-control" type="text" name="jam_session[title]" id="jam_session_title">

而且我们必须复制日期 - 我们称它为日,以便我们区分它。

<input class="form-control" type="text" name="jam_session[day]" id="jam_session_day" class="datepicker">

不要忘记添加日期选择器 class。

现在这应该会产生一个参数散列,它有一天,还有 start_dateend_date。从开始日期和结束日期开始,我们只需要时间,不需要日期。 因此,在创建操作的 jam_sessions 控制器中,您需要在创建新实例之前创建正确的日期时间格式。

检查参数以查看您得到了什么并创建新的日期实例,然后您将使用这些实例创建新的即兴会话实例。如果您需要这方面的帮助,请告诉我。

要学习的关键内容:

  • 简单的表单是一个很好的工具,但它也隐藏了表单中的许多重要元素,使它们能够像它们一样传递信息。 始终 检查浏览器中的输入元素。
  • 简单的表单在模型和表单之间建立联系。但是,您可以向表单添加更多字段 - 即使是简单的表单。
  • 哈希的结构由输入字段中的名称属性决定。