Correct object not passing to remote form - javascript

Each user of my site has their own profile page, which contains several items of the same class, call them job_items, which are instance variables of the job class. I'm working on adding edit functionality for each item. In each item I have
<%= link_to "edit", job_item, :onclick => "$('#edit_job').modal();", :remote => "true" %>
Which I want to bring up a modal containing the appropriate form:
...
<div class="modal-body">
<%= semantic_form_for(job_item, :html => { :class => "form-horizontal" }) do |f| %>
...
<% end %>
However, any time I click edit, it doesn't matter which job_item I clicked edit within, the modal appears with a form for the same job_item, namely the first on the page. How can I set which job_item I want to be edited in the form? I'm confused because if I hold my mouse over the edit link, the correct job url appears, however it is not being passed to the javascript modal.

Is it possible you have more than one element with the id "edit_job" in your page? If so, $('#edit_job') will just choose the first one, because it assumes the ids are unique. You could fix this by making sure the ids are unique
:onclick => "$('#edit_job_#{job_item.id}').modal();"
and changing the corresponding element ids accordingly.

Related

Rails5: how to pass element to bs modal with form_tag

I have an index view listing my elements. I want a button link to open a modal view containing a form_tag to pass some text which then get's sent to a third party API, but 'linked' to the element (it's ID) passed.
So far I get the modal showing and it's submitting correctly. But: the modal get's always the first/last element of the index list.
/config/routes.rb
namespace: manage do
resources :elements do
member do
post :my_action
end
end
end
/manage/elements/index.html.haml
#elements.each do |element|
%tr
%td
= link_to 'btn-text', '#myModal', data: { toggle: 'modal', target: '#myModal'}
= render 'manage/elements/element_modal', element: element
/manage/elements/_element_modal.html.haml
#myModal.modal.fade{...}
.modal-dialog
.modal-content
= form_tag path_to_my_action(element), method: :post do
= text_field_tag :text, params[:text]
= submit_tag
I tried different approaches (a modal for each element, data-attributes, AJAX) like found eg here: Bootstrap Modal in Rails Keeps displaying the first record
But actually I can't get any of these working and I don't get why. Can you give me a hint based on above example so I finally get this working? Thanks!

Rails: Dynamic form generation from the database

I've been scratching my brain (kinda painful, wouldn't advise it) trying to figure out a way to pull this off, but I haven't been able to come up with anything that really seems feasible.
The idea is this: I have a page that allows you to create an event. This event could be anything from a wedding to a marathon or fund raiser. Different events need to have a form specific to that event type, e.g. the wedding event needs the name of the bride, groom, address, receptions, etc.
What I'm trying to figure out is how to allow them to select an event type, and then go to localhost:3000/events/create(/:event_type) and have that view load in the correct form fields.
My original thought was to have event types stored in a database with each form stored as JSON, but this just seems more complicated than I'd think necessary.
Any ideas?
Here's routes.rb so far:
get 'my_events/', to: 'events#index', as: :events
get 'events/create', to: 'events#create', as: :new_event
match 'events/new', to: 'events#new', as: :post_new_event, via: :post
get 'event/:slug', to: 'events#show', as: :show_event
root 'static#index'
devise_for :users, :controllers => { :omniauth_callbacks => 'omniauth_callbacks' }
And the events controller:
class EventsController < ApplicationController
def index
#events = Event.all()
end
def create
#event = Event.new()
end
def show
#event = Event.find_by slug: params[:slug]
end
def delete
end
end
You can generate a form with tags to match any number of columns without knowing the column names like this
<%= form_for #event do |f| %>
<% #event.attributes.each do |k,v| %>
<% unless k == 'id' %> #in the case of an edit form, the id should not be changable
<p>
<%= f.label k.to_sym %><br> #get the name of the column, put it into a symbol
<%= f.text_field k.to_sym %> #same as above, will put the matching value in if it exists
</p>
<% end %>
<% end %>
<%= f.submit %>
<% end %>
Though this may not be suited for how your model appears to be set up, a single Event database that can hold any event. This would work better if you had a specific database for each type.
To go in to detail on how I would see this working for you...
Your planned route /events/create/:event_type would work
in your new action in the controller
def new
if params[:event_type] == 'wedding'
#event = Wedding.new #would need to do the same for each event type
end #a model/database for each different type of event
end
However if event is a parent Event database to a child event type, you may be able to make it work, though I'm not familiar enough with relational databases in Ruby on Rails to say how.
This is a fairly common pattern. On your edit/new form(or modal), you need to have a javascript handler on your event_id field. When it changes, you do an ajax request to your server to get the valid event_types for that event so that you may populate the event_types input control.
I would strongly discourage doing any client side storage (hard coding) of the event_types as this design will not allow for easy addition of future events.

How to make a change event only run one time the event is called for a class

I'm designing a multi dynamic select menus, i.e., I have a menu for brands, after the user select the brand, using JavaScript and AJAX, I will search for the models available from that brand and add them to the second select menu. This process repeats again but this time showing the features of the model selected.
To do this, and because I have many different areas that need the same system, I use a class with the same name in every brand select menu and another one to every model select menu.
<div class='brand_select' id='14'>
<%= f.collection_select :brand, Product.find_all_by_area(14, :group => 'brand'), :brand, :brand, :prompt => 'Choose brand' %>
</div>
<div class='model_select'>
<%= f.collection_select :model, Product.find_all_by_area(14), :model, :model, :prompt => 'Choose model' %>
</div>
<div class='brand_select' id='15'>
<%= f.collection_select :brand, Product.find_all_by_area(15, :group => 'brand'), :brand, :brand, :prompt => 'Choose brand' %>
</div>
<div class='model_select'>
<%= f.collection_select :model, Product.find_all_by_area(15), :model, :model, :prompt => 'Choose model' %>
</div>
And the JavaScript:
$('.brand_select').change(function(event) {
// option selected
var brand=$(event.target).find('option:selected').val();
// if none is selected
if (brand == ''){
$(event.target).parent().parent().find('.modelo_select').hide();
$(event.target).parent().parent().find('.caracteristica').hide();
}
else {
$(event.target).parent().parent().find('.modelo_select').show();
// find id to search on the database
var id=$(event.target).parent().attr('id');
// find the target (id of the object)
var target=$(event.target).attr('id');
$.ajax({
type: "POST",
url: "http://"+location.host+"/model/"+brand+"/"+id+"/"+target,
brand: brand,
id: id,
target: target
});
}
});
$('.model_select').change(function(event) {
// find model selected to search on the database
var model=$(event.target).find('option:selected').val();
// find brand selected to search on the database
var brand=$(event.target).parent().parent().find('.marca_select').find('option:selected').val();
// find id to search on the database
var id=$(event.target).parent().parent().find('.marca_select').attr('id');
// find the target (id of the object)
var target=$(event.target).attr('id');
$.ajax({
type: "POST",
url: "http://"+location.host+"/feature/"+brand+"/"+model+"/"+id+"/"+target,
brand: brand,
model: model,
id: id,
target: target
});
});
This code works but it repeats the event change the same number of times as the classes with that name.
What I want to do is for the function to run only one time every time a change event is called for the class.
I don't know if this is possible with class structure that I have or if I have to associate an id or a class with different names for each area to the function.
I don't see why the event should fire twice because all you're doing with $(selector).change is saying that every time a change event fires on something with that selector you want to handle it. I even ran a quick test to be sure and it doesn't fire more than once.
Can you explain a bit better what the symptom actually is? As in, what actually happens twice? Does everything in your event handler happens twice?
I was thinking that your selectors for the actions you perform on the parents might be a bit too lax ($(event.target).parent().parent()) so if you only want to do something on the container where your event was fired that wouldn't be the best way (but then again I don't know what your end purpose is here).
That for your help, I found out that the problem has nothing to do with Javascript but is instead on the Ruby on Rails.
I was adding on application.html.erb other js files and if you have the //= require_tree on the application.js it adds every js file in the tree, so adding js files on application.html.erb will make them repeat and cause strange behaviors like this one.

Rails and jQuery: remove class after click

I vahe view form, this form have:
<%= link_to day, root_path(:day => day), :id => 'link', :class => 'active_link' %>
This link reneder this form with day parameter and items on this form rendered with this parameter. I want that after clicking on this link, after re-rendering form - class 'active_link' removed. How can I make it?
P.S: this is link for item (day item from collection).
This is a view logic problem, not a JavaScript/jQuery problem. You are using a normal link to change the day parameter and re-render the entire page. Based on the only line of code you are showing us, I'm guessing your view loops through a bunch of dates and prints a link out for each one. The problem is, you are assigning the active_link class to all of the day links in your view. "Fixing" this problem with jQuery in the browser after the page loads is the wrong approach; instead fix your view logic to only assign the active_link class to the one correct link (and ditch the non-unique 'link' ids).
In your controller:
#active_day = params[:day]
In your view:
<% days.each do |day| %>
<%= link_to day, root_path(:day => day), :class => (day == #active_day ? 'active_link' : '') %>
<% end %>
Obviously, you'll need to tweak that code some to work in your app - you haven't shown enough code for me to write a working code solution.
You can do:
$('a.active_link').click(function(){
$(this).removeClass('active_link');
});
I'm no expert of ruby, but this works if your link is rendered as
<a id='link' class='active_link'></a>

How to make dynamic dropdown in Rails?

I'm working on a e-commerce project where there will be radio buttons for size selection. I have a dropdown for quantity. I want to make this dropdown dynamic based on stock available for the user selected size. Can anyone tell me how this can be done on Rails? without cluttering my view file with lot of javascript!?
If you are using Rails 3 with prototype (default afaik), you could use the prototype legacy helpers (Link on Github) to add an observer and render a partial view for your dropdown box. You could add an observer like this
<%= observe_field 'element_var_name',
:url => { :action => "another_action_here" },
:update => "div_tag_to_update",
:with => "'selected='+ escape($('element_var_name').value)" %>
Be sure to adjust element_var_name and the action to your situation. div_tag_to_update is the div that will update with the dropdown box. The another_action_here action should render a view like this:
def call_ids_by_type
#element_list = ... # whatever fits for you, like: [[key, value],[key, value]]
render :layout => false
end
In the partial view, you can use the element list to generate the dropdown box:
<%= f.select :var_name, #element_list %>

Categories

Resources