How to use a passed variable in an ejs file - javascript

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.

Related

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";
}

How to render a partial within 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();
});
});

Load data after Ajax request in a template

I render a page with the data that ejs puts together. when the user presses a submit button a section (thirdRow)of the page should be refreshed with the new data that was submitted plus the old data. I got the new data in the db, I want to refresh the thirdRow that shows all the reviews.
basically my problem is the success method in the $.ajax . I could get all the data there but it seems weird to write everything over in html strings. There should be a better way.
I saw a method where I could put the .thirdRow into a template and include that into the main EJS page and also put that into my static public folder and do something like new EJS({url : 'public/thirdRow.ejs' }).update('.thirdRow', data); in this case is the data in the last code snippet the returned data from the success callback in the AJAX? How Do I get Access to the EJS There are alot of links for ejs can you show my how to include the EJS
I don't know if this is the correct method. How would you do it? I have a page that is basically made up of all the returned data and I want to click a button and have only one section have the new data.
One section inside main.ejs
<div class="thirdRow">
<div class="reviewSection">
<% if(reviews){%>
<% reviews.forEach(function(e, i){%>
<div class="indivReview">
<div class = "userRow row">
<div>
<span>user </span>
<% if( e.username) {%>
<span><%= e.username %></span>
<%}else{ %>
<span><%=e.user%></span>
<% }%>
</div>
<div><%= e.momented %></div>
</div><!--userRow-->
<div class = "companyRow row">
<div>
<span>Experince for</span>
<span><%=e.companyName%></span>
</div>
<div>
<span> industry</span>
<span>online retail</span>
</div>
</div> <!--companyRow -->
<div class="voteRow row">
<div>
Vote
</div>
<div><%= e.vote%></div>
</div>
<div class="reviewRow row">
<div>Review</div>
<div class = "displayReview">
<% e.reviewText.split("\n").forEach(function(e){ %>
<%= e %><br>
<%})%>
</div>
</div>
<div class="statementRow ">
// make a div for each object
<% e.statements.forEach(function(obj){%>
<div class="indivStatement">
<% var arr = []%>
<%for(var prop in obj) {%>
<% if(prop !== "name"){ %>
<% if(prop == "question"){%>
<% arr[0] = obj[prop] %>
<%} %>
<% if (prop == "result"){%>
<% arr[1] = obj[prop] %>
<%}%>
<% console.log(arr) %>
<%} %>
<%}%>
<div class = "question"><%= arr[0]%></div>
<div class = "bar" data-result ="<%= arr[1]%>"><%= arr[1]%></div>
</div>
<%})%>
</div>
<div> <span></span>
<span><%=e.companyName%></span></div>
<div><%= e.momented %></div>
</div>
<%})%>
<%}%>
</div> <!--reviewSection-->
</div> <!--thirdRow-->
inside client script
$(".submitButton").on("click",function(){
console.log(datum)
var empty;
if(datum.reviewText == "" && Object.keys(datum.statements) == 0 && datum.vote == null){
empty = true;
}else{
empty = false;
}
console.log("empty : " , empty)
scrollFunction(".thirdRow", ".submitButton, .shareButtonSection")
var data = datum;
if(!empty){
$.ajax({
type : "POST",
data : JSON.stringify(data),
contentType : "application/json",
url : "http://localhost:4000/submitreview",
success : function(data){
console.log("success")
$(".thirdRow").fadeOut(800, function(){
console.log("this", $(this))
$(this).html(data).fadeIn().delay(200)
})
console.log(data)
}
})
}
})
I never used EJS on the client side. Allways used with express
Here's an example of using EJS client side
https://github.com/tj/ejs/blob/master/examples/client.html

.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").

FadeToogle Jquery dont works the selector next on this

Well, i have a div hide in my content and make a buttom to show this but the problem is i have many elements whit this names so i make this function to solve:
$("a.all_com").click(function(){
$(this).nextAll("div:first").slideToggle();
});
This function dont works, i try use meet this:
$("a.all_com").click(function(){
$(this).next("div").slideToggle();
});
and
$("a.all_com").click(function(){
$(this).nextAll("div").slideToggle();
});
Nobody works whit me please someone solution, the this is to apply some in the element actually.
My code to show/hide is this:
<div id="task_footer">
Comentar
Comentários
</div>
<div id="comment_list" style="display:none;" >
<% tasks.comments.each do |c| %>
<% if c.user %>
<p class="one_comment">
<strong><%= c.user.email %></strong>
<%= c.comment %>
</p>
<% end %>
<% end %>
</div>

Categories

Resources