Home > Software design >  How to access user-entered form data from the controller
How to access user-entered form data from the controller

Time:06-08

I have 2 easy-autocomplete form fields that I want to act like nested dropdowns.

They each have listeners that invoke a call to the controller which in turn populates the dropdown. This is working.

When the controller call for the second field is triggered, I need to know how to access the value of the first field. I would think it would be something like form.PayTo.value, or it would show up in the params hash, but I haven't been able to find it by guessing or looking online.

Better yet, is there a way to dump all objects that are available in memory at the time and I can just search for what I need?

Here is the controller code for the 2 user entry fields:

  # search code for the quickentry payto box
  def search
    q = params[:q]
    @transactions = Transaction.select("distinct PayTo").where( "PayTo like ?", "#{q}%")
  end

  # search code for the quickentry Description box
  def DescSearch
    q = params[:q]
    #@transactions = Transaction.select("distinct Description").where( "PayTo = "   :PayTo.to_s   " and Description like ?", "#{q}%")
    @transactions = Transaction.select("distinct Description").where( "PayTo = ? and Description like ?", "#{:PayTo}", "#{q}%")
    puts params
  end

Here is what the console shows:

Started GET "/quickentry/DescSearch.json?q=g" for ::1 at 2022-06-04 10:01:23 -0700
Processing by TransactionsController#DescSearch as JSON
  Parameters: {"q"=>"g"}
{"q"=>"g", "controller"=>"transactions", "action"=>"DescSearch", "format"=>"json"}
  Rendering transactions/DescSearch.json.jbuilder
  Transaction Load (0.3ms)  SELECT distinct Description FROM "transactions" WHERE (PayTo = 'PayTo' and Description like 'g%')
  ↳ app/views/transactions/DescSearch.json.jbuilder:1
  Rendered transactions/DescSearch.json.jbuilder (Duration: 1.7ms | Allocations: 713)
Completed 200 OK in 3ms (Views: 2.1ms | ActiveRecord: 0.3ms | Allocations: 1304)

The query is using the literal 'PayTo' instead of the value from the PayTo field.

Here is quickentry.html.erb

<h1>Quick transaction entry form</h1>
<%= render 'quickentryform', transaction: @transaction %>
<%= link_to 'Back', transactions_path %>

And here is quickentryform.html.erb (with some irrelevant fields snipped out)

<%= form_with(model: transaction) do |form| %>
  <% if transaction.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(transaction.errors.count, "error") %> prohibited this transaction from being saved:</h2>

      <ul>
        <% transaction.errors.each do |error| %>
          <li><%= error.full_message %></li>
        <% end %>
      </ul>
    </div>
  <% end %>

  <div >
    <%= form.label :PayTo %>
    <%= form.search_field :PayTo, placeholder:"Enter name...", "data-behavior":"autocomplete", name:"PayTo"  %>
  </div>

  <div >
    <%= form.label :Description %>
    <%= form.search_field :Description, placeholder:"Enter Description...", name:"Description" %>
  </div>

  <div >
    <%= form.label :Notes %>
    <%= form.text_field :Notes %>
  </div>

  <div >
    <%= form.submit %>
  </div>
<% end %>

Entry in Payto field

Entry in Description field

Here is the code that obtains the value of the first search box and uses it in the query that feeds the second search box.

First, the javascript that obtains the value to be added to the parameters string:

document.addEventListener("turbolinks:load", function() {
  
  $input = $('*[name="Description"]')
  var options = {
    url: function(phrase) {
      
      /* Get the value of the payto box */
      var payto = document.getElementById("transaction_PayTo").value;

      return "/quickentry/DescSearch.json?q="   phrase   "&payto="   payto ;
    },
    getValue: "Description",
  };

  $input.easyAutocomplete(options);
  console.log("Description function end");

});

And the code that uses the passed parameter:

  # search code for the quickentry Description box
  def DescSearch
    q = params[:q]
    payto = params[:payto]
    @transactions = Transaction.select("distinct Description").where( "PayTo = ? and Description like ?", "#{payto}", "#{q}%")
  end

CodePudding user response:

I hope I'm adequately understanding your question. If you're looking to access the params sent to that controller, this should work.

q = params["q"]

The data sent to the controller is JSON and that means you need to access it differently then you would a regular params hash. If you look at the line in the console that says: Parameters: {"q"=>"g"}, whereas if it were a normal params hash it might look something like: Parameters: {:q=>"g"}

Heres some more info on JSON params, hope this helped: https://guides.rubyonrails.org/action_controller_overview.html#json-parameters

CodePudding user response:

I have found a solution for this which involves grabbing the value of the first search box (outside of Ruby) and passing it in as a parameter. I assume that this was what @max was alluding to about separate endpoints, but I don't know what an endpoint is.

I still don't know how to obtain a list of all objects that are in-scope within the controller. So for that reason, I don't know if the form data is in scope to begin with inside the controller.

I put the revised working code above as a reference for anyone who would want to implement nested autocomplete elements.

  • Related