How can I organize this logic - javascript

Help me please!!
I want to create editable data table. In top of the table will be a button "Add" that adds row to the table with javascript. And in each row should be butons(links) "Save" and "Delete".
How can i send post request to server?
SORRY FOR MY dullness..
In application.js I have a function like this
function AddElementsToPage(elements) {
/*elements - is array with name elements whose will be add to page*/
this.add_row_to_data_table = function(obj,attributes,selector_table){
last_row_of_table = selector_table.find('tbody tr').last();
var new_row = "<tr><th scope='row'></th>";
if ($.isEmptyObject(last_row_of_table.html()))
{
$.each(attributes, function(index, item){
input_tag = "<input id=\""+obj+"_"+item+"\" name=\""+obj+"["+item+"]\" size=\"10\" type=\"text\" />";
new_row = new_row + "<td>"+input_tag+"</td>";
})
alert(new_row);
selector_table.append(new_row+"</tr>");
}else
{
alert("not empty");
}
}
my controllers action new
def new
#table_row = SchOfWorkInformation.new
respond_to do |format|
format.js do
render :action => 'new'
end
end
end
My new.js file
var obj = new AddElementsToPage();
obj.add_row_to_data_table("sch_of_working",["date","hour"], $('.data_table'))
My index.haml
= link_to content_tag('span', "Add" , :class=>"add"), new_sch_of_work_information_path, :remote => true
%table{:border=>"1", :class=>"data_table", :style=>"width:450px"}
%thead
%th{:style=>"width:5%;"} №
%th{:style=>"width:10%;"} Date
%th{:style=>"width:10%;text-align:center;"} schedule_code
%th{:style=>"width:2%;",:class=>"transperent_right_border"}
%th{:style=>"width:2%;"}
%tbody
%tr
%th{:scope=>"row"}
%td=#sch.date
%td=#sch.schedule_code
%td{:style=>"text-align:center"}= link_tag "save", sch_of_work_informations, #how can send post request in here
%td{:style=>"text-align:center"}

I think this is the kind of answer you would be looking at. Follow the tutorial from railscasts http://railscasts.com/episodes/196-nested-model-form-part-1 nested form and it should help you. Basically you would have an add row button and it would add in javascript the html row, you could even have a remove the row button. Once this is done just press the save button of the form to allow all change to be done.

Related

How to reject Rails update method and trigger JavaScript alert box?

I've update method inside my controller:
def update
if #daily_order.update(daily_order_params.merge({default_order:false}))
respond_to :js
else
render :edit
end
end
I've pax as one of the params inside the daily_order_params and what I'm trying to do now is, I want to show a JS alert when user is trying to update a daily order with zero (0) pax value.
I try to use byebug inside that update method to check params[:pax] but it returns nothing. It's blank.
But the newly updated pax value was saved successfully inside the database.
I try to use before_update inside my model, but I didn't know how to move forward.
before_update :reject_zero_pax_order_update
def reject_zero_pax_order_update
# i got stucked here
end
update.js.erb
console.log("record updated");
What should I do to:
Reject the update if the entered pax is 0
Trigger a JS alert box if the entered pax is 0
Maintain the old pax inside the database
The :pax attribute is inside the :daily_order hash not inside the params hash.
Your params looks something like this:
{ daily_order: { pax: 0 }}
hence you should access it with params[:daily_order][:pax]
Your action should look something like this :
unless params[:daily_order][:pax] == 0
#daily_order.update(daily_params.merge{default_order: false} )
respond_to :js
else
render :edit
end
#update.js.erb
alert('hey, the pax cant be 0 ');
I am assuming, you want the update to take place only when the pax is present else show the alert.
For displaying alert box for pax value can't be equal to 0, you need to add id or class on both update button and pax field. Also you have to add hidden field for getting id of current daily order which is to be updated.
# Add hidden field:
<%= hidden_field_tag "daily_order_id", #daily_order.id %>
# Add id on pax field:
<%= f.text_field :pax, id: 'daily_order_pax' %>
# Add id on update button:
<%= f.submit 'Update', id: 'update_daily_order' %>
Then add following code in js file:-
$(document).on('click', '#update_daily_order', function(event) {
event.preventdefault();
var id = $('#daily_order_id').val();
var pax_value = $('#daily_order_pax').val();
if (pax_value == 0) {
alert("pax value can't be equal to 0");
}else {
$.ajax({
type: 'PUT',
url: '/daily_orders/' + id
data: $('#form_id').serialize();
});
}
});
Above ajax will call only when pax value is not equal to 0

How to pre-populate dynamically added form inputs in Rails

I have an edit.html.erb form for #profile instances. Normally when I load the form, the inputs inside the form are pre-populated with the corresponding attribute of the instance.
e.g. <%= f.text_field :name %> would pre-populate its value from #profile.name.
I would like to add additional fields on runtime using jQuery that allows users to input additional data with additional dynamically added inputs.
i.e. #profile.subjects is a hash containing the subjects and their descriptions (for example it could be {"math" => "I teach calculus", "science" => "I have a physics degree"} )
I retrieve a list of subjects from #profile.subjects, and insert textarea elements into the form for each subject using append() in jQuery.
So if #profile.subjects contains "math" and "science", I would do the following in jQuery:
var subject = *string containing subject*;
parent.append("<textarea id='profile_" + subject + "_desc' name='profile[" + subject + "_desc]'></textarea");
This would imitate creating the fields <%= f.text_area :math_desc %> and <%= f.text_area :science_desc %> to my knowledge.
However, when I pass in the attributes math_desc and science_desc to the instance variable #profile in my controller, the inputs do not pre-populate with their values unlike the static form inputs.
I can access #profile.math_desc and #profile.science_desc in the view, but I would like the inputs to have these values upon the view loading.
I do not know how I would add ruby variables to the append() argument with a variable as the attribute name.
e.g. append("<textarea><%= #profile.send('math_desc') %></textarea>") works, but append("<textarea><%= #profile.send('" + subject + "_desc') %></textarea>") does not.
EDIT 1:
Here is how I assigned additional attributes to my instance:
# NOTE: #profile.subjects contains a string representation of {"Math" => "I teach calculus", "Science" => "I have a physics degree", ...}
def edit
#tutor = current_tutor
#profile = #tutor.profile
# Call method to parse subjects JSON
subject_parsing(#profile)
end
private
# Decode JSON subject field into a hash
def subject_parsing(profile)
unless profile.subjects.blank?
# Decode subjects into a hash
parsed_subjects = ActiveSupport::JSON.decode(profile.subjects)
# Extract subject names from hash into a string separated by commas
profile.subject_names = parsed_subjects.keys.join(', ')
parsed_subjects.each do |subj, desc|
subj = subj.downcase
profile.class_eval do
attr_accessor "#{subj}_desc"
end
profile.send("#{subj}_desc=", desc)
end
end
end
So my workaround was to use the gon gem to send a Rails hash to Javascript then calling the subject descriptions according to the subject_names array.
Added this to the controller (see EDIT 1 code)
# Decode JSON subject field into a hash
def subject_parsing(tutor_profile)
unless tutor_profile.subjects.blank?
# Decode subjects into a hash TODO: change this because it is very slow
gon.subjects = ActiveSupport::JSON.decode(tutor_profile.subjects)
# Extract subject names from hash into a string separated by commas
tutor_profile.subject_names = gon.subjects.keys.join(', ')
end
end
Then ended up with this in the Javascript:
var subjectNamesInput = $('#tutor_profile_subject_names');
// Initialize subject description input boxes
$.each(subjectNamesInput.tagsinput('items'), function(i, subject){
updateSubjectInputs(subject, 'add');
});
function updateSubjectInputs(subject, action){
var parent = $('#subject-description-inputs');
var subject = escape(subject);
var text = "";
if (gon.subjects[subject] != undefined)
text = gon.subjects[subject];
if (action == 'add'){
parent.append("<textarea id='tutor_profile_" + subject.toLowerCase() + "_description' name='tutor_profile[" +
subject.toLowerCase() + "_description]' class='form-control form-text-area' rows='5' placeholder='Add some detail about your experience with " + subject +
" (optional)'>" + text + "</textarea>");
}
else if (action == 'remove'){
$('#tutor_profile_' + subject.toLowerCase() + '_description').remove();
}
}
This was in my view:
<%= f.text_field :subject_names, class: 'form-control tagsinput typeahead', placeholder: 'Subjects you teach' %>
<div id="subject-description-inputs">
</div>

Preview form button in another view

I have a form where user enters some information (text boxes, select box). Inside the form I have a link_to "Preview" where users can preview what they did without saving it. They can preview it in the view of another controller I already have. Any advice on how to do this would be highly appreciated. I tried with js and ajax but it didn't work. I think that the biggest problem is how to pass form params to link_to. I am using Ruby on Rails 3.2, jQuery, JavaScript. Thanks.
Here is some code. In the second controller which checks if it is a preview or not after user clicks Preview:
def index
if !params[:access_token].nil?
#p = "something"
#m.access_token = params[:access_token]
#m.title = params[:title]
#m.body = params[:body]
else
#p = "something else"
end
respond_to do |format|
format.html
format.js
end
end
View (the first one where the form is and preview button) in haml + js, index.html.haml:
= form_for [:controller, #m], action: action, html: { multipart: true, id: "some_id" }, method: :post, remote: true do |f|
- #access_token = generate_access_token
= hidden_field_tag :access_token, #access_token
.input-prepend
%span.add-on Title
= f.text_field :title, id: "title"
.input-prepend
%span.add-on Body
= f.text_area :body, id: "body"
= f.submit t("save"), class: "btn btn-primary"
= link_to "Preview", " ", id: "preview", target: "_blank", class: "btn"
:javascript
$("#preview").click(function(e) {
var title = $("#title").val();
var body = $("#body").val();
var access_token = $("#access_token").val();
$.get('/' + "?access_token=" + access_token + "&title=" + title + "&body=" + body);
});
This .get probably doesn't make sense since it has to open in a new tab and new view.
If you really want to open the preview in a new tab/window, you can just change your last line to:
var url = '/' + "?access_token=" + access_token + "&title=" + title + "&body=" + body;
window.open(url, '_blank');
In your click event you'll want to e.preventDefault(): http://api.jquery.com/event.preventDefault/.
However, as others have noted, you don't really need to hit the server by requesting a new preview page. You might look into using something like Bootstrap's Modal or jQuery UI's Dialog to create a "popup" on the same page. The modal content would be very similar to the preview page you have set up, but with the title and body provided by e.g. var title = $("#title").val();.
var preview= window.open('/',title,'height=500,width=500');
preview.document.write(body); //you can write html code in it, your script vars in it
reference

submit() not working for first time in rails

I am developing an e-commerce site.. and now I got stuck at one point.. When I submit the form ,it doesn't submits on the first click, and i need to give a second click to get it working... I have used anchor tag to submit my data bcoz I want to show the data inside thickbox(iframe)...
View file
<%= form_for :order, :url => populate_orders_url ,:html => { :class => "data# product.id}"},:method => "post",:remote => true do |f| %>
// data
//submit button
orders controller.rb
def populate
#order = current_order(true)
params[:products].each do |product_id,variant_id|
quantity = params[:quantity].to_i if !params[:quantity].is_a?(Hash)
quantity = params[:quantity][variant_id].to_i if params[:quantity].is_a?(Hash)
#order.add_variant(Variant.find(variant_id), quantity, ad_hoc_option_value_ids, product_customizations) if quantity > 0
end if params[:products]
params[:variants].each do |variant_id, quantity|
quantity = quantity.to_i
#order.add_variant(Variant.find(variant_id), quantity, ad_hoc_option_value_ids, product_customizations) if quantity > 0
end if params[:variants]
fire_event('spree.cart.add')
fire_event('spree.order.contents_changed')
redirect_to cart
end
I have seen in firebug and populate method is processed but it not sending data into cart and it showing me empty cart..and cart is processing...
You are sending ajax request,remove :remote => true option from form and check.

Rails Updating a DIV (with reload from model) after a javascript call

OK, I have a page which shows the customer how many Widgets he has. Here's the view (haml):
#available
= "Available widgets: #{#customer.widgets.unused.count()}"
("unused" is a scope in the model showing the available widgets).
When Customer redeems Widgets with a form with ":remote => true", some javascript places a nice DIV on the page with animation and the model is updated by the controller.
Here's the controller:
def redeem
#customer = Customer.find(params[:customer_id])
number = params[:amount].to_i
unless #customer.widgets.unused.empty?
number.times do
#customer = Customer.find(params[:customer_id])
widget = #customer.widgets.unused.first # Grab first unused pass
widget.status = "Redeemed"
widget.save!
end
else
#pay = "true"
# customer.widgets.new
end
# redirect_to #customer
end
And here's the javascript (js.erb):
var number = <%= params[:amount] %>;
<% if #pay.eql? "true" %>
$("#widget-pay").modal('toggle');
<% else %>
while (number > 0) {
var item = $('<div class="widget-show">...</div>');
$('#allwidgets').isotope('insert', item);
number --;
}
<% end %>
My problem is I now want to update the "#available" DIV with the new Widget count. How do I do this?
At worst I could reload the page so the data is pulled from the model again, at best just update the DIV. Neither which I seem to be able to do from the javascript.
You can do something like this:
render :js => "$('#available').append(widget)"
widget.save!

Categories

Resources