如何将局部变量添加到 js.erb 文件中的渲染调用
How to add locals to a render call within a js.erb file
我的 js.erb 文件从我的 Rails 5.0.4 应用程序远程调用。
<% if @admin_invitation.present? && @admin_invitation.valid? %>
<%my_view = j (render partial: "shared/invitation_card",:user => @admin_invitation.invited_id, :email => @admin_invitation.invited_email, :type => "admin" ) %>
$(".invites.admins .row").prepend("<%=my_view %>");
<% end %>
App.refresh( "<%= j(render 'shared/alerts') %>" );
当我对部分值进行硬编码时,它按预期工作,但是当我将它们作为本地值从这个 js.erb 文件中输入时,它们不会通过 (nil)。值得注意的是,我从非远程 haml 视图中渲染了部分,它工作得很好。
以下是我尝试过的渲染方式(我知道有些已经过时了,但只是为了检查完整性)
render partial: "shared/invitation_card", :locals=> { :email => "admin@gmail.com", :type => "admin" }
render partial: "shared/invitation_card", object: "admin@gmail.com", as: "email"
render partial: "shared/invitation_card", email: "admin@gmail.com", type:"admin"
render partial: "shared/invitation_card", locals: { email: "admin@gmail.com", type: "admin" }
其他人对 从 rails 5 中的 js.erb 渲染 haml 部分有问题吗?
编辑:
这里是调用上面js.erb的控制器方法。
def create
if params[:invited_status] == "temporary_invitation_user"
result = CreateGroupInvitation.call(invitation_model: GroupFollowInvitation, group_id: params[:group_id], inviter: current_user, invited_email: params[:invited_email], notification: "created_group_follow_email_invitation")
else
result = CreateGroupInvitation.call(invitation_model: GroupFollowInvitation, group_id: params[:group_id], inviter: current_user, invited_id: params[:invited_id] , notification: "created_group_follow_invitation")
end
if result.success?
@invitation = result.invitation
@invited = params[:invited_id] == "null" ? params[:invited_email] : User.find(params[:invited_id])
flash.now[:success] = "Your follow invitation was sent"
else
if result.error_message.present?
flash.now[:info] = result.error_message
else
flash.now[:error] = "An error happend"
end
end
respond_to do |format|
format.js { render layout: false }
end
end
您没有指定调用方式 js.erb
,但我建议的最佳方法如下。
第 1 步 - 构建视图
首先在您的视图中包含 link、带有 remote: true
选项的表单或按钮
例如
<%= form_with(model: @invitation) do |f| %>
...
<% end %>
第 2 步 - 了解路由
route.rb
中的资源路由 :invitations
生成以下路由:
new_invitation GET /invitations/new(.:format) invitations#new
POST /invitations(.:format) invitations#create
并且您的表单 invitations/new.html.erb
在提交时将对 url /invitations
执行 POST
请求。
对 AJAX 的解释
在网络开发中,您可以在服务器和客户端之间执行两种类型的请求,
Synchronous or asynchronous requests。在同步请求中,client/browser 将向后端服务器执行 HTTP request
,后端服务器将以 response
响应。浏览器将停止并开始加载,直到他确实收到完整的响应。
在异步请求中,request and response
周期不包括浏览器停止加载。
您的javascript
文件只是client/browser资产管道中包含的一个文件,它们都是js
、[=26] =]、images
和 fonts
当用户在 http://yourwebsite.xyz
访问您的页面并对 url
执行 get
请求时由浏览器下载.您的服务器执行包含所有这些信息的响应。
因此 js
文件无法找到来自 server
应用程序或 database
中的查询的变量。两个东西是分开的,一个是你的服务器,一个是客户端。
如果你想拥有那个变量并将它添加到client/browser和asynchronously
,那么你需要使用AJAX
.
需要从您的客户端向您的后端服务器执行一个 get
请求,响应将包含 json
格式的 @invitation
变量
第 3 步 - 构建您的控制器
Rails 路由器在 /invitations
接收到 POST
请求,并将请求重定向到控制器 invitations
操作 create
。参数通过ActionController::Parameters
对象传递params
.
服务器 运行 Ruby Rails 以 3 种不同的格式响应请求:
HTML 渲染视图
JS在前端执行脚本代码。 JS 文件 invitations/create.js.erb
已经被客户端通过资产管道下载,这只是一个执行它的命令。
JSON 以 json
格式发送 @invitation
对象,它将在 /invitations.json
可用
# app/controllers/invitations_controller.rb
# ......
def create
@invitation = Invitation.new(params[:invitation])
respond_to do |format|
if @invitation.save
format.html { redirect_to @invitation, notice: 'Invitation was successfully created.' }
format.js
format.json { render json: @invitation, status: :created, location: @invitation }
else
format.html { render action: "new" }
format.json { render json: @invitation.errors, status: :unprocessable_entity }
end
end
end
第 4 步 - 将结果异步附加到页面
在 invitations/create.js.erb
中,您可以包含您的 js 代码,并且可以使用 invitations#create
操作中的实例变量
$("<%= escape_javascript(render @invitation) %>").appendTo("#invitations");
我找到了答案。其实很简单
render partial 'view' locals: {k1: v1, k2:v2} 不会给你一个本地散列。它只是定义局部变量 k1 和 k2 以在您的部分中使用。您不需要从 'locals' 哈希中提取它们。
render 'view' locals: {k1: v1, k2:v2} 确实为您提供了一个包含 k1, v2 的本地散列。在您提取它们之前,它们不会被定义。这种不一致让我失望了。我的代码已准备好让它们位于本地散列中。
我的 js.erb 文件从我的 Rails 5.0.4 应用程序远程调用。
<% if @admin_invitation.present? && @admin_invitation.valid? %>
<%my_view = j (render partial: "shared/invitation_card",:user => @admin_invitation.invited_id, :email => @admin_invitation.invited_email, :type => "admin" ) %>
$(".invites.admins .row").prepend("<%=my_view %>");
<% end %>
App.refresh( "<%= j(render 'shared/alerts') %>" );
当我对部分值进行硬编码时,它按预期工作,但是当我将它们作为本地值从这个 js.erb 文件中输入时,它们不会通过 (nil)。值得注意的是,我从非远程 haml 视图中渲染了部分,它工作得很好。
以下是我尝试过的渲染方式(我知道有些已经过时了,但只是为了检查完整性)
render partial: "shared/invitation_card", :locals=> { :email => "admin@gmail.com", :type => "admin" }
render partial: "shared/invitation_card", object: "admin@gmail.com", as: "email"
render partial: "shared/invitation_card", email: "admin@gmail.com", type:"admin"
render partial: "shared/invitation_card", locals: { email: "admin@gmail.com", type: "admin" }
其他人对 从 rails 5 中的 js.erb 渲染 haml 部分有问题吗?
编辑:
这里是调用上面js.erb的控制器方法。
def create
if params[:invited_status] == "temporary_invitation_user"
result = CreateGroupInvitation.call(invitation_model: GroupFollowInvitation, group_id: params[:group_id], inviter: current_user, invited_email: params[:invited_email], notification: "created_group_follow_email_invitation")
else
result = CreateGroupInvitation.call(invitation_model: GroupFollowInvitation, group_id: params[:group_id], inviter: current_user, invited_id: params[:invited_id] , notification: "created_group_follow_invitation")
end
if result.success?
@invitation = result.invitation
@invited = params[:invited_id] == "null" ? params[:invited_email] : User.find(params[:invited_id])
flash.now[:success] = "Your follow invitation was sent"
else
if result.error_message.present?
flash.now[:info] = result.error_message
else
flash.now[:error] = "An error happend"
end
end
respond_to do |format|
format.js { render layout: false }
end
end
您没有指定调用方式 js.erb
,但我建议的最佳方法如下。
第 1 步 - 构建视图
首先在您的视图中包含 link、带有 remote: true
选项的表单或按钮
例如
<%= form_with(model: @invitation) do |f| %>
...
<% end %>
第 2 步 - 了解路由
route.rb
中的资源路由 :invitations
生成以下路由:
new_invitation GET /invitations/new(.:format) invitations#new
POST /invitations(.:format) invitations#create
并且您的表单 invitations/new.html.erb
在提交时将对 url /invitations
执行 POST
请求。
对 AJAX 的解释
在网络开发中,您可以在服务器和客户端之间执行两种类型的请求,
Synchronous or asynchronous requests。在同步请求中,client/browser 将向后端服务器执行 HTTP request
,后端服务器将以 response
响应。浏览器将停止并开始加载,直到他确实收到完整的响应。
在异步请求中,request and response
周期不包括浏览器停止加载。
您的javascript
文件只是client/browser资产管道中包含的一个文件,它们都是js
、[=26] =]、images
和 fonts
当用户在 http://yourwebsite.xyz
访问您的页面并对 url
执行 get
请求时由浏览器下载.您的服务器执行包含所有这些信息的响应。
因此 js
文件无法找到来自 server
应用程序或 database
中的查询的变量。两个东西是分开的,一个是你的服务器,一个是客户端。
如果你想拥有那个变量并将它添加到client/browser和asynchronously
,那么你需要使用AJAX
.
需要从您的客户端向您的后端服务器执行一个 get
请求,响应将包含 json
格式的 @invitation
变量
第 3 步 - 构建您的控制器
Rails 路由器在 /invitations
接收到 POST
请求,并将请求重定向到控制器 invitations
操作 create
。参数通过ActionController::Parameters
对象传递params
.
服务器 运行 Ruby Rails 以 3 种不同的格式响应请求:
HTML 渲染视图
JS在前端执行脚本代码。 JS 文件 invitations/create.js.erb
已经被客户端通过资产管道下载,这只是一个执行它的命令。
JSON 以 json
格式发送 @invitation
对象,它将在 /invitations.json
# app/controllers/invitations_controller.rb
# ......
def create
@invitation = Invitation.new(params[:invitation])
respond_to do |format|
if @invitation.save
format.html { redirect_to @invitation, notice: 'Invitation was successfully created.' }
format.js
format.json { render json: @invitation, status: :created, location: @invitation }
else
format.html { render action: "new" }
format.json { render json: @invitation.errors, status: :unprocessable_entity }
end
end
end
第 4 步 - 将结果异步附加到页面
在 invitations/create.js.erb
中,您可以包含您的 js 代码,并且可以使用 invitations#create
操作中的实例变量
$("<%= escape_javascript(render @invitation) %>").appendTo("#invitations");
我找到了答案。其实很简单
render partial 'view' locals: {k1: v1, k2:v2} 不会给你一个本地散列。它只是定义局部变量 k1 和 k2 以在您的部分中使用。您不需要从 'locals' 哈希中提取它们。
render 'view' locals: {k1: v1, k2:v2} 确实为您提供了一个包含 k1, v2 的本地散列。在您提取它们之前,它们不会被定义。这种不一致让我失望了。我的代码已准备好让它们位于本地散列中。