Submit value to Rails Model - javascript

if i have this as my form
<%= form_for #rating, :id =>"ratingForm" do |f| %>
<%= f.hidden_field :ratings, :value => '' %>
<%= f.hidden_field :user_id, :value => current_user.id %>
<%= f.hidden_field :recipe_id, :value => #recipe.id %>
<div class="rateit" id="rateit10">
</div>
<%= f.submit "Submit" %>
<% end %>
How do i pass the value of the content within this div
<div class="rateit" id="rateit10">
</div>
if i use this jquery I can get the value of rateit10
$("#rateit10").bind('rated', function() {
$(this).rateit('value');
});
The value derives from clicking upon a set of stars, im trying to implement a rating system in rails using the Rateit plugin

This will pass a hash to your controller method:
function pass_to_controller(){
var rate_value = $("#ratings").value();
var user_id = $("#user_id").value(); /*you already have access to this through current_user.id */
var recipe_id = $("#recipe_id").value();
$.ajax({
type: "Get",
url: "path_to_your_controller_action_here",
timeout: 5000,
data: {rating : rate_value, user : user_id, recipe : recipe_id }
}).done(function(response){//do your response here});
}
You can't directly pass to the model - that circumvents the whole thought process behind MVC. So the best way to do it is to use ajax, pass it to your controller method, then if you need to do something in your database call your model method.
The advantage of using ajax like this is that it won't reload your page when someone rates something.

The easiest way is to trigger an update of your hidden field when the user click on a star, rather than read the value of the stars when the form is submitted.
I should add a onnclick event on the stars to update the hidden field. To do this, add an ID to your hidden field with :id => "my_hidden_field" to name it.
Then, trigger a javascript function when the user click on a star :
$("#second_star").click(function() {
$("my_hidden_field").value = 2;
});

To show text inside div using javascript:
divObj = document.getElementById("rateit10");
if ( divObj ){
if ( divObj.textContent ){ //FF
alert ( divObj.textContent );
}else{ //IE
alert ( divObj.innerText ); //alert ( divObj.innerHTML );
}
}
To show innerdiv inside div using javascript:
myDivObj = document.getElementById("rateit10");
if ( myDivObj ) {
alert ( myDivObj.innerHTML );
}else{
alert ( "Text Found" );
}
To show text inside div using jquery
$(function(){
var txt = $('#rateit10').text();
alert(txt);
};

Related

Rails passing value to hidden field using javascript

I have an array structured as follows:
<% #locations = [['Town 1',2],['Town 2',2]...] %>
That I pass through an options_for_select tag that passes the shows the town name correctly and passes the id when submitted which is great. But, what I want to do is pass the town name (key?) as well to display on the results page as well. I understand the best method is to use a hidden_field_tag with javascript to pass the value through, but all I can pass is the id value, not the town name value.
Form
<%= form_tag(results_path, method: :post) do %>
<%= select_tag :location, options_for_select(#locations) %>
<%= hidden_field_tag(:location_name, value = nil, html_options = {id: 'locationName'}) %>
<%= submit_tag 'Submit' %>
<% end %>
Javascript
$('#location').change(function(){
var input = document.getElementById("location");
var site = document.getElementById("locationName");
site.value = input.value;
})
As you're using jquery:
$('#location').change(function(){
var locationName = $("#location option:selected").text(); # this will return the selected option text e.g. location name
$("#locationName").val(locationName);
})
Hope it works!

Rails: Delete nested attribute while updating entry

I have a form with nested attributes, where you can dynamically add and remove attributes (the form lets you click "add hobby" and "remove hobby" links...a user has hobbies, and when entering his profile he can add one, two, five, or fifty hobbies).
With the help of the nested form gem this works completely fine. However, I also provide the ability to UPDATE a user's profile.
When doing this, a user can click the dynamic "remove" link to take off a hobby. However, this doesn't delete the "hobby" from the database, like I want it to. So I'm trying to write Jquery or Javascript or something that deletes the object from the database, if it exists.
This is what the code looks like:
...
...
<%= f.fields_for :hobbys, :wrapper => false do |hobby| %>
<tr class="fields">
<td> <%= user.text_field :hobby %> </td>
<td> <%= user.link_to_remove "Remove" %> </td>
</tr>
<% end %>
</table>
<p><%= f.link_to_add "Add hobby", :hobbys, :data => { :target => "#hobbys" } %></p>
<script>
$(document).on('nested:fieldRemoved', function(event){
var field = event.field;
/* ??? Delete field somehow ??? */
})
</script>
Is there any way to do this? I really don't know how to go about it....it doesn't seem like Jquery can delete off a database...
UPDATE
here's my best attempt so far...
...
...
<%= f.fields_for :hobbys, :wrapper => false do |hobby| %>
<tr class="fields">
<td> <%= user.text_field :hobby %> </td>
<td> <%= user.link_to_remove "Remove" %> </td>
</tr>
<% end %>
</table>
<p><%= f.link_to_add "Add hobby", :hobbys, :data => { :target => "#hobbys" } %></p>
<script>
$(document).on('nested:fieldRemoved', function(event){
$.get("delete", { id: 2 })
alert( "Deleted: ");
})
</script>
I'm just trying to get this damn thing to work, by hardcoding an id as the argument (since I can't yet easily extract it). But it keeps using the string "delete" as the id of the user.....huh??
Here's the log output:
Started GET "/users/delete?id=2" for 127.0.0.1 at 2016-10-05 08:35:15 -0400
Processing by UsersController#show as */*
Parameters: {"id"=>"delete"}
Current user: anonymous
Completed 404 Not Found in 19.5ms
ActiveRecord::RecordNotFound (Couldn't find User with id=delete):
You could use Jquery to call a function in Ruby to do it for you:
Javascript:
$.get( "delete", { id: id_to_delete } )
.done(function( deleted ) {
alert( "Deleted: " + deleted.id );
});
Route (route.rb):
get 'delete', to: 'application_controller#delete'
Application Controller (application_controller.rb):
def delete
id = params[:id].to_i
to_delete = Hobby.find(id).destroy
render json: {id: id}
end
Add a listener on click of the remove button for each activity and make an ajax request to your backend api which handles it. It will look something like below:
$('.activities').each(function(activity) {
$(activity).click(function(event) {
$.ajax
url: 'activity/:id',
method: delete,
success: function(data) { REMOVE ELEMENT IN HERE }
error: alert('this didnt work');
})
})

jQuery updating rails form partial based on selected item in drop down

In my rails app I have a dropdown menu that a user can select an account to make a payment to:
//_payment.html.erb
<div class="field" id="payment-to-account">
<%= f.label 'Payment To:' %><br>
<%= f.collection_select :to_account_id, #liability_account_payment_list, :id, :account_details, {include_blank: 'Please Select'} %>
</div>
When the user selects a account I render a partial inside of this form based on their selection:
//_payment.html.erb
<%= form_for(#transaction,
as: :transaction,
url:
#transaction.id ? account_transaction_path(#account, #transaction) : account_transactions_path) do |f| %>
...
<% #f = f %>
<div id="to-account-form" style="display:none;"></div>
...
<script>
jQuery(function(){
$("#payment-to-account").change(function() {
var selected_item = $( "#payment-to-account option:selected" ).text();
var selected_item_index = $( "#payment-to-account option:selected" ).index();
//looks for account type in parentheses followed by space moneysign " $"
var regExp = /\(([^)]+)\)\s\$/;
var matches = regExp.exec(selected_item);
// array of account ids in order of list
var payment_account_ids = <%= raw #payment_list_ids %>;
switch (matches[1]) {
case 'Mortgage':
$('#to-account-form').html("<%= j render 'payment_to_mortgage', f: #f %>");
$('#to-account-form').slideDown(350);
break;
case 'PersonalLoan':
case 'CreditCard':
case 'StudentLoan':
case 'OtherLiability':
$('#to-account-form').html("<%= j render 'payment_to_all_other_liabilities', f: #f %>");
$('#to-account-form').slideDown(350);
break;
default:
$('#to-account-form').html("<br>" + "Contact support, an error has occurred");
$('#to-account-form').slideDown(350);
}
});
});
</script>
Right now it renders the correct partial based on the selection, but when that partial loads I need more information from the account model. I created a method called find_pay_to_account that take the input selected account id in the Accounts model that looks for the account based on the id.
When the user selects and account from the drop down, I'd like that method called on the partial that is loaded so I can show the user additional information about the account they are making a payment to before they submit the form. But I don't know how. I wanted to add something like this to my jQuery switch statement.
selected_account_id = payment_account_ids[selected_item_index-1]
#payment_to_account = Account.find_pay_to_account(selected_account_id)
Since rails preloads the partials in the background, making the following change to my partial render in the case statements still wont work:
From this
$('#to-account-form').html("<%= j render 'payment_to_mortgage', f: #f %>");
To this
$('#to-account-form').html("<%= j render 'payment_to_mortgage', f: #f, #payment_to_account: #payment_to_account %>");
I did some searching and found that with AJAX might be able to help:
Pragmatic Studio
Rails Cast
But i'm trying to access the model, not the controller and I'm trying to update a form partial. What is the correct way to do this?
Here are pics that show the user flow. An example of what I'm trying to update can be seen in the last pic. When the mortgage account is selected, it needs to show the minimum payment for the mortgage account. Right now it says zero because the partials rendering with all the information from BOA seed 0214.
If you want to access record information from your model inside of front-end javascript you will indeed want to setup a small api to query the database for that information. In ajax it would be something like this
function processDataFunction(data){
console.log(data)
}
$.ajax({
type: "GET",
dataType: "json",
url: "/some-path/:some_id",
success: processDataFunction(data){}
});
#config/routes.rb
Rails.application.routes.draw do
get "/some-path/:some_id", to: "some_controller#some_view", :defaults => { :format => :json }
end
#app/controllers/some_controller.rb
class SomeController < ApplicationController
def some_view
#some_records = SomeModel.find_by_id(params[:some_id])
respond_to do |format|
format.json { render json: #some_records }
end
end
end
To access the information in the rendered partial without making another controller action, I collected all data I might need in the original action. That way I could get the exact result I was looking for without changing my routes and doing ajax request.
To do this I added methods to the controller new action. You can see from my original question, all accounts I may need information for are in the variable that is in the dropdown menu:
#liability_account_payment_list
This is where the dropdown menu gets its information from
That variable is in the Transaction controller new action. So I created another variable storing an array on the line after the above variable:
#liability_accounts_payment_list_minimum_payments = #liability_account_payment_list.map {|account| account.minimum_payment.to_f + account.minimum_escrow_payment.to_f}
This new variable is an array of all the accounts minimum payments in the order they are listed in the dropdown menu the user will select from.
Then I changed the jQuery on the page to the following
//_payments.html.erb
<script>
jQuery(function(){
$("#payment-to-account").change(function() {
var selected_item = $( "#payment-to-account option:selected" ).text();
var selected_item_index = $( "#payment-to-account option:selected" ).index();
//looks for something in parentheses followed by space moneysign " $"
var regExp = /\(([^)]+)\)\s\$/;
var matches = regExp.exec(selected_item);
// array of minimum payments from accounts in list converted from ruby to js
var min_payments = <%= raw #liability_accounts_payment_list_minimum_payments %>;
// set the js variable to the appropriate minimum payment
var selected_account_min_payment = min_payments[selected_item_index-1];
switch (matches[1]) {
case 'Mortgage':
$('#to-account-form').html("<%= j render 'payment_to_mortgage', f: #f %>");
$("#min-payment-field-hidden").val(selected_account_min_payment);
$("#min-payment-field").html(selected_account_min_payment);
$('#to-account-form').slideDown(350);
break;
case 'PersonalLoan':
case 'CreditCard':
case 'StudentLoan':
case 'OtherLiability':
$('#to-account-form').html("<%= j render 'payment_to_all_other_liabilities', f: #f %>");
$("#min-payment-field-hidden").val(selected_account_min_payment);
$("#min-payment-field").html(selected_account_min_payment);
$('#to-account-form').slideDown(350);
break;
default:
$('#to-account-form').html("<br>" + "Contact support, an error has occurred");
$('#to-account-form').slideDown(350);
}
});
});
</script>
The lines that have min-payment-field-hidden are because setting two different divs with the same id does not work. One div is being used to set hidden_field, the other is showing the user what the value is.
//_payment.html.erb
<-- To make sure the appropriate minimum payment is submitted to controller -->
<%= f.hidden_field :amount, :id => "min-payment-field-hidden" %>
<div>
<%= f.label "Minimum Payment" %>
<div id="min-payment-field"></div>
</div>
If you look at my switch statement, you can see I set the above value with these lines:
$("#min-payment-field-hidden").val(selected_account_min_payment);
$("#min-payment-field").html(selected_account_min_payment);
Now the user can see the minimum payment for the specific account they choose from the dropdown.

Rails, Ajax, and boolean; can't uncheck box

I know there are a bunch of related questions out there, but I can't get mine to work. Here is what I have...
#app/views/tasks/index.html.erb
<%- #tasks.each do |task| %>
<div class="task-wrapper">
<%= check_box_tag 'checked_in', task.id , task.checked_in, :class => "task-check" %>
<%= content_tag :span, task.name %>
</div>
<% end %>
<%= link_to 'New Task', new_task_path %>
<script>
$(".task-check").bind('change', function(){
if (this.checked){
$.ajax({
url: '/tasks/'+this.value+'/toggle',
type: 'POST',
data: {"checked_in": this.checked}
});
}
else {
alert("no");
}
});
</script>
#app/controllers/tasks_controller.rb
...
def toggle
#task = Task.find(params[:id])
if #task.update_attributes(:checked_in => params[:checked_in])
# do I need something here?
else
# do I need something here?
end
end
...
My task model has a 'checked_in' attribute that is boolean.
I got this code from this question...
Rails change boolean value with checkbox and jquery ajax
...and don't quite understand everything that is going on. When I create a new task I can successfully check the box to set my boolean value to true. However, when I uncheck the box I get the js pop-up that says "No", but nothing get set in the DB, and nothing is sent back to server.
Any ideas?
The problem comes from your js code
$(".task-check").bind('change', function(){
if (this.checked){
$.ajax({
url: '/tasks/'+this.value+'/toggle',
type: 'POST',
data: {"checked_in": this.checked}
});
}
else {
alert("no");
}
});
When you check/uncheck the box, the changeevent is triggered, then the function is testing this.checked. It returns false false when the box is unchecked, so you don't go inside the condition but directly in the else, which calls alert.
So you probably want to remove the condition.
Thats how browsers work. They dont send the value of unchecked checkboxes.
Check/Uncheck need to be determined based on the presence of the parameter.
Thanks Antoine. That worked...doing the best I can to learn JS. For posterity here is what worked...
app/views/tasks/index.html.erb
<%- #tasks.each do |task| %>
<div class="task-wrapper">
<%= check_box_tag 'checked_in', task.id , task.checked_in, :class => "task-check" %>
<%= content_tag :span, task.name %>
</div>
<% end %>
<%= link_to 'New Task', new_task_path %>
<script>
$(".task-check").bind('change', function(){
$.ajax({
url: '/tasks/'+this.value+'/toggle',
type: 'POST',
data: {"checked_in": this.checked}
});
});
</script>
...additionally I was getting a template error being thrown in the console, so here is updated controller code.
def toggle
#task = Task.find(params[:id])
#task.update_attributes(:checked_in => params[:checked_in])
render :nothing => true
end

Hiding/Showing Fields Based On Radio Selection With simple_form

I have a form where I need the user to select (with radio buttons) an option that will determine the next form field beneath it. In this case, their post can be a post or a revision of a post. Thus, selecting 'post' will show a title field (to name the post) and selecting 'revision' will show a select list of existing posts to choose from (the title will be inherited).
_form.html.erb
<!--Form inputs-->
<%= f.collection_radio_buttons :is_revision, [[false, 'Post'] ,[true, 'Revision']], :first, :last %>
<%= f.input :revision_id, collection: #originals, :input_html => {:id => 'revision'} %>
<%= f.input :title, :input_html => { :maxlength => '50', :placeholder => 'Title', :id => 'title'} %>
<!--Javascript-->
<script type="text/javascript">
$('input[name="post[is_revision]"]').on("change", function(){
if ( $("#post_is_revision_true").attr("checked")){
$("#title").hide();
$("#revision").show();
}
if ( $("#post_is_revision_false").attr("checked")){
$("#revision").hide();
$("#title").show();
}
});
</script>
I should mention that this works fine when hiding and showing one field, yet when selecting the other radio button nothing changes. I feel the logic is correct (although I'm not the strongest with JS) but I can't seem to get this.
EDIT: I made a few jQuery errors. Also, here is a jsFiddle example
Try this.
$('input[name="post[is_revision"]').change(function() {
var selected = $('input:checked[name="post[is_revision]"]').val();
if(selected == 'revision') {
$('#title').hide();
$('#revision').show();
} else if(selected == 'new_post') {
$('#revision').hide();
$('#title').show();
}
});
Another way to do it, smaller but more confusing:
$('input[name="post[is_revision"]').change(function() {
var is_revision = $('input:checked[name="post[is_revision]"]').val() == "revision";
$('#title').toggle(!is_revision);
$('#revision').toggle(is_revision);
});
If one will always be selected first, you could condense it to this:
$('input[name="post[is_revision"]').change(function() {
$('#title').toggle();
$('#revision').toggle();
});
Or for kicks and giggles and slides:
$('input[name="post[is_revision"]').change(function() {
$('#title').slideToggle();
$('#revision').slideToggle();
});
Comment if you have problems with any.

Categories