How to render a partial within javascript - javascript

I have two forms on a page which have mostly the same inputs. I have tabs on the screen that switch between each form. However when i submit one of the forms, i recieve a 'cant be blank' on the same input fields on the other form. I understand why this is happening. I tried to stop this by using a if statement to only render either form depending on which tab is clicked. This did not work as you cant target html id's in an if statement. Then i tried to use javascript which used a 'show' and 'hide' methods depending on which tab was clicked which also didnt work as i believe that that even though the form is still hidden, it is still actually there. Now im not sure what to do. My only idea is to render the forms within javascript?
<input id="tab1" type="radio" name="tabs" checked>
<label class="label-header" for="tab1"> UK Address</label>
<input id="tab2" type="radio" name="tabs">
<label class="label-header"for="tab2"> International Address </label>
<!-- <section id="content1"> -->
<%# if %>
<%= f.simple_fields_for :address do |fields| %>
<%# raise %>
<section id="content1">
<%= render "address/fields", fields: fields, addressable: addressable %>
</section>
<% end %>
<%# else %>
<%= f.simple_fields_for :address do |fields| %>
<section id="content2">
<%= render "address/international_fields", fields: fields, addressable: addressable %>
</section>
<% end %>
$(document).ready(function() {
var uk_address = $('#content1');
var international_address = $('#content2');
$('#tab1').on('click', function() {
uk_address.show();
international_address.hide();
});
$('#tab2').on('click', function() {
uk_address.hide();
international_address.show();
});
});

You should be able to enable/disable the items inside the javascript you have with this modification:
$(document).ready(function() {
var uk_address = $('#content1');
var international_address = $('#content2');
$('#tab1').on('click', function() {
uk_address.removeAttr("disabled").show();
international_address.attr("disabled", "disabled").hide();
});
$('#tab2').on('click', function() {
uk_address.attr("disabled", "disabled").hide();
international_address.removeAttr("disabled").show();
});
});

Related

How to use a passed variable in an ejs file

SO i am trying to change the value of an html tag in an ejs file to a variable i declared in a JavaScript file
let checkbox = document.querySelector('input[name="plan"]');
checkbox.addEventListener('change', function () {
if (this.checked) {
document.querySelector('.plan-title').innerHTML = investment.name;
document.querySelector('.plan-description').innerHTML = investment.description;
}
else {
document.querySelector('.plan-title').innerHTML = '';
document.querySelector('.plan-description').innerHTML = '';
}
});
So when I pass it directly it shows but I want it to be dynamic and Although it gets pass through when i click the checkbox it doesn't seem to have any value.
<%- include('../partials/sidebar'); %>
<% if(currentUser && currentUser.isAdmin){ %>
Add New Plan
<% } %>
<div class="container">
<h1>Investments</h1>
<% investments.forEach((investment)=>{ %>
<div class="col-md-4">
<div class="card">
<strong>
<%= investment.name %>
</strong>
<h4>
<%= investment.min %> - <%=investment.max %>
</h4>
<p>
<%= investment.caption %>
</p>
<p><input type="checkbox" name="plan" id="">Choose investment</p>
</div>
<% if(currentUser && currentUser.isAdmin){ %>
Edit
Delete
<% } %>
</div>
<% }) %>
<% investments.forEach((investment)=>{ %>
<div class="">
<div><strong>Package: </strong>
<p class="plan-title">
</p>
</div>
<p class="plan-description">
</p>
<input type="number" name="" id="" min="<%= investment.min %>"
max="<%= investment.max %>">
</div>
<% }) %>
</div>
<%- include('../partials/footer'); %>
I cant seem to get through this, need help thanks!
If I got it right, you are trying to insert the value of the EJS variable in the HTML tag from JavaScript when the user clicks the checkbox.
The value of the HTML tag doesn't change because in your JS code:
document.querySelector('.plan-title').innerHTML = investment.name;
document.querySelector('.plan-description').innerHTML = investment.description;
investment.name and investment.description are undefined. Check the console on your page.
This is because you tried accessing EJS variables after the page finished rendering.
EJS is mainly used to pass server-side variables to the page before it is rendered. So once it's rendered you cannot access those variables.
So to have the values of those variables in your JavaScript after the page finishes rendering, try doing:
document.querySelector('.plan-title').innerHTML = '<%- investment.name %>';
document.querySelector('.plan-description').innerHTML = '<%- investment.description %>';
instead. This is how you pass the EJS variable to JavaScript. JavaScript now sees it as a string and there's no problem, unlike in your code where it was looking for investment object and returned undefined since that variable is not defined on the client-side.
Also, since you have a for-each loop in the HTML part, I'm assuming you are trying to change the values of specific plan-title and plan-description divs. If that's the case, '<%= investment.name %>' and '<%= investment.description %>' in JavaScript part should be in a for-each loop as well, but that would be a lot of mess.
I suggest you instead to right under the for-each loop in the HTML part, add class to the div tag according to the index of the for-each loop, add on change event to the checkbox, and pass the checkbox and the index of the for-each loop to the JavaScript function which would handle the on change event, include the EJS variables in the plan-title and plan-description divs, and in the JavaScript function that handles on change event change the CSS display property from display: none to display: block to these divs.
See an example:
HTML:
<% investments.forEach((investment, index)=>{ %>
<div class="col-md-4">
<div class="card">
<strong>
<%= investment.name %>
</strong>
<h4>
<%= investment.min %> - <%=investment.max %>
</h4>
<p>
<%= investment.caption %>
</p>
<p><input onchange="displayPlan(this, '<%= index %>')" type="checkbox" name="plan" id="">Choose investment</p>
</div>
<% if(currentUser && currentUser.isAdmin){ %>
Edit
Delete
<% } %>
</div>
<% }) %>
<% investments.forEach((investment, index)=>{ %>
<div class="plan <%= index %>" style="display: none;">
<div><strong>Package: </strong>
<p class="plan-title">
<%- investment.name %>
</p>
</div>
<p class="plan-description">
<%- investment.description %>
</p>
<input type="number" name="" id="" min="<%= investment.min %>"
max="<%= investment.max %>">
</div>
<% }) %>
JavaScript:
function displayPlan(checkbox, id){
if (checkbox.checked) {
document.querySelector(`.plan.${id}`).style.display = 'block';
}
else {
document.querySelector(`.plan.${id}`).style.display = 'none';
}
}
Cheers!
EDIT: Grammar and syntax issues
It's not clear to me what variable you're referring to, but any variable you set in a client-side script will not be available to you in an EJS file that you're rendering on the server. Server-side Node.js code and client-side JavaScript code have no knowledge of each other.

How do I make javascript change the element of specific element in rails

I have a little bit of a problem with the id names for my rails app where I want javascript to disable/enable a field with the press of a button.
I have a big index page where people can rate a bunch of pictures on the index page itself. For this I am using the #posts.each do |post| method.
The user should then be able to rate the picture with a slider, and after the slider was used, the range should be disabled. If the user wants to change the rating it is possible to click on "CHANGE", which enables the slider again.
Problem I have right now is with the enable function. I have a bunch of posts on the index page, and and all of the sliders and buttons have the same class names and ids. I have tried to give each slider and button a specific id with id:'ratingPost#{post.id}', but the problem then is that I cannot get javascript to know what is the postid that was just clicked.
Can you help me here?
Thank you very much!
My code is here:
#posts_index.html.erb
<% #posts.each do |post| %>
...
<% if post.ratings.find_by(user_id: current_user.id) %>
<%= form_for [post, post.ratings.find_by(user_id: current_user.id)] do |f| %>
<%= f.range_field :score, class:"form-control-range slider", id:"ratingPost", onMouseUp:"submit()", onTouchEnd:"submit()", :disabled => true, data: { source: post} %>
<% end %>
<% else %>
<%= form_for [post, #rating] do |f| %>
<%= f.range_field :score, class:"form-control-range slider", id:"formControlRange", onMouseUp:"submit()", onTouchEnd:"submit()"%>
<% end %>
<% end %>
...
<% if post.ratings.find_by(user_id: current_user.id) %>
<h2><%= post.ratings.where(user_id: current_user.id).last.score %>%</h2>
<button id="RatingChangeButton"><p>CHANGE</p></button>
<% end %>
</div>
</div>
</div>
<% end %>
<script>
document.getElementById("RatingChangeButton").addEventListener("click", enableRating);
function enableRating() {
document.getElementById("ratingPost").disabled=false;
}
</script>
Ideally you should not have multiple elements with the same ID in your HTML, instead use class.
Now to your question, what you can do is store the id of the post in a data attribute for your buttons and rating fields, and access that id in the javascript function to identify the corresponding slider. Something like,
https://codepen.io/anujmiddha/pen/NWRwwLL
<p>Post 1: <input class="ratingPost" data-post-id="1" disabled></p>
<p>Post 2: <input class="ratingPost" data-post-id="2" disabled></p>
<p>
<button class="RatingChangeButton" data-post-id="1" onClick="enableRating(this)">
<p>CHANGE 1</p></button>
</p>
<p>
<button class="RatingChangeButton" data-post-id="2" onClick="enableRating(this)">
<p>CHANGE 2</p></button>
</p>
function enableRating(view) {
let element = document.querySelector('[data-post-id="' + view.dataset.postId + '"],[class="RatingChangeButton"]');
element.disabled = false;
element.value = "enabled";
}

Send f.select parameter to jquery and show dynamic form elements

I have a form who uses a nasted form. I want to him show up when the f.select selects the option unificação.
I using a example that i see in a example, when i select a new option the alert appers, but i don't know how i send the selected element to function and how i tell to him to show the f.fields_for :unifications.
<div class="form-row">
<label>
<span>Evento</span>
<%= f.select :event, ['Reencaminhar', 'Reclassificar', 'Rejeitar alteracão de diagnóstico', 'Rejeitar reencaminhamento', 'Solicitar esclarecimento', 'Cancelar solicitação', 'Rejeitar cancelamento', 'Responder', 'Unificação', 'Envio de cópia de ID', 'Reiterar', 'Registrar Solicitação', 'Reabrir solicitação', 'Complementar solicitação'], {}, :onChange => "fillForm.test(this)" %>
</label>
</div>
<%= f.fields_for :unifications do |unification_form| %>
<label>
<%= unification_form.link_to_remove "Remover cpf" %>
<%= unification_form.text_field :cpf %>
</label>
<% end %>
requests.coffee
#fillForm =
test: ->
alert('Hello world')
Add a div to hide/show the nested form block:
<div id="attributes-to-display" style="display:none">
<%= f.fields_for :unifications do |unification_form| %>
<label>
<%= unification_form.link_to_remove "Remover cpf" %>
<%= unification_form.text_field :cpf %>
</label>
<% end %>
</div>
Its hidden by default. I don't use coffee script, so a possible solution with plain javascript:
// binds the change event
$("#the_select_id").on('change', function() {
// checks if the selected value is what you expect
if ($(this).val() == "whatever") {
// if so, show the block
$("#attributes-to-display").show();
}
else {
// if not, hide the block
$("#attributes-to-display").hide();
// and clean the cpf input box
$("#the_nested_input_id").val('');
}
});
You need to replace the ids (#) with the correct form ids, as I don't have enough information to provide it.

Back button Javascript issue

So I have a page where I am making selections using option buttons, Those selections show up as a value. There are options which are selected as default using Javascript as per the code below.
Now on hitting Proceed I go to the next page. Now on the next page I have a back button and when I press the back button, What I want is the selections which I had made on the previous page should remain the same, What is happening on the other hand is, the default selected options are showing up.
I am using this button for the moment:
<input type="button" value="Back" onclick="window.history.back()" />
And this is how I am doing the selection:
<div class="panel panel-default">
<div class="panel-heading">
<h2 class="panel-title" id="selected_part_<%= part.id %>">
<% #link_text = "<b>#{part.name}</b> : <span class='selected_part_option'>#{part.options.detect{|o| o.is_default?}.try(:name)}</span>" %>
<% if part.children.exists? %>
<% part.children.each do |part_child| %>
<% if part_child.display_type == "radio" || part_child.display_type == "dropdown" %>
<%# #link_text = #link_text + " | <span id='part_child_" + part_child.id.to_s + "'>" + part_child.options.first.name + "</span>" %>
<% end %>
<% end %>
<% end %>
<%= link_to raw(#link_text), "#collapse_part_#{part.id}", class: "collapser", "data-toggle" => "collapse", "data-parent" => "#accordion" %>
</h2>
</div>
Any idea how do I achieve what I want to?
Thanks in advance.
The default behaviour of Firefox browser is to remember the form's input value. I think in your case, you may use some JavaScript which reset the form automatically, which makes lost the state that the browser remembered.

.load() Jquery function load duplicate window in the same time

I have the Jquery code below:
$(document).ready(function() {
$('tr[href]').click(function(event) {
$('tr[href]').removeClass('selected')
$(this).addClass('selected');
event.preventDefault();
$('#profile').load('home/users/1');
event.stopPropagation();
});
});
Every time I click the target, I found the .load function load the window double times the last click. For example, in the rails log it shows several Started GET "/home/users/1in the same time thus my app becomes slow and slow. Below is the view file where the window is loaded:
<div class="col-md-5" >
<div class="table table-responsive" >
<div id='list' >
<% if params[:q] == 'a' %>
<%= render 'users' %>
<% elsif params[:q] == 'b' %>
<%= render 'jobs_index' %>
<% else %>
<%= render 'lineitems' %>
<% end %>
</div>
</div>
</div>
<div class="col-md-5">
<div id="profile">//load the window
</div>
Could any body tell me why this occurs? Very thanks!
I solved it.
I modified the code $('#profile').load('home/users/1'); in application.js as below:
var url="home/users/"+$(this).attr("href")
$('#profile-outline').load(url+" #special");
And add a in the outermost of the html file.Then the problem is solved.
In summary, just use load("url #container") to replace load("url").

Categories

Resources