javascript - Need method create and not update when instance actually does exist -
ruby 2.0.0, rails 4.0.3
i have _new partial. but, render instance exists. necessary can pass instance id around through javascript between view , controller, since cannot pass instance itself. call class.first in new method have existing instance use through process.
my problem _new partial submit button recognizes instance exists. causes update instead of create. button literally says update. when pressed, routes update method. not want. want create method, i'll create new instance populated gathered parameters.
what do? wrong in carrying dummy instance start process? if so, correct solution? if otherwise acceptable, how force button create instead of update?
all assistance , comments appreciated.
edit: i've tried variations on button try force trigger new method. continues fire update. last failed effort is:
<button type="submit" formaction="new_admin_car_path" class="btn btn-default btn btn-primary">create car</button>
...end edit...
the form is:
<div class="span8"> <% car_id = @car.id %> <%= simple_form_for [:admin, @car], defaults: {label: false}, html: {id: 'new_admin_car', class: 'form-vertical', method: post}, wrapper: :vertical_form, wrapper_mappings: { check_boxes: :vertical_radio_and_checkboxes, radio_buttons: :vertical_radio_and_checkboxes, file: :vertical_file_input, boolean: :vertical_boolean } |f| %> <%= f.input(:stock_number, {input_html: {form: 'new_admin_car', car: @car, value: nil}, autocomplete: :off, placeholder: 'stock number?'}) %> <%= f.input(:ymm_year_id, {input_html: {form: 'new_admin_car', car_id: car_id, value: nil}, collection: ymmyear.all.order("year desc").collect{|c| [c.year, c.id]}, prompt: "year?"}) %> <%= render partial: "makes", locals: {form: 'new_admin_car', car_id: car_id} %> <%= render partial: "models", locals: {form: 'new_admin_car', car_id: car_id} %> <%= f.association(:color, {input_html: {form: 'new_admin_car', value: nil}, autocomplete: :off, prompt: 'color?'}) %> <div class="col-xs-6 col-sm-3"> <br/> <input type="submit" form="new_admin_car" value="create car" class="btn btn-default btn btn-primary"> <% end %> </div> </div>
makes partial:
<% unless car_id.blank? %> <% car = car.find(car_id) %> <%# car.ymm_make_id = nil %> <%= simple_form_for [:admin, car], defaults: {label: false}, remote: true |f| %> <% makes ||= "" %> <% make = "" %> <% make = car.make_id if car.class == car , car.exists?(car.id) %> <% if !makes.blank? %> <%= f.input :ymm_make_id, {input_html: {form: form, car: car, car_id: car.id, value: make}, collection: makes.collect { |s| [s.make, s.id] }, prompt: "make?"} %> <% else %> <%= f.input :ymm_make_id, {input_html: {form: form, car: car, car_id: car.id, value: make}, collection: [], prompt: "make?"} %> <% end %> <% end %> <% end %>
controller car method new clear nils fields:
def new @car = car.first @car.clear end
rendered form:
javascript form is:
// when #year field changes $("#car_ymm_year_id").change(function () { // make call , replace content // first select identifies has been selected, or fired var year = $('select#car_ymm_year_id :selected').val(); // pull variables input_html tag var form = $('select#car_ymm_year_id').attr("form"); var car_id = $('select#car_ymm_year_id').attr("car_id"); // routes controller action $.post('/admin/cars/make_list/', { form: form, year: year, car_id: car_id }, function (data) { $("#car_ymm_make_id").html(data); }); return false; });
controller method:
def make_list makes = ymmmake.makes(params[:year]) #@car = car.find(params[:car_id]) render partial: "makes", locals: {car_id: params[:car_id], form: params[:form], makes: makes} end
if understand correctly, want achieve following:
display form creating new car models. in form, user enters year; system loads makes year server , presents select drop down user choose make from.
the car model belongs_to ymm_make, include selected ymm_make_id when form submitted.
here how solve this. use standard rails form helpers, have 1 less abstraction layer worry about.
the form (with car.new
):
<%= form_for [:admin, car.new] |f| %> <%= f.text_field :stock_number, autocomplete: "off", placeholder: "stock number?" %> <%= text_field_tag :year_search, nil, placeholder: "year" %> <%= f.select :ymm_make_id %> <!-- skipping models , colors here sake of brevity --> <%= f.submit "create" %> <% end %>
for year search field, use text_field_tag
instead of f.text_field
, because don't want search field value submitted part of car when whole form submitted. leave dropdown field empty - populate through javascript , json.
for list of makes, i'll make resource controller returns json:
class ymmmakescontroller < applicationcontroller respond_to :json def index @makes = ymmmake.makes(params[:year]) respond_with @makes end end
don't forget route.rb entry controller, e.g.
namespace :admin resources :ymm_makes, only: :index end
we'll make <select>
options out of our json in javascript:
$("input[name=year_search]").change(function () { // send request /admin/ymm_makes 'year' parameter // set value of year_search text field $.getjson( "/admin/ymm_makes", {year: $(this).val()}, function(data) { var options_html = []; // iterate on json received back; each entry 1 'ymm_make' // in json form $.each( data, function( index, make ) { // make new <option> tag each make , push options_html array // assume here ymmmake has attribute called 'name' want display options_html.push( "<option value='" + make.id + "'>" + make.name + "</option>" ); }); // put our generated <options> tags <select> tag $('select#car_ymm_make_id').html( options_html.join('') ); }); });
with in place, should have working form creating new cars associated ymmmake model object.
a few observations existing code:
nested forms
<%= simple_form_for [:admin, @car] |f| %> <%= render partial: "makes", locals: {form: 'new_admin_car', car_id: car_id} %> <% end %>
if see correctly, 'makes' partial contains form, creating <form>
nested in <form>
. html does not allow that.
wrong closing tag order
<div class="col-xs-6 col-sm-3"> <br/> <input type="submit" form="new_admin_car" value="create car" class="btn btn-default btn btn-primary"> <% end %> </div>
the closing </div>
must come before <% end %>
. if build invalid html, risk strange visual behaviour , javascript errors.
redundant arguments
<%= simple_form_for [:admin, @car], html: {id: 'new_admin_car', class: 'form-vertical', method: post}, |f| %>
"id" , "method" should default values. leaving them out makes code easier read.
invalid <input>
attributes through input_html
<%= f.input(:stock_number, {input_html: {form: 'new_admin_car', car: @car, value: nil}, autocomplete: :off, placeholder: 'stock number?'}) %>
i'm not familiar simple_form, see, input_html
used add attributes input element. lines above produce text input invalid car
attribute. form
attribute should not necessary anymore remove nested form.
wrong http method
$.post('/admin/cars/make_list/'
you load makes through post ajax request. requests return data, not change anything, more appropriate.
Comments
Post a Comment