新手问题 Ajax 里用 append 嵌入一段 Rails 代码

miserytan · 2017年07月13日 · 最后由 zaqmjuop 回复于 2017年07月15日 · 2088 次阅读

我有如下代码,想通过 onchange 事件获取到下拉列表里的值,然后通过 ajax 传递到前端页面中,并想用 append 嵌入一段功能为下拉菜单的 rails 代码到我预留出来的域里。

<div class="object-select col-lg-6" style="float:left" >          
    <%= f.select :software_kingdom, options_for_select(ProductCatalog.where('parent_id =?',1).map{|t|[t.name,t.id]},@app.software_kingdom),
                                                            :include_blank => true, :label => l(:label_product_catalog_software_kingdom) %>
</div>
<div id ="system_domain" class="object-select col-lg-6" >

</div>
$(document).ready(
        function () {
              $("#app_software_kingdom").on("change", function () {
                  var soft_king =$("#app_software_kingdom option:selected");
                  var soft_select = soft_king.val();
          $.ajax({
                          url: "new",
                          data: {soft_selectid: soft_select},
                          success: function(data){
                         $('#app_software_kingdom').val(data.soft_king);
$('#system_domain').append(<%=f.select:system_domain,options_for_select(ProductCatalog.where('parent_id=?',data.soft_king).map{|t[t.name,t.id]},@user2omain),:include_blank => true, :label => l(:label_product_catalog_system_domain) %>");
# 这里忽略(,@user2omain)这个是我没有的,可能是编译的时候出现了问题
                          }
                  });

            });
})
class AppsController < ApplicationController
    def new
        @app = @project.apps.new
        if !params[:soft_selectid].blank?
            @product_ware = ProductCatalog.where(:id => params[:soft_selectid])

            respond_to do |format|

                format.json { render :json => { :software_kingdom => @product_ware.first.id}}
            end
      end
  end
end

但是现在总报这个错误

$('#app_software_kingdom').val(data.soft_king);
$('#system_domain').append(<%=f.select:system_domain,options_for_select(ProductCatalog.where('parent_id=?',data.soft_king).map{|t[t.name,t.id]},@user2omain),:include_blank => true, :label => l(:label_product_catalog_system_domain) %>");

报错的提示很明白 是没有 data 方法,那么就是这一句有问题

ProductCatalog.where('parent_id=?',data.soft_king)

检查下吧。

hging 回复

是的就是这个 data.soft_king 有问题,可是怎么将 js 的变量塞入到 rails 的代码中呢

hging 回复

或者是有什么办法可以解决这个尴尬的情况,因为不单单是 data.soft_king 这个有问题,我将 data.soft_king 换成一个常量比如 2,也是不好用的,所以我断定可能是这里的 append 不可以写 rails 的代码,可能不识别,所以有什么办法可以解决吗

append 里面可以写 rails 代码。<%= f.select xxx %>里面的 f 是一个普通变量,不是实例变量无法进行转换。把f.select xxx在后台拼接而成再传给前端你试试。

hging 回复

我用的这种方法来解析 rails 代码,但是 data.soft_king 还是报错,我应该怎么解析这个 js 变量呢

$('#system_domain').append("<%= escape_javascript(f.select :system_domain, options_for_select(ProductCatalog.where('parent_id =?',data.soft_king).map{|t|[t.name,t.id]},@app.system_domain),:include_blank => true, :label => l(:label_product_catalog_system_domain)) %>");

有没有大神出来帮忙解下围

首先不应该在 js 里写 erb,controller render js 时可以,你的 data.soft_king 是 client 端代码,你却在 server 端使用,肯定会有问题,f.select 这个也不能这么写,你可以在后台把 options 取完以 json 传给前台,或者 render js 的方法也行。

rails 渲染 view 的时候会根据 erb 模板默认规则把代码进行转换,helper 方法和@实例变量会转换成静态值在页面显示,<%= f.select xxx %>会自动变成类似<select><option>的静态 html 代码,调用 ajax 方法的时候 f 这鬼东西根本就不存在了,这是服务器端的东西,用户看到的是客户端的静态页面,所以你可以用<select></select>标签来替代<%= f.select %>。如果是我,我会选择在 view 里面新建一个_select.html.erb,然后把你那段代码放进来,不要<f.select>,直接用select_tag,配合 rails 的 options_for_select,controller 里面 render file: '_select.html.erb',页面直接success(data){ append(data)}

还没学到f.select 所以你的代码不能完全看懂 但是从前端取值在传到后端再 ajax 可以像这样 取完值后用 jq 发 post 请求

var $van = $("#dcpt").text();
$.post("<%= articles_path%>",
    { 
      utf8: "",
      authenticity_token: "<%=form_authenticity_token%>",
      van: $van
    }
);

然后 接收

def create
    @van=params[:van] if params[:van]
    respond_to do |format|
        format.js
    end
end

就可以引用了

$("#fuck").append("<%=@van%>");
zaqmjuop 回复

前后端分离的写法

fan124 回复

你说的对

我有写过这种前后端分离的,当时 append 一个变量到我的前端页面中,这个变量是我用来获取我的 option 的

success: function(data){
             $('#app_software_kingdom').val(data.soft_king);
                $('#system_domain').append("<% @system_dom %>");
             }

然后前台页面里,我直接用这个变量

<%= f.select :system_domain, options_for_select(ProductCatalog.where('parent_id =?', @system_dom.to_i ).map{|t|[t.name,t.id]},@app_project.system_domain),:include_blank => true, :label => l(:label_product_catalog_system_domain)  %>

options_for_select 里面的 option 我都能获取到了,

但是界面上的下拉框还是空的,这是怎么回事

@Rei

append("<% ======@= %>") render plain: params.inspect

zaqmjuop 回复

什么意思?有些新手,还望耐心指教下

miserytan 关闭了讨论。 07月14日 14:48
miserytan 重新开启了讨论。 07月14日 17:15
seven.lee 回复

不懂什么是前后端分离,我以为可以把 ruby 变量插在 js 中是因为有 erb 吧

需要 登录 后方可回复, 如果你还没有账号请 注册新账号