通过Rails中的AJAX调用更新实例变量以显示表单

时间:2018-08-26 18:15:05

标签: javascript ruby-on-rails ajax

这就是我想要做的:

  1. 用户粘贴一个URL。
  2. 用户粘贴的输入框具有:onpaste,可触发urlPasted()函数。
  3. urlPasted()函数提交输入框所在的表单,该表单会对名为lookup_profile的自定义函数进行AJAX调用。
  4. 在控制器中,lookup_profile函数执行一些Web请求,然后更新一些实例变量。
  5. 一旦这些变量被更新(大约需要5秒钟),该视图就会具有等待20秒钟的功能,并使用这些实例变量的结果来更新模态上的文本框。

到目前为止,这是我的看法:

  <%= form_tag url_for(:controller => 'users', :action => 'lookup_profile'), id: "profileLookupForm", :method => 'post', :remote => true, :authenticity_token => true do  %>
      <div class="form-group row">
        <div class="col-sm-12">
          <%= text_field_tag "paste_data", nil, onpaste: "profileURLPasted();", class: "form-control"%>
        </div>
      </div>
  <% end %>

  <script type="text/javascript">
      function profileURLPasted() {
        // Once the user pastes data, this is going to submit a POST request to the controller.
        setTimeout(function () { 
            document.getElementById("profileLookupForm").submit();
        }, 100);
        setTimeout(function () { 
            prefillForm();
        }, 20000);
      };

    function prefillForm() {
    // Replace company details.
    $('#companyNameTextBox').val("<%= @company_name %>");
  };
  </script>

这是控制器的外观:

  def lookup_profile
    # bunch of code here
    @company_name = "Random"
  end

现在这是我遇到的问题。当用户粘贴数据时,它会完美地提交到custom_action lookupProfile。但是,在lookupProfile运行其代码之后,Rails不知道之后要做什么。那样的话,我是说它给了我这个错误:

  

Users#lookup_profile缺少此请求格式的模板,并且   变体。 request.formats:[“ text / html”] request.variant:[]

实际上,我实际上在views/users/lookup_profile.js.erb有一个文件。由于某种原因,它正在尝试呈现HTML版本。我不知道为什么。

第二,我尝试将其放在控制器的最后:

    respond_to do |format|  
        format.js { render 'users/lookup_profile'}
    end

但是会导致此错误:

ActionController::UnknownFormat

任何帮助将不胜感激。我只希望自定义函数运行,更新实例变量,然后让我使用该数据更新当前表单。

这是我尝试做的另一件事类似的堆栈溢出参考:Rails submitting a form through ajax and updating the view,但此方法不起作用(出现actioncontroller错误)

*编辑1 *

好,所以我通过将form_tag替换为:

来修复ActionController错误。
<%= form_tag(lookup_profile_users_path(format: :js), method: :post, :authenticity_token => true, id: 'profileLookupForm', remote: true) do %>

但是现在它实际上是将实际的javascript呈现到视图中,我不希望这样。我只希望能够访问在lookup_profile操作中更新的实例变量,而不显示视图。

*编辑2 *

所以我认为我的问题归结为:在表单中放置按钮并从IT提交与提交表单的JavaScript代码不同。如果我能弄清楚这是怎么回事,那么我认为我可能状况很好。

1 个答案:

答案 0 :(得分:0)

您正在那里混合一些东西。首先,我猜想document.getElementById("profileLookupForm").submit()方法会忽略来自rails的submit()指令,而不是执行remote: true,而是应该执行ajax请求。

因此,将提交更改为:

form = getElementById("profileLookupForm");
$.post(form.action, {paste_data: this.value}, 'script')
// form.action is the url, `this` is the input field, 'script' tells rails it should render a js script

这样,请求将异步完成,并且响应不会替换当前页面。

现在,我认为您正在混淆的是@company_name不会随着该ajax请求而改变。呈现表单和其他所有内容时,@company_name被实际值IN THAT MOMENT取代,并且在发布请求后不会更改,因为引用丢失了。所以这行:

$('#companyNameTextBox').val("<%= @company_name %>");

将是

$('#companyNameTextBox').val("");

时间。

您想要的是使用脚本进行响应,该脚本使用您设置为@company_name的值来更新字段(而且,等待任意时间X秒是一种非常糟糕的做法)。

因此,与其回应:

format.js { render 'users/lookup_profile'}

使用您要执行的代码创建视图lookup_profile.js

$('#companyNameTextBox').val("<%= @company_name %>");

在这里,@company_name实际上是您之前告诉您的那些请求所获得的值,脚本即刻生成并作为请求的响应而执行。