Rails 在 Bootstrap 4 模态中执行 Javascript

Rails Executing Javascript in Bootstrap 4 modal

我有一个 Rails 5.1 应用程序,我在使用 coffeescript/JS 的表单内使用 Ajax 创建患者记录。使用以下代码可以正常工作:

_form.html.erb

<div class="modal fade patient-modal" tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel">
  <div class="modal-dialog modal-sm" role="document">
    <div class="modal-content">
      <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
        <h4 class="modal-title" id="mySmallModalLabel">Add Patient</h4>
      </div>
      <div class="modal-body">
        <%= form_for Patient.new do |f| %>
          <div class="form-group">
            <%= f.label :first_name %>
            <%= f.text_field :first_name, class: "form-control" %>
            <%= f.label :last_name %>
            <%= f.text_field :last_name, class: "form-control" %>
            <%= f.label :date_of_birth %>
            <%= f.text_field :date_of_birth, class: "form-control", id: 'patient_dob_modal', placeholder: 'yyyy-mm-dd' %>
            <%= f.label :age %>
            <%= f.text_field :age, class: "form-control", id: 'patient_age_modal' %>
            <%= f.label :sex %>
            <%= f.text_field :sex %>
          </div>
          <div class="form-group">
            <%= f.submit class: "btn btn-sm btn-primary" %>
          </div>
        <% end %>
      </div>
    </div>
  </div>
</div>

application.js

$(document).on('turbolinks:load', function() {
  $('#patient_date_of_birth_modal').datepicker({
    format: 'yyyy-mm-dd',
    zIndexOffset: 100000,
    forceParse: false
  });
});

patients.coffee

$(document).on 'turbolinks:load', ->
  selectizeCallback = null
  $('.patient-modal').on 'hide.bs.modal', (e) ->
    if selectizeCallback != null
      selectizeCallback()
      selectizeCallback = null
    $('#new_patient').trigger 'reset'
    $.rails.enableFormElements $('#new_patient')
    return
  $('#new_patient').on 'submit', (e) ->
    e.preventDefault()
    $.ajax
      method: 'POST'
      url: $(this).attr('action')
      data: $(this).serialize()
      success: (response) ->
        selectizeCallback
          value: response.id
          text: response.first_name
        selectizeCallback = null
        $('.patient-modal').modal 'toggle'
        return
    return
  $('.patient').selectize create: (input, callback) ->
    selectizeCallback = callback
    $('.patient-modal').modal()
    $('#patient_first_name').val input
    return
  return

在患者模式中,我使用 bootstrap-datepicker 选择出生日期,然后我写了一些 coffeescript 来计算年龄并自动填充它,如下面的代码所示 patients.coffee

$(document).on 'turbolinks:load', ->
  getAge = (dateString) ->
    today = new Date
    birthDate = new Date(dateString)
    age = today.getFullYear() - birthDate.getFullYear()
    m = today.getMonth() - birthDate.getMonth()
    if m < 0 or m == 0 and today.getDate() < birthDate.getDate()
      age--
    age

  $('#patient_dob_modal').on 'change', ->
    date = $(this).val()
    age = getAge(date)
    $('#patient_age_modal').val age
    return
  return

当我去添加一个病人和模式 fires/shows 时,我可以填写姓名等字段,但是当我使用日期选择器选择出生日期并让 coffeescript 计算年龄时它会出现在字段中,直到我关闭 bootstrap-datepicker,然后它会清除整个模态表单,包括名字和姓氏。

我在检查时没有在控制台中看到任何错误,我确实看到 coffeescript 正在正确执行。

老实说,我不确定这有什么问题,因为我不像 Ruby 那样精通 Javascript/coffeescript。我想知道是不是我做错了什么导致输入字段在我的回调或计算本身的某个地方被清除。

如有任何帮助,我们将不胜感激。我用谷歌搜索并搜索了堆栈,发现了一些关于在模态内执行 JS 的文章,但尚未成功实现这一小块功能。

Update 我禁用了 bootstrap-datepicker 并且只是手动输入出生日期字段和计算的 coffeescript 而没有清除整个表格。所以它看起来像是 bootstrap-datepicker 的一些问题。但是我不确定问题出在哪里。

这是因为日期选择器的模式会在关闭时触发 'hide.bs.modal' 事件,该事件会传播到“.patient-modal”。 Read more

您可以在日期选择器的模态事件上使用event.stopPropagation()

或更明确地 select 在事件处理程序中形成:

$form = $(e.target).find('#new_patient')
$form.trigger 'reset' if $form

在 Stack 之外寻求帮助后,我被指向 https://github.com/uxsolutions/bootstrap-datepicker/issues/50#issuecomment-90855951

所以我将代码更改为:

$(document).on('turbolinks:load', function() {
  $('#patient_date_of_birth_modal').datepicker({
    format: 'yyyy-mm-dd'
  }).on('hide', function(event) {
    event.preventDefault();
    event.stopPropagation();
  });
});

感谢 Jacob M. 多了一双 Google 眼睛。