Working with JSON.stringify( obj ) in node/express ejs - javascript

I'm trying to pass an object to my view using JSON.stringify but I am not sure how to access elements in the object. Here is how I pass the object to my view:
const getTracking = (request, response) => {
pool.query('SELECT * FROM tracking', (error, results) => {
if (error) {
throw error
}
var trackingObj = JSON.stringify(results.rows);
response.render('pages/trackingInfo', {
trackingObj: trackingObj
});
})
}
Then in my index.ejs document I can access my object like so:
<p><%= trackingObj %></p>
which results in the following output in the browser (data is grabbed from postgres database):
[{"wo_num":1,"completion_date":"2021-08-04T04:00:00.000Z","material":"test","description":"test","qty":1,"total_hours":null},
{"wo_num":2,"completion_date":"2021-08-05T04:00:00.000Z","material":"test2","description":"test2","qty":2,"total_hours":2},
Is there a way to access the elements of this JSON.stringify object individually so I could do something like display them in a table?

JSON.parse('<%- JSON.stringify(trackingObj) %>')
if you want to just see the content you can also use (will be displayed on the terminal
<% console.log(trackingObj) %>
for a better view :
<% console.table(trackingObj) %>

As #Jayesh commented, the solution was to access the object using indices like so: trackingObj[0].material
To then display the elements in a table you can iterate through them in the following manner:
<% trackingObj.forEach(function(obj) { %>
<tr>
<td> <%= obj.material %> </td>
<td> <%= obj.wo_num %> </td>
<tr>
<% } %>

Related

Append ruby partial in javascript, and pass a rails variable

Creating a chat component with ActionCable in Rails5. I learned today that render partial, even in .js.erb does supposedly doesn't work. render specifically is the issue. So now I'm trying to call a partial, and pass a ruby variable to it.
I have tried many things, currently this is how I'm trying to accomplish it:
chatbox.append(<%= j (Erubis::Eruby.new(File.read(File.join(Rails.root, 'app/views/msgs',
'_msg.html.erb'))).result(msg: #msg)) %>);
and the error is
undefined method `self_or_other' for #<Erubis::Eruby:0x007f832bbb8590>
So the partial is there, but the variable is not correct.
views/msgs/_msg.html.erb
<li class="<%= self_or_other(msg) %>">
<div class="avatar">
<%# if msg_interlocutor(msg).avatar.url(:thumb) == "thumb/missing.png" %>
<%= image_tag(msg_interlocutor(msg).avatar.url(:thumb), class: "convoPic")%>
</div>
</li>
I also tried:
chatbox.append(<%= j (Msg.new(File.read(File.join(Rails.root, 'app/views/msgs',
'_msg.html.erb'))).result(msg: #msg)) %>);
And get this error:
When assigning attributes, you must pass a hash as an argument.
Trying with render:
App.msgs = App.cable.subscriptions.create('MsgsChannel', {
received: function(data) {
var chatbox = "#chatbox_" + data.convo + " .chatboxcontent"
var id = data.convo;
var sender_id = data.user.id;
var reciever_id = data.receiver;
<%= #msg %> = data.msg
$(chatbox).append("<%= escape_javascript render(:partial => 'msgs/msg', :locals => { :msg => #msg }) %>");
chatbox.scrollTop(chatbox[0].scrollHeight);
},
renderMsg: function(data) {
console.log(data)
}
});
And error I receive:
undefined method `render' for #<#<Class:0x007fe976b5c180>:0x007fe9773ed470>
How do I properly call in a partial, pass it a ruby variable (with the msg record). Thank you!!
do you have a "messages_helper.rb" file with the following
module MessagesHelper
def self_or_other(message)
message.user == current_user ? "self" : "other"
end
def message_interlocutor(message)
message.user == message.conversation.sender ? message.conversation.sender : message.conversation.recipient
end
end
This is where it's defined.

fix the render with ajax in partial

I am trying to render in another partial, like this:
<% cobran = #detalleco.cobran %>
$("#cobran_<%= #detalleco.IdCobranza %>").fadeOut(500, function(){
$(this).remove();
$(".child").remove();
$("#container_cobranza").html("<%=escape_javascript(render(:partial => 'cobranza/cobran', cobranza: cobran))%>");
});
but I get this error:
ActionView::Template::Error (undefined local variable or method cobran' for #<#<Class:0xb47692ec>:0x83cb1500>
Did you mean? cobran_url):
1: <tr id="cobran_<%= cobran.id %>">
2: <td><%=cobran.id%>
3:
4:
app/views/cobranza/_cobran.html.erb:1:in_app_views_cobranza__cobran_html_erb__36360536__1042659538'
app/views/detallecob/create.js.erb:12:in `_app_views_detallecob_create_js_erb__76211164__1041949938'
don't recognize the variable "cobran" because in the view is doing the render this way:
<tbody id="container_cobranza">
<%= render #cobranza %>
</tbody>
And in the partial puts the singular of "cobranza" that is "cobran" like this:
<tr id="cobran_<%= cobran.id %>">
<td><%=cobran.id%>
<td><%=cobran.FechaReg%></td>
<td><%=cobran.FechaVence%></td>
<td><%=cobran.TipoDoc%></td>
</tr>
How can I solve this issue? thanks
You can't use that erb variable in javascript. Pass it to the javascript via a data attribute. Add to one of your elements: data-cobran="<%= #detalleco.cobran %>" Put an id on the element and then access it by the id var cobran = $("#nameOfId").data('cobran')
After that you can use it.

Passing Params to nodejs ejs template

Guys i'm trying to render MongoDB record in my .ejs file, however, i console.log the variable prior the end of my route and i get the expected value, however, if becomes undefined in the .ejs file
below is the code:
router.get("/new",function(req,res){
var selectedMake;
console.log("Welcome to new make route!");
Make.find({},function(err,result){
if(err){
console.log("an error occured while fetching the data");
}else{
if(req.query.id){
Make.findById(req.query.id,function(err,foundMake){
console.log("found the query string");
selectedMake = foundMake;
console.log(selectedMake); // renders expected value when passing valid ID in the query string
})
}
res.render("vehicles/newvehiclemake",{selectedMake: selectedMake, makes:result,modelId: req.query.id});
}
})
});
and here is the .ejs excerpt where the variable selectedMake is being used:
<% if (!typeof selectedMake == undefined) { %>
<% selectedMake.models.forEach(function(model){ %>
<tr><td><%= model.name %></td></tr>
<% }) %>
<% }else { %>
<tr><td>No Models available for the selected Make</td></tr>
<% } %>
appreciate your input and thanks in advance.
typeof on any variable returns a string so you have to check for 'undefined' in your ejs
<% if (typeof selectedMake !== 'undefined') { %>
I'm not sure but you make mistake at first line in your .ejs file.
Try this:
<% if (typeof selectedMake !== 'undefined') { %>

JavaScript dynamic object keys ejs

I really cannot find a way to describe this. Essentially I have a database that can have any number of tables with different column lengths and names. I have a table which defines each table and it's columns. I have a query to search for values within these tables, and I pass the results of the search and the columns to ejs using express. What I need is to echo the results. I do have:
<div class="row">
<table>
<thead>
<tr>
<% columns.forEach(function(column) { %>
<th><%= column %></th>
<% }); %>
</tr>
</thead>
...
This outputs the name of the columns in the table header correctly. I cannot for the life of me figure out how to print the actual results however. I have tried many different ways but all I keep getting is undefined or [Object object]. I have this currently:
<tbody>
<% for(var r = 0; r < results.length; r++) { %>
<tr>
... need to access column here ...
</tr>
<% } %>
</tbody>
I first tried the following (inside above)
<% for(var key in Object.keys(results[r])) { %>
<%= results[r].key %>
<% } %>
followed by so many different attempts along the lines of this. I suppose the issue is not knowing the possible key names. I don't even know what to search for either to be entirely honest. My mind is drawing a blank.
Any help is much appreciated.
Object.keys returns an array of all the keys in an object. You can use forEach to iterate over those keys, to access the value of the object via object[key]
Also, you can use forEach on your results instead of for to keep things clean.
<% results.forEach(function (result) { %>
<tr>
<% Object.keys(result).forEach(function (key) { %>
<td><%= result[key] %> </td>
<% }) %>
</tr>
<% }) %>
Modern browsers have arrows now, so this can be simplified a little:
<% results.forEach(result => { %>
<tr>
<% Object.keys(result).forEach(key => { %>
<td><%= result[key] %> </td>
<% }) %>
</tr>
<% }) %>

Is it right to generate the javascript using C# in ASP.NET MVC view page?

[Sorry for long question but it is necessary to explain the problem]
I am working on a learning website and it is supposed to show a list of messages to user if there are any. Something like this:
When user presses close button, that message must be marked "read" and should not be shown next time. Following code is used to generate those messages:
<% foreach (var m in Model.UserMessages) { %>
<div class="um" id="m<%=Html.AttributeEncode(m.ID) %>">
<p class="mh"><%= Html.Encode (String.Format ("From {0} ({1})", m.From, m.Sent)) %></p>
<p><%= Html.Encode (m.Text) %></p>
<% using (Html.BeginForm ("CloseMessage", "Home", new { id = m.ID })) { %>
<input type="submit" value="Close<%= Html.AttributeEncode (m.ID) %>" id="c<%= Html.AttributeEncode (m.ID) %>"/>
<% } %>
</div>
<% } %>
After that, following the guidelines, I added the support of http post method in controller which marks the message as read and then refreshes the view (to handle disabled JavaScript):
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult CloseMessage (int id) {
using (var dl = new DL ()) {
dl.MarkAsRead (id);
}
if (Request.IsAjaxRequest ()) {
return new EmptyResult ();
}
else {
return RedirectToAction ("Index");
}
}
Then I wanted to add JavaScript support such that only the message goes away (using jQuery). But the problem is that I am generating the buttons and messages programmatically.
So ended up with a weird looking javascript code in viewpage:
<script type="text/javascript">
$().ready(function() {
<% foreach (var m in Model.UserMessages) { %>
$("#c<%=Html.AttributeEncode (m.ID) %>").click(function(event) {
$.post("Home/CloseMessage/<%=Html.AttributeEncode (m.ID) %>");
$("#m<%=Html.AttributeEncode (m.ID) %>").slideUp("slow");
event.preventDefault();
});
<% } %>
});
</script>
This is basically creating the javascript code in a C# loop which actually works but too much for me to digest. Is there any better way of doing this?
You could just create one javascript function that takes the element IDs as parameters :
function myFunction(ID) {
$.post("Home/CloseMessage/" + ID);
$("#m" + ID).slideUp("slow");
}
And :
<% foreach (var m in Model.UserMessages) { %>
<div class="um" id="m<%=Html.AttributeEncode(m.ID) %>">
<p class="mh"><%= Html.Encode (String.Format ("From {0} ({1})", m.From, m.Sent)) %></p>
<p><%= Html.Encode (m.Text) %></p>
<% using (Html.BeginForm ("CloseMessage", "Home", new { id = m.ID })) { %>
<input type="submit" value="Close<%= Html.AttributeEncode (m.ID) %>"
id="c<%= Html.AttributeEncode (m.ID) %>"
onclick="myFunction('<%=Html.AttributeEncode(m.ID)%>')"/>
<% } %>
</div>
<% } %>
YOu could uses a CSS selector in your JS to get all buttons with a particular class assigned to them. Then you can wire up you click event to them. So your HTML would be something like this:
<% foreach (var m in Model.UserMessages) { %>
<div class="um" id="m<%=Html.AttributeEncode(m.ID) %>">
<p class="mh"><%= Html.Encode (String.Format ("From {0} ({1})", m.From, m.Sent)) %></p>
<p><%= Html.Encode (m.Text) %></p>
<% using (Html.BeginForm ("CloseMessage", "Home", new { id = m.ID })) { %>
<input type="submit" class="MyCloseButton" value="Close<%= Html.AttributeEncode (m.ID) %>" id="c<%= Html.AttributeEncode (m.ID) %>"/>
<% } %>
</div>
<% } %>
I've only added the class="MyCloseButton" to your input
Then in your JS (I use mootools but JQuery has CSS selectors too but you will need to port it sorry) you can do something like this:
window.addEvent( "domready", function() {
$$("input.MyCloseButton").each( function( button ) {
// Add your code here, you can reference button.id etc for each of your buttons
}
});
This way you only have to write out one little function in plan JS and not worry about doing it server-side, all you need to do it decorate your buttons with a css class so the JS can find them.
I understand its not pretty, but its not that bad either. I think there are easier ways to do this, however.
You can use jquery's positional selectors from the button's click event handler. Then just assign the same handler to every button.
<script type="text/javascript">
$(document).ready(function() {
$("input[type=submit]").click(function(){
$(this).parent().slideup("slow");
$.post("Home/CloseMessage/" + $(this).parent().attr("id"));
event.preventDefault();
});
});
});
</script>

Categories

Resources