In views/offers/index:
<%= f.collection_select :catId_get, Category.order(:name), :id, :name,
{ include_blank: true },
{data:{
dynamic_selectable_url: dynamic_select_offers_path(':catId_get'),
dynamic_selectable_target: '#offer_menu_id'
}} %>
<%= f.collection_select :menuName_get, #offer.Category.try(:menus) || [], :id,:menu_item_name, :include_blank => true %>
In views/dynamic_select/offers/index.json.jbuilder:
json.array!(#menus) do |menu|
json.extract! menu, :menu_item_name, :id
end
In controllers/dynamic_select/offers_controller.rb:
module DynamicSelect
class OffersController < ApplicationController
respond_to :json
def index
#menus=Menu.where(:category_id=>params[:catId_get])
respond_with(#menus)
end
end
end
In javascripts/dynamic_selectable.js.coffee:
$.fn.extend
dynamicSelectable: ->
$(#).each (i, el) ->
new DynamicSelectable($(el))
class DynamicSelectable
constructor: ($select) ->
#init($select)
init: ($select) ->
#urlTemplate = $select.data('dynamicSelectableUrl')
#$targetSelect = $($select.data('dynamicSelectableTarget'))
$select.on 'change', =>
#clearTarget()
url = #constructUrl($select.val())
if url
$.getJSON url, (data) =>
$.each data, (index, el) =>
#$targetSelect.append "<option value='#{el.id}'>#{el.name}</option>"
#reinitializeTarget()
else
#reinitializeTarget()
reinitializeTarget: ->
#$targetSelect.trigger("change")
clearTarget: ->
#$targetSelect.html('<option></option>')
constructUrl: (id) ->
if id && id != ''
#urlTemplate.replace(/:.+_id/, id)
In javascripts/init.js.coffee:
window.initApp = ->
$('select[data-dynamic-selectable-url][data-dynamic-selectable-target]').dynamicSelectable()
document.addEventListener 'page:load', initApp
$ initApp
In db/migrate:
create_table :menus do |t|
t.integer 'hotel_id'
t.string 'menu_item_name'
t.integer 'price'
t.string 'item_type'
end
add_index("menus","hotel_id")#index is used to search
end
create_table :categories do |t|
t.string 'name'
t.integer 'hotel_id'
end
add_index("categories","hotel_id")
end
I am new in rails.I want to populate data on the menu_item dropdown when i select a category from its parent dropdown. Please help me, i have been stucked in this for 2 days.
Started GET "/offers/index" for 127.0.0.1 at 2014-10-29 16:25:57 +0530
Processing by OffersController#index as HTML
←[1m←[35mCategory Load (15.6ms)←[0m SELECT `categories`.*
FROM `categories` ORDER BY `categories`.`name` ASC
Rendered
offers/index.html.erb within layouts/application (15.6ms)
Completed
500 Internal Server Error in 32ms
ActionView::Template::Error
(undefined method `Category' for nil:NilClass):
316:
<div>
317: <%= f.label "Select Menu:" %>
318:
319: <%= f.collection_select
:menuName_get, #offer.Category(:menus) || [], :id,:menu_item_name,
:include_blank => true %>
320:
321:
322:
</div>
app/views/offers/index.html.erb:319:in `block in
_app_views_offers_index_html_erb___717332836_61645344'
app/views/offers/index.html.erb:303:in
`_app_views_offers_index_html_erb___717332836_61645344'
You have not set #offer in your controller, something like:
#offer = Offer.first
Then you can use:
#offer.categories
Not #offer.Category note the down case and plural.
Related
This is a continuation from here:
Passing a form as a local to a ajax rendered partial in Rails 5
I've looked all over and can't find a solution that works.
Relevant Controller (profits_controller.rb):
def new_tabs
#market = Market.order('mjsnumber').all.first
#profit = Profit.new
profit_types_markets_products
end
def fetch_market
#market = Market.where(:id => params[:market_id]).first
#form = params["form"]
respond_to do |format|
format.js { render layout: false}
end
end
Relevant View (new_tabs.html.erb):
<%= simple_form_for #profit, :remote => true do |form| %>
<% #markets.each_with_index do |market, i| %>
<%= link_to market.nick, fetch_market_path(:market_id => market.id, :form => form, profit: #profit), :remote=>'true', :id => 'navBtn' + market.id.to_s, :class => 'd-flex flex-grow-1 align-content-center text-center nav-item nav-link ' + active(i).to_s + profit_nav_font_color(market.color).to_s, "data-toggle" => "pill", "roll" => "tab", "style" => "background-color: " + market.color.to_s + ";", remote: true %>
<% end %>
<%= render :partial => 'edit_partial_form', locals: { market: #market, form: form, profit: #profit } %>
Relevant Partial (_edit_partial_form.html.erb):
<%= market.namae %>
<%= form.simple_fields_for :figures, :defaults => { :input_html => { :class => "floatTextBox" }}, remote: true do |figures_form| %>
<%= figures_form.input "[test]" %>
<% end %>
Relevant JS (fetch_market.js.erb):
$("#edit_partial_form").html("<%= escape_javascript(render partial: 'edit_partial_form', locals: { market: #market, form: #form, profit: #profit } ) %>");
Routes:
resources :profits do
resources :markets
resources :products
collection do
get 'new_by_product_type'
get 'new_tabs'
end
end
get "/fetch_market" => 'profits#fetch_market', as: 'fetch_market'
patch 'profits/:id/autosave', as: :autosave_profit, to: 'profits#autosave'
It renders the partial fine, and the links appear to contain the FormBuilder information. When I click the link and add a "puts params" to the controller, it shows the params there. But then gives me an error when loading the partial in console:
ActionView::Template::Error (undefined local variable or method `form' for #<#<Class:0x00007fdbd6453648>:0x00007fdbd68db5f8>
Did you mean? fork):
1: $("#edit_partial_form").html("<%= escape_javascript(render partial: 'edit_partial_form', locals: { market: #market, form: form, profit: #profit } ) %>");
Full Error from local environment when I click on the link for the second market in the list of generated markets:
Processing by ProfitsController#fetch_market as JS
Parameters: {"form"=>"#<SimpleForm::FormBuilder:0x00007fed50dba9f8>", "market_id"=>"2"}
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2 [["id", 1], ["LIMIT", 1]]
↳ /home/mudl/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/activerecord-5.2.3/lib/active_record/log_subscriber.rb:98
Market Load (0.3ms) SELECT "markets".* FROM "markets" WHERE "markets"."id" = $1 ORDER BY "markets"."id" ASC LIMIT $2 [["id", 2], ["LIMIT", 1]]
↳ app/controllers/profits_controller.rb:75
Rendering profits/fetch_market.js.erb
Rendered profits/_edit_partial_form.html.erb (6.5ms)
Rendered profits/fetch_market.js.erb (7.5ms)
Completed 500 Internal Server Error in 12ms (ActiveRecord: 0.6ms)
ActionView::Template::Error (undefined method `simple_fields_for' for "#<SimpleForm::FormBuilder:0x00007fed50dba9f8>":String):
11: MJS 番後: <%= market.mjsnumber %>
12: </span>
13: </div>
14: <%= form.simple_fields_for :figures, :defaults => { :input_html => { :class => "floatTextBox" }}, remote: true do |figures_form| %>
15: <%= figures_form.input "[test]" %>
16: <% end %>
17:
app/views/profits/_edit_partial_form.html.erb:14:in `_app_views_profits__edit_partial_form_html_erb__249336059151108365_70328546926840'
app/views/profits/fetch_market.js.erb:1:in `_app_views_profits_fetch_market_js_erb___2023159631102932010_70328546933900'
app/controllers/profits_controller.rb:78:in `block (2 levels) in fetch_market'
app/controllers/profits_controller.rb:77:in `fetch_market'
(undefined method `simple_fields_for' for "#<SimpleForm::FormBuilder
I am removing the simple_form tag because after a simple test changing the simple_form to a regular form, the error persists with whatever method I call after field_for in the partial.
Thanks in advance.
EDIT:
So I ended up giving up and just using the #profit variable to make a new form in the partial (not ideal, but I'll hack it). Still curious if this is even possible, though, so I'll leave the question open..
So first of all you need to close your form block, then if you couldn`t pass form to partial then try to do this without partial
<%= simple_form_for #profit, remote: true do |form| %>
<% #markets.each_with_index do |market, i| %>
<%= link_to market.nick, fetch_market_path(market_id: market.id, form: form, profit: #profit), id: 'navBtn' + market.id.to_s, class: 'd-flex flex-grow-1 align-content-center text-center nav-item nav-link ' + active(i).to_s + profit_nav_font_color(market.color).to_s, "data-toggle" => "pill", "roll" => "tab", "style" => "background-color: " + market.color.to_s + ";", remote: true %>
<%= market.name %>
<% end %>
<%= form.simple_fields_for :figures, :defaults => { :input_html => { :class => "floatTextBox" }}, remote: true do |figures_form| %>
<%= figures_form.input "[test]" %>
<% end %>
<% end %>
And better to used something_key: "value" instead of this syntax :something_key => "value"
Trying to populate US county from database by selected state from same table. Trying to implement in Rails 5 using this approach here is the link
So far I was able to figured out and see call being made and proper data return in browser console, but dropdown never gets updated. I was trying to messing around with different routes but still no luck. Please, any help would be appreciated.
#routes
get 'account/main/_update_weather', :to => 'client/main#_update_weather', :as
=> :client_location_java
get 'account/_location', :to => 'client/main#_location', :as =>
:client_location
#controller ../controllers/client/main_controller.rb
def _location
#weathers = Weather.all
#profile = Profile.new
#county_name = Weather.where("state_code = ?", "AL")
end
def _update_weather
#county_name = Weather.where("state_code = ?", params[:state_code])
respond_to do |format|
format.js
end
end
#Ajax /assets/javascripts/location.js.coffee
$ ->
$(document).on 'change', '#state_select', (evt) ->
$.ajax 'main/_update_weather',
type: 'GET'
dataType: 'html'
data: {
state_code: $("#state_select option:selected").val()
}
success: (data, textStatus, jqXHR) ->
console.log("Dynamic county select OK!")
error: (jqXHR, textStatus, errorThrown) ->
console.log("AJAX Error: #{textStatus}")
#View for update ../client/main/_update_weather.html.erb
<script>
$("#county_select").empty()
.append("<%=j render(:partial => #county_name) %>")
</script>
<% #county_name.each do |a| %>
<option value="<%= a.id %>"><%= a.county_name %></option>
<% end %>
#view which trying to update ../client/main/_location.html.erb
<% content_for :head do %>
<%= javascript_include_tag 'location', :media => "all", 'data-turbolinks-
track' => true %>
<% end %>
<%= select_tag "state", options_for_select(state_code) {},
{ id: 'state_select' } %>
<%= f.select :weathers_id, options_for_select(#county_name.collect {|a|
[a.county_name, a.id] }, 0), {}, { id: 'county_select' } %>
#Console output
Started GET "/account/main/_update_weather?state_code=CA" for 127.0.0.1 at 2017-07-17 22:49:11 -0700
User Load (0.3ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 10 ORDER BY `users`.`id` ASC LIMIT 1
Processing by Client::MainController#_update_weather as HTML
Parameters: {"state_code"=>"CA"}
Rendering client/main/_update_weather.html.erb
Weather Load (3.4ms) SELECT `weathers`.* FROM `weathers` WHERE (state_code = 'CA')
Rendered collection of client/weathers/_weather.js.erb [56 times] (0.7ms)
Rendered client/main/_update_weather.html.erb (8.0ms)
Completed 200 OK in 17ms (Views: 12.0ms | ActiveRecord: 3.4ms)
When a :user_id is selected how can we show in collection_select that user's challenges? In other words, how can we make #user equal to whatever :user_id was selected in _dueler_fields?
duels/_form.html.erb
<%= simple_form_for(#duel) do |f| %>
<%= f.fields_for :duelers do |dueler| %>
<%= render 'dueler_fields', :f => dueler %>
<% end %>
<%= link_to_add_association f, :duelers do %>
+ Dueler
<% end %>
The loser(s) will <%= f.text_field :consequence, placeholder: "Enter Consequence" %>
<% end %>
duels/_dueler_fields.html.erb
<%= f.select :user_id, User.order(:name).map { |user| [user.full_name, user.id] } %> will
<%= collection_select(:dueler, :challenge_id, #challenges, :id, :full_challenge) %>
duels_controller
def new
#duel = Duel.new
#duel.duelers << Dueler.new(user_id: current_user.id, user_name: current_user.name, user_last_name: current_user.last_name)
#user = # How can we set this to whatever was selected?
#challenges = #user.challenges.order(:created_at)
end
schema.rb
create_table "duelers", force: true do |t| #belongs_to :user & :challenge & :duel
t.integer "user_id"
t.integer "challenge_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "duel_id", null: false
t.boolean "accept"
t.string "user_name"
t.string "user_last_name"
t.string "challenge_name"
end
add_index "duelers", ["duel_id"], name: "index_duelers_on_duel_id", using: :btree
create_table "duels", force: true do |t| #belongs_to :user & :challenge, has_many :duelers
t.text "consequence"
t.text "reward"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
UPDATE
<%= f.select :user_id, User.order(:name).map { |user| [user.full_name, user.id] }, include_blank: true, id: "change-challenge-options" %> will
<%= collection_select(:dueler, :challenge_id, #challenges, :id, :full_challenge, include_blank: true) %>
<script> # Doesn't Work
$( "#change-challenge-options" ).change(function() {
$.ajax({
type: "GET",
url: '<%= user_challenges_path %>',
data: {name: $('#change-challenge-options').prop('value')}
});
});
</script>
Is not necessary go to controller to get user challenges while refreshing the page, the best form to solve it seems to get a function that returns the challenges to a json petition activated from the "change" action of the users_id select
in users_controller:
def challenges
user = User.find_by_id(user_params)
#challenges = user.challenges.order(:created_at)
respond_to |format|
format.js { render json: #challenges.as_json, status: 200 }
end
end
def user_params
params.require(:user).permit(:user_id)
end
in javascript:
$("#user_select").on("change", function(){
// make ajax petition with the user: {user_id: $(this).val()}
// and rescue the results to display wher you want
})
I am implementing 'acts_as_commentable_with_threading' and the js script is not working with the delete or create actions. I have to reload the page for my comments to be added and removed from the page.
I have placed my 'comments.js.coffee' file in the 'app/assets/javascript' directory. It looks like the following:
#comments.js.coffee
jQuery ->
# Create a comment
$(".comment-form")
.on "ajax:beforeSend", (evt, xhr, settings) ->
$(this).find('textarea')
.addClass('uneditable-input')
.attr('disabled', 'disabled');
.on "ajax:success", (evt, data, status, xhr) ->
$(this).find('textarea')
.removeClass('uneditable-input')
.removeAttr('disabled', 'disabled')
.val('');
$(xhr.responseText).hide().insertAfter($(this)).show('slow')
# Delete a comment
$(document)
.on "ajax:beforeSend", ".comment", ->
$(this).fadeTo('fast', 0.5)
.on "ajax:success", ".comment", ->
$(this).hide('fast')
.on "ajax:error", ".comment", ->
$(this).fadeTo('fast', 1)
#In Comments controller file I wrote:
def create
#comment_hash = params[:comment]
#obj = #comment_hash[:commentable_type].constantize.find(#comment_hash[:commentable_id])
# Not implemented: check to see whether the user has permission to create a comment on this object
#comment = Comment.build_from(#obj, current_user, #comment_hash[:body])
if #comment.save
render :partial => "comments/comment", :locals => { :comment => #comment }, :layout => false, :status => :created
else
render :js => "alert('error saving comment');"
end
end
def destroy
#comment = Comment.find(params[:id])
if #comment.destroy
render :json => #comment, :status => :ok
else
render :js => "alert('error deleting comment');"
end
end
end
# In Catalogs controller the code is:
def find_user
#member = Member.find(params[:id])
end
def show_user
find_user
#comments = #member.comment_threads.order('created_at desc')
#new_comment = Comment.build_from(#member, #member.id, "","")
respond_to do |format|
format.html # show.html.erb
format.json { render json: #member }
end
end
#In Comments model, the code include:
acts_as_nested_set :scope => [:commentable_id, :commentable_type]
attr_accessible :commentable, :body,:member_id,:sender
validates :body, :presence => true,:length=>{:maximum=>1000}
validates :member, :presence => true,:length=>{:maximum=>200}
validates :sender,:presence=> true,:length=>{:maximum=>200}
belongs_to :commentable, :polymorphic => true
# NOTE: Comments belong to a user
belongs_to :member
def self.build_from(obj, member_id, comment,sender)
new \
:commentable => obj,
:member_id => member_id,
:body => comment,
:sender => sender
end
...................
# In Member model, I add the following lines:
acts_as_commentable
has_many :comments, :dependent=>:destroy
# In the view file 'show_user', I wrote:
<div class='comments'>
<%= render :partial => 'comments/form', :locals => { :comment => #new_comment }%>
<%= render :partial => 'comments/comment', :collection => #comments, :as => :comment %>
</div>
#Partial 'comments/comment' contains:
<div class='comment'>
<hr>
<b><%= comment.sender %> </b>
<small><%= comment.updated_at%></small> <%= link_to "×",comment_path(comment), :method => :delete, :remote => true, :confirm => "Are you sure you want to remove this comment from # {comment.sender}?", :disable_with => "×", :class => 'close'%>
<p><%= comment.body.html_safe%></p>
</div>
# In _form.html.erb file:
<div class='comment-form'>
<%= simple_form_for comment, :remote => true do |f|%>
<small>Leave your comment </small><br/>
<%= f.input :sender,:as => :hidden,:input_html => { :rows => "2", :value =>"# {current_user.login}"}, :label => false %>
<%= f.input :body, :input_html => { :rows => "2", :class =>"tinymce"}, :label => false %>
<%= f.input :commentable_id, :as => :hidden, :value => comment.commentable_id %>
<%= f.input :commentable_type, :as => :hidden, :value => comment.commentable_type %>
<%= f.button :submit, :class => "btn btn-primary", :disable_with => "Submitting…" %>
<%end%>
</div>
In config/routes file:
resources :comments, :only => [:create, :destroy]
#Here is the output I get if I click on to 'create comments' button:
I hope someone will help me. Thank you.
I **deleted** the jquery.min.js file from my app/assets/javascripts directory
and in my gem file I added the line : gem 'jquery-rails'
and used 'bundle install' to use the gem in my app.
The application.js file has three lines:
//= require jquery
//= require jquery_ujs
//= require_tree .
And in my layout.html.erb file I have the line:
<%= javascript_include_tag 'application' %>
I know it is pretty obvious. Sometimes you need to get things wrong
to understand the obvious better. Now I can add and remove
messages using AJAX and js files.
Thanks for your time.
I am working on rails 3.2 and I am using gems simple_form, cocoon, and rails3-jquery-autocomplete.
I have following models Machine, Part, PartUsage, MachineCosting and PartCosting
Machine and Part models with many-to-many association.
class Machine < ActiveRecord::Base
attr_accessible :name
has_many :part_usages
has_many :parts, :through => :part_usage
end
class Part < ActiveRecord::Base
attr_accessible :name
end
class PartUsage < ActiveRecord::Base
attr_accessible :machine_id,
:part_id
belongs_to :part
belongs_to :machine
end
MachineCosting and PartCosting models with one-to-many association.
class MachineCosting < ActiveRecord::Base
attr_accessible :machine_id,
:total_cost,
:machine_name,
:part_costings_attributes
attr_accessor :machine_name
has_many :part_costings, :dependent => :destroy
accepts_nested_attributes_for :part_costings, :allow_destroy => true
def machine_name
self.machine.try(:name)
end
end
class PartCosting < ActiveRecord::Base
attr_accessible :part_id,
:part_name,
:cost
attr_accessor :part_name
belongs_to :machine_costing
belongs_to :part
def part_name
self.part.try(:name)
end
end
Form for MachineCosting
views/machine_costings/_form.html.erb
<%= simple_form_for(#machine_costing, :html => {:multipart => true}) do |f| %>
<%= f.input :machine_id, :url => autocomplete_machine_id_machines_path,
:as => :autocomplete %>
<!-- HERE, WHENEVER I SELECT A MACHINE, I WANT TO ADD NESTED-FORMS FOR
PARTCOSTINGS CORRESPONDING TO ALL THE PARTS OF THE MACHINE I JUST SELECTED.-->
<%= f.simple_fields_for :part_costings do |part_costing|%>
<%= render 'part_costings/part_costing_fields', :f => part_costing %>
<% end %>
<% end %>
Please suggest how can I populate and dynamically add fixed no of fields for PartCostings using javascript after machine_id is selected in the field.
I would be happy to provide any more information.
Thanks again!!
First, summary of my approach.
In MachineCosting form, use 'rails3-jquery-autopopulate' gem to search for Machines by their name.
Hack MachineController to also send 'Parts info' together with matching machines in json form.
When user selects a machine, use javascript to add nested_forms for PartCostings and partially populate them using data recieved in json form.
Now here is how I have done it (code part).
views/machine_costings/_form.html.erb
<%= simple_form_for(#machine_costing, :html => {:multipart => true}) do |f| %>
<%= f.error_notification %>
<%= f.input :machine_name, :url => autocomplete_machine_name_machines_path,
:as => :autocomplete, :input_html => { :id_element => "#machine_costing_machine_id"} %>
<%= f.association :machine, :as => :hidden %>
<div id='part_costings'>
<%= f.simple_fields_for(:part_costings) do |part_costing|%>
<%= render 'part_costings/part_costing_fields', :f => part_costing %>
<% end %>
<div class="links hidden">
<%= link_to_add_association 'Add part costings', f, :part_costings,
:partial => 'part_costings/part_costing_fields' %>
</div>
</div>
<%= f.button :submit%>
<% end %>
views/part_costings/_part_costing_fields.html.erb
<div class= 'nested-fields'>
<!-- DO NOT CHANGE THE ORDER OF ATTRIBUTES ELSE machine_costing.js WILL FAIL -->
<%= f.input :part_id, :as=> :hidden %>
<%= f.text_field :part_name, :disabled => 'disabled' %>
<%= f.input :cost %>
<%= link_to_remove_association '<i class="icon-remove"></i>'.html_safe, f ,:class =>"part_costing_remove" %>
</div>
controllers/machines_controller.rb
class MachinesController < ApplicationController
# OVER RIDING THIS BY OWN METHOD
# autocomplete :machine, :name, :full=> true, :extra_data => [:machine_id]
def autocomplete_machine_name
respond_to do |format|
format.json {
#machines = Machine.where("name ilike ?", "%#{params[:term]}%")
render json: json_for_autocomplete_machines(#machines)
}
end
end
def json_for_autocomplete_machines(machines)
machines.collect do |machine|
parts = Hash.new
unless machine.part_usages.empty?
machine.part_usages.each do |part_usage|
parts[part_usage.part.id] = part_usage.part.name
end
end
hash = {"id" => machine.id.to_s, "value" => machine.name,
"parts" => parts}
hash
end
end
#
#
#
end
And here is the javascript part.
assest/javascripts/machine_costings.js
$(function() {
// Part Costings
var part_id;
var part_name;
$('#machine_costing_machine_name').bind('railsAutocomplete.select', function(event, data){
console.debug("Machine selected...");
parts = data.item.parts;
console.debug("Removing existing part_costings...");
$('.part_costing_remove').click();
console.debug("Adding part_costings...");
for(var id in parts) {
part_id = id;
part_name = parts[id];
$('.add_fields').click();
}
console.debug("Done adding all part_costings...");
});
$('#part_costings').bind('cocoon:after-insert', function(e, part_costing) {
part_costing[0].getElementsByTagName('input')[0].value = part_id;
part_costing[0].getElementsByTagName('input')[1].value = part_name;
console.debug("Added part_costing...");
});
});
routes.rb
resources :machines do
get :autocomplete_machine_name, :on => :collection
end
The critical points in javascript solution are...
Method "bind('railsAutocomplete.select', function(event, data)" from rail3-jquery-autocomplete gem.
Method "bind('cocoon:after-insert', function(e, part_costing)" from cocoon gem.
That's all.
Please let me know if you have some suggestions. Thanks :)