Rails and jQuery: How to select input from a specific form - javascript

I have a rails app with a job model, and on the index page, each job has a form. I need to be able to access the specific form everytime the submit button is selected, so I can take the input for the form and perform some jQuery validation with it.
Here is some of my index.html page.
<ul>
<% #unassigned.each do |job| %>
<li>
<div class="row new-message">
<div class="small-12 columns">
<%= form_for #message do |f| %>
<%= f.text_area :body, {placeholder: 'enter a new message...'} %>
<%= f.hidden_field :job_id, value: job.id %>
<%= f.submit 'send message', class: 'button small radius secondary message-button', "data-job-id" => job.id %>
<div id="message<%= i %>-validation-errors"> </div>
<% end %>
</div>
</div>
<li>
<% end %>
<ul>
And here is the javascript/jQuery where I try to select the input from a specific form
var messages;
messages = function() {
$('.message-button').click(function(e) {
var id = $(this).data('job-id');
messageValidation(e, id);
});
function messageValidation(e, id) {
var body = $('#message_body').val();
var div = '#message' + id + '-validation-errors';
if(body == "") {
$(div).html('');
e.preventDefault();
$(div).html('<small style="color:red"> Message body empty </small>');
}
};
};
$(document).ready(messages);
The index page will have a form for each job, and I want there to be front end validation that checks when the button is submitted, that the body field is not empty. It works fine the first time, but after going back to the index page, and trying to validate a second time var body = $('#message_body').val(); always seems to be empty, whether I put anything in the body or not. I believe it has something to do with the fact that since there is the same form for each job, there are multiple #message_body id's on the same page, and it is selecting the incorrect one. I am new to jQuery and javascript can someone please help me

You cannot have multiple elements with same id on a page. What you can do is add a class identifier to those elements.
In your case, simple set class="message_body" to your elements and select them as shown below:
$('.message-button').click(function(e) {
var id = $(this).data('job-id');
var body = $(this).parent().find('.message_body').val();
messageValidation(e, body, id);
});

To solve this problem I needed to select the child of the form and find the message_body through that.
messages = function() {
$('.new_message').submit(function(e) {
//var id = $(this).data('job-id');
var $this = $(this);
var body = $this.children('#message_body').val();
var id = $this.children('#message_job_id').val();
messageValidation(e, body, id);
});
function messageValidation(e, body, id) {
var div = '#message' + id + '-validation-errors';
if(body == "") {
$(div).html('');
e.preventDefault();
$(div).html('<small style="color:red"> Message body empty </small>');
}
};
};

Related

I want to see the textarea in Rails JUST as javascript does

I have a form that allows a user to submit HTML, and I just want to make a few changes to the text (e.g. replace a company name with one in Active Record), and then replace the HTML inside of a textarea. However, it's not playing too well. For whatever reason, trying to replace the textarea with the contents that were submitted in its POST request does not work. Nothing happens.
Here's my view form:
<div class="modal-body">
<div class="form-group row">
<div class="col-sm-12">
<%= form_tag(convert_email_template_path(format: :js), method: :post, :authenticity_token => true, id: 'importEmailForm', remote: true) do %>
<%= text_area_tag 'import_email', nil, rows: 10, placeholder: "Paste the headers of your email here.", class: "form-control" %>
<% end %>
</div>
</div>
</div>
<div class="modal-footer">
<%= link_to '<i class="fa fa-download"></i> Import'.html_safe, '#', onclick: "importEmail();", class: "btn btn-success btn-sm" %>
</div>
So basically, importEmail() looks like this:
function importEmail() {
setTimeout(function () {
$.ajax({
type: 'POST',
url: $("#importEmailForm").attr("action"),
data: $("#importEmailForm").serialize(),
});
}, 100)
};
which basically submits the form in the view. I need to capture this POST data, make a change or two, and then proceed with replacing textarea with the modified contents.
Now if I do this in plain javascript, this works fine:
#views/templates/convert_email.js.erb
var sourceBody = $('#import_email').val();
var start_position = sourceBody.indexOf("<html>");
var stop_position = sourceBody.indexOf("</html>");
var html = sourceBody.substring(start_position, stop_position);
var fixed_html = html.replace(/(=\n)/g, '');
// Grab body.
var iframe = document.getElementsByClassName("fr-iframe")[0]
var innerDoc = (iframe.contentDocument) ? iframe.contentDocument : iframe.contentWindow.document;
// get the element in question
const input = innerDoc.getElementsByTagName("body")[0];
// Before pasting data, let's make sure the code view is turned OFF.
if ($('textarea').froalaEditor('codeView.isActive') == true) {
$('textarea').froalaEditor('codeView.toggle');
}
// dispatch keyboard events
input.innerHTML = fixed_html;
// Close modal.
$('#Modal').modal('toggle')
But if capture this POST data with params[:import_email], and do something like this:
#controllers/templates.rb
body = params[:import_email]
#body = body.gsub("=\n", "")
and pass that to the javascript view.
#views/templates/convert_email.js.erb
// Grab body.
var iframe = document.getElementsByClassName("fr-iframe")[0]
var innerDoc = (iframe.contentDocument) ? iframe.contentDocument : iframe.contentWindow.document;
// get the element in question
const input = innerDoc.getElementsByTagName("body")[0];
// log codeview status
var codeView = 0
// Before pasting data, let's make sure the code view is turned OFF.
if ($('textarea').froalaEditor('codeView.isActive') == false) {
codeView = 0;
$('textarea').froalaEditor('codeView.toggle');
} else {
codeView = 1;
}
function
// dispatch keyboard events
input.innerHTML = "<%= #body %>";
resizeFroala();
// Close modal.
$('#Modal').modal('toggle')
Nothing happens. Perhaps there's a way to treat a textarea as source code or something?
Using the first method (javascript only), this is what fixed_html looks like in the console:
I want to get #body to look like this, but in order for me to do that, I have to do this in the controller:
body = params[:import_email]
#body = body.gsub("=\r", "\r").gsub("\n", "").gsub("\r", "").gsub("\t", "")
but trying to write this to the console looks like this:
Sorry for any confusion. Hope this makes sense. I just basically want to do what works flawlessly in Javascript, but in Rails.
Think I finally figured it out. Didn't realize rails used <%== %> in addition to <%= %>
Changed my code to:
input.innerHTML = "<%== j #body %>";
and this did the trick. Wow.

Params is not passing for the second time form the controller to view in Rails

I am building "comments" model for "post". Single profile will be having two tabs. Each tabs will be having ten posts. So , I am calling post using UUID (Unique Id).On first time, comments get posted and index page for comments is shown. But for the next time, without refreshing the page, comments getting posted via ajax but index page is not shown.
My comments section in Posts/index is
<% #posts.each do |p| %>
<% a = SecureRandom.uuid %>
<i class="fa fa-comment post-comment coms" data-a="<%= a %>"
style="cursor:pointer;" data-postid="<%= p.id %>" data-class="<%=
p.class.to_s %>"></i>
<%= p.comments.count %>
<div id="comments_post_<%= a %>"></div>
<% end %>
<script type="text/javascript">
var comments_url = "<%= comments_path %>";
$(".coms").click(function(e){
var p_a = $(this).data("a");
var c_type = $(this).data("class");
var id = $(this).data("postid");
e.stopImmediatePropagation()
$("#comments_post_"+p_a).toggle(
function(){($("#comments_post_"+p_a).load(comments_url+"?c_type="+c_type+"&id="+id+"&p_uuid="+p_a));}
);
});
In jquery, I am passing the UUID as p_uuid to the comments index action.
comments/controller index action is
def index
#holder = params[:c_type].constantize.find(params[:id])
#c_uuid = params[:p_uuid] unless params[:p_uuid].blank?
render partial: "comments/index"
end
I am assigning params[:p_uuid] to the #c_uuid.
comments/index is
<div class="row postComment"">
<div class="col-md-2 col-sm-2"><%= image_tag(current_user.image_url[:url], :class => "commentpic") rescue "" %></div>
<div class="col-md-10 col-sm-10">
<textarea id="commentText" class="annotation send-comm form-control" placeholder="Add a comment"
data-c-id="<%= #holder.id %>" data-c-type="<%= #holder.class.to_s %>" data-uuid="<%= #c_uuid %>"></textarea>
<div class="hint">Press Shift + Enter for a new Line</div>
</div>
</div>
<script>
var comments_url = "<%= comments_path %>";
function postComment(context){
var comment = $(context).val();
var c_type = $(context).data("c-type");
var c_id = $(context).data("c-id");
var uuid=$(context).data("uuid");
var commParams = {
commentable_type: c_type,
commentable_id: c_id,
body: comment
}
postData( comments_url, { comment: commParams }, function(data){
$("#comments_"+"<%= #holder.class.to_s.downcase %>_<%= #c_uuid %>").load(comments_url+"?c_type=<%= #holder.class.to_s %>&id="+"<%= #holder.id %>");
});
</script>
Actual problem is, I am posting first comment, its getting posted and index page is shown. But , for the second time the comments getting saved in database but its not getting shown on index or index not getting updated.
I checked with the console.log, #c_uuid from comments controller in passed to the comments/index for the first time, but its not available for the second time. Means, #c_uuid is nil for the second time.Please, help me in this.

get input fields twice, one hidden

I am building a simple web application in RoR (ruby 2.2.2). So I build a user control page where I can invite different users. Therefore I build a input field and a 'add user' button. When the add user button is clicked, the value of the input field is copied in a extra created input field beneath (via javascript). So everything worked fine, since today. Now everytime when I open the user control page, next to my wanted input field, is a extra input field which is hidden & has the same id as my wanted input field. I really no not know what I did and how I get rid of this field.
So here is my rails code:
<div class='col-md-12'>
<%= form_for #project, html: { class: 'form-horizontal project' } do |f| %>
<% unless #project.persisted? %>
<%= fields_for :invitations do |invitation|%>
<%= invitation.text_field :email, { value: '', name:'invitationfield', class: "typeahead form-control", size: 50, placeholder: "max.mustermann#student.hpi.uni-potsdam.de" } %>
<% end %>
<input type="button" id='AddOneMoreUser' class='btn btn-default btn-xs' value="Add new User">
<div id="invitedUser"> </div>
<% end %>
</div>
<%= f.submit nil, class: 'btn btn-primary' %>
<%= link_to t('.cancel', default: t('helpers.links.cancel')),
projects_path, class: 'btn btn-default' %>
<% end %>
</div>
Here is my JS code:
inviteInitUser = ->
count = 0
$('body').on 'click', '#AddOneMoreUser', ->
console.log 'clicked'
email = $('#invitations_email').val()
$('#invitations_email').val('')
div = document.createElement("div")
div.id = 'user' + count
deleteButton = document.createElement("input")
deleteButton.type = 'button'
deleteButton.value = 'Remove Invitation'
deleteButton.id = 'delete' + count
deleteButton.name = 'deleteInvitationButton' + count
newInvitation = document.createElement("input")
newInvitation.value = email
newInvitation.name = 'invitations[' + count + ']'
div.appendChild(newInvitation)
div.appendChild(deleteButton)
list = document.getElementById("invitedUser")
list.appendChild(div)
count += 1
$(deleteButton).on 'click', -> deleteInvitation()
return
deleteInvitation = ->
deleteButtonCount = $("input[type=button][clicked=true]").prevObject[0].activeElement.id
deleteButtonCount = deleteButtonCount.split('delete')[1]
list = document.getElementById("invitedUser")
elem = document.getElementById("user" + deleteButtonCount)
list.removeChild(elem)
ready = ->
if $('#AddOneMoreUser').length
inviteInitUser()
return
$(document).ready ready
$(document).on 'page:load', ready
So maybe someone knows where my error is . Here is a picture of my input field next to this 'hidden' one:

rails: form on submit should go to a custom url containing values of two dropdown menus

i have a little problem with making a custom url from two value got from dropdown menus.
i am trying to use jquery to that. these two values have their ids as
#convertor_from_currency
#convertor_to_currency
jquery:
<script>
$(document).ready(function(){
$("#currency_form").submit(function(e){
e.preventDefault();
var from = $('#convertor_from_currency').val();
var to = $('#convertor_to_currency').val();
var url_end = from + "-" + to;
var url = $('#currency_form').attr('action') + '/' + url_end;
$('#currency_form').attr('action', url);
$('#currency_form').submit();
//alert(url);
});
</script>
and this is a markup of the form:
<%= form_for :convertor , :html => {:id => "currency_form"}, :url => {:controller => "converter", :action => "show" } do |f| %>
<%= f.label :from_currency %>
<%= f.select :from_currency, options_for_select(currencies, #from_cur) %>
<%= f.label :to_currency %>
<%= f.select :to_currency, options_for_select(currencies, #to_cur), :required => true %>
<%= f.submit "Calculate", class: "btn btn-large btn-primary", id: "submitButton" %>
<% end %>
routes
root 'converter#index'
# get "converter/show"
match '/currencies/', to: 'converter#show', via: [:post]
on submitting i want the url to be:
'/currencies/url_end
where "url_end" is a concatenation of the values submitted in the form:
#convertor_from_currency
#convertor_to_currency
updated, this is my controller.
class ConverterController < ApplicationController
def index
end
def show
#amount = params[:convertor][:amount]
#from_cur = params[:convertor][:from_currency]
#to_cur = params[:convertor][:to_currency]
#result = ConverterHelper.show(#from_cur, #to_cur, #amount)
end
end
how do i do this?
any ideas will be appreciated even if it is using another way other than jquery/javascript
Can you try rewriting this route:
match '/currencies/', to: 'converter#show', via: [:post]
to:
match '/currencies/:from-:to', to: 'converter#show', via: [:post]
In this case requests to (for example) /currencies/usd-eur will be routed to converter#show and you will be able to access the currencies in the controller action using params[from] and params[:to].
UPDATE:
There was an error in javascript code:
This code should work as you expected:
<script>
$(document).ready(function(){
$("#currency_form").submit(function(e){
var from = $('#convertor_from_currency').val();
var to = $('#convertor_to_currency').val();
var url_end = from + "-" + to;
var url = $('#currency_form').attr('action') + '/' + url_end;
$.post(url, $('#currency_form').serialize(), function(data){alert('success');});
alert(url);
e.preventDefault();
return false;
});
});
</script>
You should not call submit on form as long as you are inside submit handler. Instead, you should use $.post(...) to submit the form data. Form data can be serialized as in my example to be sent with the $.post(). You should have added "});" before closing tag.
One of routing configurations that should work for you:
match '/currencies/' => 'converter#index', as: :converter
match '/currencies/:from-:to' => 'converter#show', via: [:post]
your form should use converter_path helper as the action url. And the JS code should submit the form to /currencies/:from-:to.
You need to update the form in the view to:
{:id => "currency_form"}, :url => converter_path do |f| %>
You can use this sample code in your controller to ensure that the form is submitted correctly:
def show
#amount = params[:convertor][:amount]
#from_cur = params[:convertor][:from_currency]
#to_cur = params[:convertor][:to_currency]
##result = ConverterHelper.show(#from_cur, #to_cur, #amount)
render text: "text"
end
You can uncomment the line and remove render once you see that the form is correctly processed on the server.
this can help (it worked for me)
<script>
$(document).ready(function(e){
$("#currency_form").submit(function(){
var from = $('#convertor_from_currency').val();
var to = $('#convertor_to_currency').val();
var url_end = from + "-" + to;
var url = $('#currency_form').attr('action') + '/' + url_end;
$('form#currency_form').attr('action', url);
// window.location.href = url
e.preventDefault();
alert(url);
return false;
});
});
</script>
you can (un)comment to make it work according to your question
don't forget your routes
root 'converter#index'
match '/currencies/', to: 'converter#show', via: [:post]
post '/currencies/:url' => 'converter#show'
then upvote!!!!

Getting rid of form and use just button to create new record

Rails 3.1. I have the following:
// _form.html.erb
<%= form_for ([#country, #state], :remote => true) do |td| %>
<div id= "state_errors" style="display:none"></div>
<%= td.text_field :position, :id => "next_state" %>
<div class="actions">
<%= td.submit %>
</div>
<% end %>
// global.js
function nextState() {
Array.max = function( array ) {
return Math.max.apply( Math, array );
};
var getLastState = $("input.sortable_state_item_position").map(function() {
return $(this).val();
}).get();
getLastState.push("0");
return Array.max(getLastState) + 1;
}
$("input#next_state").val(nextState());
// states_controller.rb
class StatesController < ApplicationController
before_filter :load
def load
#country = Country.find(params[:country_id])
#states = State.all
end
def create
#state = #country.states.build(params[:state])
#state.save
end
...
end
You will notice that I created a form tag for user to create a record when the submit button is clicked. But I am not sure if I could get rid of the entire form_for and just use a normal a or button to trigger the create because I kinda thing that the entire form is redundant as there is no need for the user to input anything. My javascript enters the value automatically.
Please advise. Many thanks.
In my State controller:
def create
#state = #country.states.build(params[:trip_day])
#state.position = State.where(:country_id => #country.id).maximum(:position).to_i + 1
#state.save
end
Replace the form with this:
<%= link_to "Add new state", country_states_path(#country), :remote => true, :method => :post %>
I removed the nextState() function, entire form.

Categories

Resources