How to use f.select for static hash value? - javascript

How can we use f.select tag for collection of static hash values
class ReceiptPrinter
RECEIPT_PRINTER_TYPES ={
0=> "Normal",
1=> "Dot Matrix",
2=> "Thermal",
}
def initialize(options={})
#receipt_printer_type=options[:receipt_printer_type] || DEFAULT_VALUES[:ReceiptPrinterType]
#receipt_printer_header_height=options[:receipt_printer_header_height]|| DEFAULT_VALUES[:ReceiptPrinterHeaderHeight]
#receipt_printer_header_type=options[:receipt_printer_header_type]|| DEFAULT_VALUES[:ReceiptPrinterHeaderType]
#receipt_printer_template=options[:receipt_printer_template]|| DEFAULT_VALUES[:ReceiptPrinterTemplate]
# define_methods()
end
end
In my view page i used select option
<% form_for #receipt_printer, :url => { :action => "fees_receipt_settings" } do |f| %>
<%= f.select("receipt_printer_template", #settings.map{| item| [item[0],item[1].to_i]},{},{:onchange => "set_template(this.value)"} ) %>
<% end %>
I am getting error wrong number of arguments

You can try with rails's options_for_select,
<%= f.select :receipt_printer_template",options_for_select(#settings.map{ |item| [item[0], item[1]],{},{:onchange => "set_template(this.value)"} ) %>
Here is the reference

ANSWER.
Since #settings is just a simple hash, you don't have to use map. The select form helper should look like:
<%= f.select :receipt_printer_template, #settings, {}, {onchange: "set_template(this.value)"} %>
SUGGESTED REFACTOR
If you are adamant on using map, I would suggest to refactor the code a little to prevent your view from being flooded with app logic, something like:
# app/helpers/receipt_helper.rb
def settings_for_select
#settings.map{ |item| [item[0],item[1].to_i] }
end
# your form view
<%= f.select :receipt_printer_template, settings_for_select, {}, {onchange: "set_template(this.value)"} %>
Should help a little already, also notice the use of the new hash syntax, it provides a cleaner API to work with.

Related

Rails how to render two different modals for destroy action

I want to add confirmation modal when bank manager has to delete bank_employee without clients bank_employee.users = nil. If bank_employee has clients I want to render different modal - destroy_confirmation_modal. How to do it in a proper way? Where should I put if condition?
code snipped of
edit.html.erb
<div class="row">
<div class="col-sm-12 col-md-12 col-xs-12 text-center bank-employee__button-wrapper bank-employees-users-registration__registrations-submit--wrapper">
<%= t('.delete') %>
<%= f.submit t('.submit'), id: "formSubmit", class: "bank-employee__button bank-employee__button-submit"%>
</div>
</div>
<% end %> // this `end` comes from `form_for`
<%= button_to "", bank_employee_path(#bank_employee), method: :delete, form: {id: "bankEmployeeDestroyForm" }, class: "bank-employee__button-destroy" %>
<div class="row">
<div class="col-xs-12 col-sm-12 col-md-12 text-center">
<%= link_to bank_employees_path do %>
<span class="bank-employee__back-button">
<%= image_tag "icon_back.svg", alt: "Back icon", class: ""%>
<%= t('.back') %>
</span>
<% end %>
</div>
</div>
</div>
<%= render "destroy_confirmation_modal" %>
I don't think I should update my controller method but maybe I'm wrong?
controller.rb
def destroy
authorize current_bank_employee
#bank_employee = find_bank_employee(params[:id])
if #bank_employee.users.any? && associated_bank_employees.present?
reassign_users_and_notify_bank_employee
elsif #bank_employee.users.any?
render :edit
else
#bank_employee.destroy
render :destroy_notice, locals: { old_bank_employee: #bank_employee, assigned: false }
end
end
EDIT
my routes.rb
resources :bank_employees, except: [:show], concerns: [:with_datatable] do
member do
get :confirm
end
end
rails routes showed me this path as confirm_bank_employee so I've changed if condition as follow
<% if #bank_employee.users.empty? %>
<%= button_to "", confirm_bank_employee_path(#bank_employee), form: {id: "bankEmployeeDestroyForm" }, class: "bank-employee__button-destroy", remote: true %>
<% else %>
<%= button_to "", bank_employee_path(#bank_employee), method: :delete, form: {id: "bankEmployeeDestroyForm" }, class: "bank-employee__button-destroy" %>
<% end %>
You need a different approach.
<% if #bank_employee.clients.empty? %>
<%= button_to "", bank_employee_confirm_path(#bank_employee), form: {id: "bankEmployeeDestroyForm" }, class: "bank-employee__button-destroy", remote: true %>
<% else %>
<%= button_to "", bank_employee_path(#bank_employee), method: :delete, form: {id: "bankEmployeeDestroyForm" }, class: "bank-employee__button-destroy" %>
<% end %>
now you need two things:
inside routes.rb create a collection for your blank_employee_confirm_path:
whatever setup you have, i assume you have some kind of blank_employees resources path:
resources :blank_employees do
member do
get :confirm
end
end
now, inside your controller you need to add the method confirm:
def confirm
## do whatever you want do to here
render :js
end
this will then head over to confirm.js
create a confirm.js.erb file inside your blank_employees view folder. To confirm this is working, you can add a console.log('it works') in it.
Once you have confirmed that it is working you can add the javascript code to the confirm.js.erb file:
$('#modal-body').html('<%= escape_javascript(render :partial => 'shared/your_confirmation_modal'%>');
with this setup, you need in your edit.html.erb file a <div id="modal-body"></div> that will take the modal. Also notice that in my example the confirmation modal is stored in "views/shared/_your_confirmation_modal.html". Change the path to your setup or create the exact path in order to make this work!
Notice that the "confirm" path is for the blank_employees that have no clients. The button will be only rendered when there is no client. All the other logic you had before for the blank_employees with clients stay the same. You don't need to change there anything. If you had any logic inside there for blank_employees without any clients, move the code to the confirm method.
One more thing: Make sure to add to your destroy method a render :js as well, and inside destroy.js.erb add the same kind of logic like inside confirm.js.erb, beside that you want to render the modal for blank_employees with clients. Your destroy.js.erb file should look something like this:
$('#modal-destroy').html('<%= escape_javascript(render :partial => 'shared/your_destroy_modal'%>');
Very important: Just like with the first modal, add a <div id="modal-destroy"></div> to your edit.html.erb file, otherwise it wont render the modal.
If something is unclear, let me know!
Greetings!

How to avoid sending params of fields deleted using JQuery remove()

In this code I was trying to remove fileds for nested_attributes using ajax :remote => ture to avoid reloading
the whole page in browser. Although fileds in fields_for was removed from DOM and association was removed from database, the fields of the nested attributes
still exist in page source and raise ActiveRecord::RecordNotFound error when trying to send params to update action of parent model
consider the following code:
_artist_form.html.erb
<%= form_for #artist do |f| %>
<%= f.label :name %>
<%= f.text_field :name %><br/>
<%= f.label :style %>
<%= f.text_field :style %><br/>
<%= f.fields_for :songs do |song_builder|%>
<div id = 'song_<%= song_builder.object.id %>_div'>
<%= song_builder.label :title %>
<%= song_builder.text_field :title %><br/>
<%= song_builder.label :lyrics %>
<%= song_builder.text_area :lyrics %><br/>
<%= link_to 'Remove song', delete_song_path(:a_id => #artist.id, :s_id => song_builder.object.id),
:method => :delete , :remote => true %>
</div>
<% end %>
<%= f.submit 'Save' %>
<% end %>
routes.rb
Rails.application.routes.draw do
...
delete '/artists/remove_song', :to => 'artists#delete_song', :as => :delete_song
end
application_controller.rb
class ArtistsController < ApplicationController
def edit
...
end
def update
#artist = Artist.find(params[:id])
if #artist.update(artist_params) #=> error Couldn't find Song with ID=2 for Artist with ID=2
redirect_to artist_path(#artist)
else
flash[:errors] = #artist.errors.full_messages
render :edit
end
end
...
def delete_song
#song_id = params[s_id]
aritst = Artist.find(:params[a_id])
song = artist.songs.find(#song_id)
song.delete
respond_to do |format|
format.js {render 'delete_song.js.erb'}
end
end
end
delete_song.js.erb
$('#song_<%= #song_id %>_div').remove() ;
Error
Couldn't find Song with ID=2 for Artist with ID=2
how to prevent sending params of removed fields by $(...).remove() to update action?
I tried to find a solution for this error. So according to charlietfl comment, I tried to store delete status somewhere locally, then rails can delete association later. So I modified the code as following:
deleting all remote script code including delete_song.js.erb file and delete_song action and delete route. then I allowed marking nested attribute for delete in Artist model file:
accepts_nested_attributes_for :songs, :allow_destroy => true
then adding delete button in _artist_form.html.erb file as following:
<%= button_tag 'x' , :class => 'close_sign', :type => 'button', :onclick => "$('#song_#{song_builder.object.id}_destroy').val('true'); $('#song_#{song_builder.object.id}_div').hide()" %><br/>
and a hidden flied to fields_for as below:
<%= song_builder.hidden_field :_destroy, :id => "song_#{song_builder.object.id}_destroy" %>
and allowing :songs_nested_attributes => [:title, :lyrics, :_destroy] in song_params
once user remove the song field, it will be hidden and marked for destroy later

Sidebar and Main page persistence - Rails

I am using a sidebar that searches and generates a list (within the sidebar) I want the main page to remain unchanged when searching with the sidebar. I believe this requires some JS, but I know nothing about JS.
my navbar is in a div _navbar.html.erb
main page is basically any other page being generated
here is my code: https://github.com/nrkfeller/ratingapplication
You need to use AJAX with rails. Here is how it may work for you:
Add a :remote => true to your form and :'data-update-target' => 'update-container' to specify where you want the search results to go. You might want to avoid using the courses_path, but use form_tag({:controller => courses, :action => 'search'} to directly state where you want the form to be submitted.
<%= form_tag courses_path, method: :get, :remote => true ,class: "navbar- form navbar-right", :'data-update-target' => 'update-container' , role: "search" do %>
<p>
<%= text_field_tag :search, params[:search], class: "form-control" %>
<%= submit_tag "Search",:disable_with => 'Please wait...', name: nil, class: "btn btn-default" %>
</p>
<% end %>
Add this to your sidebar. This is where the partial with the results will come:
<div id="update-container"></div>
Add the javascript`` to put it where it is supposed to be when the request finishes:
<script>
$(function() {
$('form[data-update-target]').on('ajax:success', function(evt, data) {
var target = $(this).data('update-target');
$('#' + target).html(data);
});
});
Add a partial named _search_results.html.erb <- this is where your results go.
<!-- arbitrary code -->
<%= #results.each do |result| %>
<%= result %>
In your controller:
def search
#results= #your search code
render :partial => 'search_results', :content_type => 'text/html'
end
This is will get the functionality you wanted. Beware, this is more of a pesudocode than an exact implementation of what you want to do. You have to fill in the gaps.
I hope I was helpful!

Rails controller and javascript

So I have a form that adds codes to an appointment in rails. There are 2 types of codes, regular codes that get added straight to the apt and wildcard codes that return a list of codes that contain the query (ex. 800* returns anything with 800 in it).
What I need to do is have any regular codes get added to the appointment and return the appointment page if no wildcard codes are selected. If wildcard codes are selected, I need to render a partial that toggleslides out with the search results. If both wildcard and regular codes are selected I need the toggleslide but also have the regular codes updated on the codes table on the page.
The problem I'm having is when just regular codes are selected, the toggleslide is still being called and populated with the appointment page in it.
I have the form that does this set to remote and in a js file I have the ajax response do the toggleslide and populate it with the response. Is there a way to override the ajax response in the controller and just redirect to the appointment page if no wildcard codes are selected?
Or is there a better way to do all this? I tried using a js template but keep getting a 406 error. Or I fix the 406 error by removing any respond_to calls but the toggleslide doesn't get called.
In my js file in my assets.
$(document).ready(function() {
$("#custom_codes_form_1").on("ajax:success", function(e, data, status, xhr) {
$('#my_lists_modal_1').hide();
$('#search_code_results').html(data);
$('html, body').animate({ scrollTop: 0 }, 'slow');
$('#search_code_results').show('blind', {direction: "left"});
});
return false;
});
In my controller. #all_codes is the list of codes returned on a search query.
This is in the add_code_list_codes method:
if !#all_codes.nil?
render :partial => "/encounter/code_search_results", :content_type => 'text/html', :locals => {:codes => #codes, :apt => #apt, :all_codes => #all_codes, :diagnoses_search => true, :type => #type}
else
respond_to do |format|
format.html {redirect_to encounter_show_path(:id => #apt.id)}
end
end
Here's the form.
<%= form_tag({:controller => :encounter, :action => :add_code_list_codes, :id => #apt.id}, :class => 'form-horizontal', :id => "custom_codes_form_#{cl.id}", :remote => true ) do %>
<% CodeType.by_name.all.each do |ct| %>
<h4 class="small_bottom_margin"><%= ct.display_name %></h4>
<div class="control-group">
<% cl.code_list_items.all_by_code_type(ct.id).each do |cc| %>
<%= label_tag :codes, :class => 'checkbox' do %>
<% if cc.code %>
<%= check_box_tag 'codes[]', cc.id %> <strong><%= cc.code.code %></strong> - <%= cc.name_override ? cc.name_override : cc.code.name %>
<% else %>
<%= check_box_tag 'codes[]', cc.id %> <strong><%= cc.search_criteria %></strong> - Wildcard
<% end %>
<% end %>
<% end %>
</div>
<% end %>
<%= submit_tag("Add Selected Charges", :class => 'btn', 'data-disable-with' => "Adding Charges") %>
<% end %>

Rails jQuery pageless problem

Here's the deal,
I'm trying to solve why pageless (infinite scroll) isn't rendering. Using this jQuery Plugin
I have my index page of products with pagination by will_paginate:
def index
#products = Product.find(:all, :order => "position DESC").paginate(:per_page => 3, :page => params[:page])
if request.xhr?
render :partial => 'shared/products', :object => #products
end
end
My index page is calling the products partial
<%= render "shared/products", :object => #products %>
Which in turn is passing the collection onto a singular product partial
<%= render 'shared/product', :collection => #products %>
And calling pageless on it if javascript is enabled (otherwise will_paginate steps in.
<%= pageless(#products.total_pages, products_path) %>
-----------
def pageless(total_pages, url=nil, container=nil)
opts = {
:totalPages => total_pages,
:url => url,
:loaderMsg => 'Loading more results'
}
container && opts[:container] ||= container
javascript_tag("$('#results').pageless(#{opts.to_json});")
end
And finally here is the code for the singular product partial
<% #products.each do |product| %>
<li id="product_<%= product.id %>">
<%= link_to product_image(product), product %>
</li>
<% end %>
Now when I load the page, there are no js errors, I can see the pages getting loaded in my server logs and yet nothing is rendering. Everything seems to work perfectly and yet it doesn't render. Any help would be appreciated.
-Scott
The products weren't being appended to the html. Turned out to be a class/id issue in the html. For anyone trying to debug something similar, see Jonathan Tran's comment on the question.
i changed few things to make it work for rails3:
index.html.erb
<%= render :partial => 'blah/fooPartial' , :locals => { :foo => #foo} %>
<%= will_paginate(#foo) %>
<%= pageless(#foo.total_pages, #path ) %>
My FooController:
def index
#foo = Foo.paginate(:page => params[:page], :per_page => 10).
order("created_at DESC")
respond_to do |format|
format.js
format.html # index.html.erb
end
end
My index.js.erb
$('.row').last().after("<%= escape_javascript( render :partial => 'blah/fooPartial' , :locals => { :foo => #foo}).html_safe %>");
Also Changed the ajax datatype at the very end from 'html' to 'script' in jquery.pageless.js as suggested by ahuang
Hope this helps!!!cheers!!!

Categories

Resources