ruby-on-rails - Rails、简单形式的 flatpickr 不起作用

标签 ruby-on-rails ruby datepicker simple-form flatpickr

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

到目前为止,我设法让它工作(某种程度),但没有使用 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 文件(仅涉及即兴 session 表的部分):

  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 Controller

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 来完成这项工作。

以下是表格的两个版本中的一些选择。

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

只是简单的形式(可以工作但丑陋): enter image description here

以下是我创建即兴演奏 session 时的日志。第一部分(在 ^[[B^[[B 之前是加载新页面时,表单所在的位置。之后是提交表单后的日志。需要明确的是,我输入的开始日期是 28 日)但它记录了今天的日期(默认购买)

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" = $1 ORDER BY "users"."id" ASC LIMIT $2  [["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" = $1 AND "active_storage_attachments"."record_type" = $2 AND "active_storage_attachments"."name" = $3 LIMIT $4  [["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" = $1 LIMIT $2  [["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" = $1 ORDER BY "users"."id" ASC LIMIT $2  [["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 ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11) 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" = $1 LIMIT $2  [["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" = $1 LIMIT $2  [["id", 22], ["LIMIT", 1]]
  ↳ app/controllers/jam_sessions_controller.rb:40
  Message Load (0.3ms)  SELECT "messages".* FROM "messages" WHERE "messages"."jam_session_id" = $1  [["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" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
  ↳ app/views/jam_sessions/show.html.erb:12
  User Load (0.2ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2  [["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" = $1  [["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" = $1 AND "users"."id" = $2 LIMIT $3  [["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" = $1 AND "participations"."spot_id" IS NULL LIMIT $2  [["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" = $1 AND "users"."id" = $2 LIMIT $3  [["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" = $1 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" = $1 AND "active_storage_attachments"."record_type" = $2 AND "active_storage_attachments"."name" = $3 LIMIT $4  [["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" = $1 LIMIT $2  [["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 是否也可以在小弹出窗口中设置结束时间。我知道它可以在一个弹出窗口中包含开始日期和结束日期以及时间,但我不确定结束时间。因此,您可能想要做的就是在一个字段中选择日期,然后在两个字段中选择您已经准备好的时间。然后在 Controller 中的创建操作中,在创建新的即兴演奏会之前将所有内容放在一起

因此,您需要重命名“starts_at”字段之一。 Simple_form 不会喜欢这样,因为它查看即兴 session 对象,而不仅仅是另一个日期列。所以这里我们需要稍微欺骗一下,只需在 plan html 中或使用 Rails 的帮助程序编写输入字段即可。

您可以只在表单中包含一个输入字段,它将与表单一起提交,但我们希望确保信息在参数中得到正确的位置。 您知道有关 jam session 的所有信息都嵌套在 params 哈希中的“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">

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

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

检查参数以查看您获得的内容并创建新的日期实例,然后使用该实例创建新的 jam session 实例。如果您需要帮助,请告诉我。

要学习的关键内容:

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

关于ruby-on-rails - Rails、简单形式的 flatpickr 不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61081203/

相关文章:

mysql - 如何通过 Rails 迁移减少存在值的 MySQL 列的 varchar?

ruby-on-rails - 这个 C# 到 Ruby 的最干净的端口是什么?

ruby - 使用 Ruby 重定向后如何获取最终 URL?

javascript - 在jsp中,根据具有日期选择器的其他字段隐藏字段

Angularjs 验证 - 无法识别 Bootstrap 日期选择器输入

ruby-on-rails - 表中的 fields_for 生成技术上不正确的 HTML

javascript - history.back(-1) 没有刷新最后一页?

JavaScript 日期和时间选择器

ruby-on-rails - 向模型提供变量字符串以调整 Paperclip Imagemagick 的大小

ruby - 使用 mechanize gem 时出现错误 "getaddrinfo: No such host is known. (Socke tError)"