在第一次加载操作时,如何将实例变量传递给 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
,我想访问我的 [=20] 中的 @rating
实例变量=] 像这样的文件:
console.log('<%= @rating %>');
现在 returns 和 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>
这是 JS - app/assets/javascripts/profiles.js.erb
- 对应于 HTML:
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-values ,这很简单)。然后在加载 JS 后,这个 noUiSlider
脚本会同时更新 button
标签(又名彩色框)的值和滑块的位置。
它的方式是在这一行:
noUiSlider.create(sliders[i], {
start: 5,
因此,我希望它能从我的 Profiles#Show
控制器中拉取 @rating
,而不是仅仅默认为 5
,所以类似于 start: <%= @rating %>
。这会像我想要的那样自动更新 Slider 和 button
(又名彩色框)。
问题出在第一页加载上,@rating
是 nil/empty。这就是我正在努力解决的问题。
也许我需要发送一个 get
请求,但我不确定如何处理。
编辑 2
郑重声明,AJAX 调用可以正常工作并像我预期的那样更新数据库。当我移动滑块时会发生这种情况,虽然它最初已加载。所以问题只出现在第一页加载上,如果 @rating
.
中有值,我需要更新滑块 & button
你的问题对我来说没有多大意义,因为你说过你正在尝试呈现@rating,但后来你编写了呈现 '<%= @profile.ratings % 的代码>'。此外,您共享的 if 语句表明有时该字段为零。我会看看我能做些什么,但我认为你需要 post 更多信息。
我假设您有一个这样的页面:
<%# profile.html.erb %>
<div id="profiles">
...
<button data-remote="true" >Load ratings</button>
</div>
然后当您单击此按钮时,它会以 :js 格式向您的控制器发送请求,从而加载您的 profile.js.erb。
必须是一个显示任何文本的控制器动作。如果您正在查看来自 rails 的 HTML 页面,则某处有一些控制器操作。您需要将 @rating 实例变量添加到该控制器操作,并在相应的视图中呈现它。
你能post:
- 您访问的是什么路线(url)
- 该路由由哪个控制器渲染
- 该路线呈现的视图(如果有)
如果您需要从 profiles.js.erb
访问该变量,请将其计算放入相应控制器的 profiles
操作中。目前,它是在另一个操作中计算的,当然,在 profiles
.
中不可用
我想通了。
基本上,对我来说最好的方法是为每个 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 中,我所做的只是 select 每个按钮的 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,
瞧......就像变魔术一样!
我有一个 ProfilesController
具有以下内容:
if @profile.ratings
@rating = @profile.ratings.find_by(user: current_user)
end
当页面刚刚加载时,在它甚至将请求发送回控制器之前,为了它 respond_to
,我想访问我的 [=20] 中的 @rating
实例变量=] 像这样的文件:
console.log('<%= @rating %>');
现在 returns 和 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>
这是 JS - app/assets/javascripts/profiles.js.erb
- 对应于 HTML:
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-values ,这很简单)。然后在加载 JS 后,这个 noUiSlider
脚本会同时更新 button
标签(又名彩色框)的值和滑块的位置。
它的方式是在这一行:
noUiSlider.create(sliders[i], {
start: 5,
因此,我希望它能从我的 Profiles#Show
控制器中拉取 @rating
,而不是仅仅默认为 5
,所以类似于 start: <%= @rating %>
。这会像我想要的那样自动更新 Slider 和 button
(又名彩色框)。
问题出在第一页加载上,@rating
是 nil/empty。这就是我正在努力解决的问题。
也许我需要发送一个 get
请求,但我不确定如何处理。
编辑 2
郑重声明,AJAX 调用可以正常工作并像我预期的那样更新数据库。当我移动滑块时会发生这种情况,虽然它最初已加载。所以问题只出现在第一页加载上,如果 @rating
.
button
你的问题对我来说没有多大意义,因为你说过你正在尝试呈现@rating,但后来你编写了呈现 '<%= @profile.ratings % 的代码>'。此外,您共享的 if 语句表明有时该字段为零。我会看看我能做些什么,但我认为你需要 post 更多信息。
我假设您有一个这样的页面:
<%# profile.html.erb %>
<div id="profiles">
...
<button data-remote="true" >Load ratings</button>
</div>
然后当您单击此按钮时,它会以 :js 格式向您的控制器发送请求,从而加载您的 profile.js.erb。
必须是一个显示任何文本的控制器动作。如果您正在查看来自 rails 的 HTML 页面,则某处有一些控制器操作。您需要将 @rating 实例变量添加到该控制器操作,并在相应的视图中呈现它。
你能post:
- 您访问的是什么路线(url)
- 该路由由哪个控制器渲染
- 该路线呈现的视图(如果有)
如果您需要从 profiles.js.erb
访问该变量,请将其计算放入相应控制器的 profiles
操作中。目前,它是在另一个操作中计算的,当然,在 profiles
.
我想通了。
基本上,对我来说最好的方法是为每个 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 中,我所做的只是 select 每个按钮的 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,
瞧......就像变魔术一样!