【问题标题】:How to call a Rails method from in javascript如何在 javascript 中调用 Rails 方法
【发布时间】:2020-11-17 20:52:20
【问题描述】:

我是 ruby​​ on rails 的新手,我想从 javascript 调用控制器方法

show.html.erb

<label class="switch">
  <%if @vehicle.parking%>
    <input type="checkbox" checked onchange="parkingMode(<%= @vehicle.id %>)">
  <%else%>
    <input type="checkbox" onchange="parkingMode(<%= @vehicle.id %>)">
  <%end%>
  <span></span>
</label>

vehicle_controller.rb

def change_parking
  vehicle = Vehicle.find(params[:vehicle_id])
  if !vehiculo.parking
    vehicle.parking = true
    vehicle.save
  else
    vehicle.parking = false
    vehicle.save
  end
end

vehicle.js

function parkingMode(id){
    console.log(id)
}

【问题讨论】:

    标签: javascript ruby-on-rails ruby


    【解决方案1】:

    您不能直接从视图中调用 Rails 控制器方法,您需要向它发送请求。

    一个很好的方法是使用表单:

    <%= form_for(@vehicle) do |f| %>
      <input name="parked" type="checkbox" checked="<%=@vehicle.parked%>" />
      <input type="submit" />
    <%= end %>
    

    然后您的控制器可以根据是否选中 params[:parked] 来更新车辆并重定向回同一页面

    def change_parked
      @vehicle.update_column(:parked, params[:parked])
      redirect_to vehicle_path(@vehicle.id)
    end
    

    这样做的好处是您不需要任何 JavaScript 来更改车辆。但是,如果您想避免页面刷新...

    要在没有表单的情况下执行此操作,您需要使用 JavaScript 和 Ajax 来 ping 路由到该控制器方法的端点。

    所以,您的 parkingMode JavaScript 方法可能类似于(我在这里使用 jQuery 是为了方便)

    const request = $.post('/vehicles/change_parking')
    request.done((response) => {
      console.log('Do something here')
    })
    

    这将调用您的控制器方法,结果可能返回JSON

    def change_parking
      vehicle = Vehicle.find(params[:vehicle_id])
      if !vehiculo.parking
        vehicle.parking = true
        vehicle.save
      else
        vehicle.parking = false
        vehicle.save
      end
    
      render json: { vehicle: vehicle }, status: 200
    end
    

    然后您需要更改复选框的checked 值:

    const request = $.post('/vehicles/change_parking')
    request.done((response) => {
      $('input[type="checkbox"]).attr('checked', response.responseJSON.vehicle.parked)
    })
    

    有几件事我想解决。

    首先,您在视图中使用if 语句,您可以将其简化为:

    <input type="checkbox" checked="<%= @vehicle.parked %> onchange="parkingMode(<%= @vehicle.id %>)">
    

    这意味着只有在车辆停放时复选框才会显示checked

    其次,在你的change_parking方法中,你只需要调用一次save

    def change_parking
      vehicle = Vehicle.find(params[:vehicle_id])
      if !vehiculo.parking
        vehicle.parking = true
      else
        vehicle.parking = false
      end
    
      vehicle.save
    end
    

    您还可以执行vehicle.parking = !vehicle.parking 之类的操作并删除if 语句。

    【讨论】:

    • 我同意 Carl 的观点,但如果你想走 JavaScript 路线,我建议 Stimulus.JS。一旦掌握了它,它就超级容易使用。
    【解决方案2】:

    可以使用 JS 调用控制器操作。但不是直接。但是,您可以使用 Rails 已经提供的工具来执行此操作。

    首先,我们渲染一个远程复选框:

    check_box_field 'parking_mode_toggle', '1', false, remote: true, data: { url: '/change_parking' }
    

    尽管official document 中没有给出,但如果您阅读Rails UJS code,您会看到UJS 驱动程序会在选中/取消选中复选框时立即发出请求。

    然后,在您的控制器中,您可以:

    def change_parking
      # TODO: Change your database state according to the +params+ received
    
      respond_to do |format|
        format.js { render js: 'parkingMode()' }
      end
    end
    

    【讨论】:

      猜你喜欢
      • 2017-02-22
      • 1970-01-01
      • 2011-04-08
      • 2011-08-21
      • 1970-01-01
      • 2015-08-15
      • 2011-01-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多