繁体   English   中英

在第一次执行操作时,如何将实例变量传递给js.erb?

[英]In first load of action, how do I pass instance variables to js.erb?

我有一个具有以下内容的ProfilesController

if @profile.ratings
  @rating = @profile.ratings.find_by(user: current_user)
end

刚加载页面时,甚至还没有将请求发送回控制器之前,要它发送到respond_to ,我@rating这样在我的app/assets/javascripts/profiles.js.erb文件中访问该@rating实例变量:

console.log('<%= @rating %>');

现在它返回nil

我如何在首次加载时访问该profile.js.erb中的@rating实例变量?

编辑1

为了更清楚和更具体的背景,这是正在发生的事情。

我有一些由JS驱动的UISliders ,如下所示:

在此处输入图片说明

生成此代码的HTML是(以及更多类似内容) Profile#Show.html.erb

        <td>
            <p>
              <button type="button" class="btn btn-danger m-r-sm slider-step-value" id="slider-step-value-speed-<%= @profile.slug %>">5</button>
              Speed
            </p>
            <div id="slider-speed" class="slider"></div>
        </td>
        <td>
            <p>
              <button type="button" class="btn btn-primary m-r-sm slider-step-value" id="slider-step-value-tackling-<%= @profile.slug %>">3</button>
              Tackling
            </p>
            <div id="slider-tackling" class="slider"></div>
        </td>

这是与该HTML对应的JS- app/assets/javascripts/profiles.js.erb

  var sliders = $('.slider');
  var buttons = $('.slider-step-value');

  for ( var i = 0; i < sliders.length; i++ ) {
    var button = $(sliders[i]).prev('p').find('button')[0];
    var _slider_type = sliders[i].id.split('-')[1];
    console.log(_slider_type);
    console.log('<%= @rating %>');
    noUiSlider.create(sliders[i], {
      start: 5,
      step: 1,
      behaviour: 'tap',
      connect: [true, false],
      range: {
        'min':  1,
        'max':  10
      }
    });

    attachEvent(sliders[i], button);
  }

  function attachEvent(slider,button){
    slider.noUiSlider.on('update', function( values, handle ) {
      button.innerText = parseInt(values[handle]);
      var _profile_id = button.id.split('-').slice(4).join('-');
      var _rating_type = button.id.split('-')[3]
      var url = "/profiles/" + _profile_id + "/" + _rating_type + "_rating/?" + _rating_type + "=" + button.innerText

      $.ajax({
        type: "PATCH",
        url: url,
        success: function(){
          // console.log(_profile_id + "'s " + _rating_type + " was successfully updated.");
        },
        error: function(){
          // console.log(_profile_id + "'s " + _rating_type + " was NOT successfully updated.");
        }
      })
    });
  }

这是我的ProfilesController#Show动作:

class ProfilesController < ApplicationController
  before_action :set_profile, only: [:show, :edit, :update, :destroy, :invite_user, :speed_rating, :tackling_rating, :dribbling_rating, :passing_rating]
  authorize_resource except: [:dashboard, :speed_rating, :dribbling_rating, :tackling_rating, :passing_rating]
  skip_authorization_check only: [:dashboard, :speed_rating, :dribbling_rating, :tackling_rating, :passing_rating]

def show
    if @profile.ratings
      @rating = @profile.ratings.find_by(user: current_user)
    end
end
end

因此,问题在于,在第一次加载时,发生的事情是HTML加载了在HTML中进行硬编码的默认值(我将最终将其更改为普通的db值,这很简单)。 然后,在加载JS之后,此noUiSlider脚本会同时更新button标记(即彩色框)的值和滑块的位置。

它的操作方式如下:

noUiSlider.create(sliders[i], {
          start: 5,

因此,我不仅希望将其默认设置为5 ,还希望它从我的Profiles#Show控制器中获取@rating ,因此类似start: <%= @rating %> 那样我会自动更新Slider& button (又称彩色框)。

问题出在首页加载上, @rating为空/空。 这就是我正在努力的目标。

也许我需要发送一个get请求,但是我不确定该如何处理。

编辑2

作为记录,AJAX调用可以正常工作并按我期望的方式更新数据库。 但是,当我最初移动滑块之后,才移动滑块。 因此,问题仅在于首页加载,如果@rating有值,我需要更新滑块和button

我想到了。

基本上,对我来说,最好的方法是在初始加载时向从数据库中提取的每个button标记添加一个data属性。

因此,虽然我的旧button标签看起来像这样:

<button type="button" class="btn btn-danger m-r-sm slider-step-value" id="slider-step-value-speed-<%= @profile.slug %>">5</button>

我的新button标签如下所示:

<button type="button" class="btn btn-danger m-r-sm slider-step-value" id="slider-step-value-speed-<%= @profile.slug %>" data-speed-value="<%= speed_rating %>"><%= speed_rating %></button>

其中speed_rating是我的profiles_helper.rb中定义的帮助方法,如下所示:

  def speed_rating
    if @rating.speed
      @rating.speed
    else
      "5"
    end
  end

然后,在我的JS中,我所做的就是为每个按钮选择该data属性,如下所示:

var button = $(sliders[i]).prev('p').find('button')[0];
var _slider_type = sliders[i].id.split('-')[1];
var _original_value = $('button#' + button.id).data(_slider_type + "-value");

唯一的新行是:

var _original_value = $('button#' + button.id).data(_slider_type + "-value");

然后我将其添加到我的noUiSlider.create调用中,所以现在看起来像这样:

noUiSlider.create(sliders[i], {
  start: _original_value,

与之相反,最初看起来像这样:

noUiSlider.create(sliders[i], {
   start: 5,

瞧...。就像魔术一样!

您的问题对我来说没有多大意义,因为您已经说过要渲染@rating,但是随后您编写了渲染'<%= @ profile.ratings%>'的代码。 另外,您共享的if语句建议有时该字段为nil。 我将尽我所能,但我认为您需要发布更多信息。

我想象你有一个这样的页面:

<%# profile.html.erb %>
<div id="profiles">
  ...
  <button data-remote="true" >Load ratings</button>
</div>

然后单击此按钮时,它将以:js格式向您的控制器发送请求,该请求将加载profile.js.erb。

必须有一个显示任何文本的控制器动作。 如果您正在从Rails中查看HTML页面,那么某个地方会有一些控制器动作。 您需要将@rating实例变量添加到该控制器操作,并在相应的视图中呈现它。

您可以发帖:

  1. 您正在访问的路线(网址)
  2. 该路线由哪个控制器呈现
  3. 该路线由哪个视图呈现(如果有)

如果需要从profiles.js.erb访问该变量,请将其计算结果放入相应控制器的profiles操作中。 目前,它是通过其他操作计算得出的,自然也不会在profiles

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM