This is the Category model:
var mongoose = require("mongoose");
var categorySchema = new mongoose.Schema({
name:String,
image:String,
description:String,
series: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "Series"
}
]
});
module.exports= mongoose.model("Category",categorySchema);
And This is the series model
var mongoose=require("mongoose");
//making the schema
var seriesSchema = new mongoose.Schema({
name:String,
type:String,
application:String,
product:[{
type: mongoose.Schema.Types.ObjectId ,
ref:"Product"
}]
});
module.exports=mongoose.model("Series",seriesSchema);
So each Category includes some series that has a name and an application and series in an array.
My table and this is the original code:
<table class="table">
<thread>
<tr>
<th scope="col" class="mytable">Series Name</th>
<th scope="col" class="mytable">Series Application</th>
</tr>
</thread>
<tbody>
<% Category.series.forEach(function(series){ %>
<tr>
<td><strong><%=series.name%></strong></td>
<td><em><%=series.application%></em></td>
</tr>
<% }); %>
</tbody>
</table>
I want to merge rows that have the same content. I tried to use a for loop which ended up screwing the whole thing new results:
<table class="table">
<thread>
<tr>
<th scope="col" class="mytable">Series Name</th>
<th scope="col" class="mytable">Series Application</th>
</tr>
</thread>
<tbody>
<% for(var i=1;i<series.length;i++){ %>
<tr>
<td><strong><%=series[i-1].name%></strong></td>
<% var j=1;%>
<% console.log(series[i]);%>
<% if(series[i-1].application==series[i].application){ %>
<% j++; %>
<td rowspan="<%=j%>"><em><%=series[i-1].application%></em></td>
<% } else { %>
<td><em><%=series[i-1].application%></em></td>
<% } %>
<% j=0;%>
</tr>
<% }; %>
</tbody>
</table>
As far as I can see, you really don't have rows with equal content in them. They either differ in the first column or in both. Anyway, it appears to me as if you'd try to combine the rows if their contents are equal in the second column.
In case it is OK to loose the information inside the first column, you'll want to just skip the entire row. Just move the comparison before you render the <tr>. Don't forget that you have to render the first row in any case. For example:
<table class="table">
<thread>
<tr>
<th scope="col" class="mytable">Series Name</th>
<th scope="col" class="mytable">Series Application</th>
</tr>
</thread>
<tbody>
<% for(var i = 0; i < series.length; i++){ %>
<% if(i < 1){ %>
<tr>
<td>
<strong>
<a href="/categories/<%=Category._id%>/series/<%=series[i]._id%>/products"><%=series[i].name%>
</a>
</strong>
</td>
<td>
<em><%=series[i].application%></em>
</td>
</tr>
<% } else if(series[i-1].application !== series[i].application){ %>
<tr>
<td>
<strong>
<a href="/categories/<%=Category._id%>/series/<%=series[i]._id%>/products"><%=series[i].name%>
</a>
</strong>
</td>
<td>
<em><%=series[i].application%></em>
</td>
</tr>
<% }; %>
<% } %>
</tbody>
</table>
The other possibility would be to combine the values of the first column. Solving that inside the loop is going to get fuzzy. It's easier to combine the information before you render them, although you have to utilize a bit more extra JavaScript for it. The JS changes the structure in such a way, that it merges contents in the first column together (link in the code below) if they have the same application:
function mergeEqApplications (series) {
return series.reduce(function (acc, s) {
if (!acc.hasOwnProperty(s.application)) {
acc[s.application] = {
link: [{name: s.name, id: s._id}],
application: s.application
};
} else {
acc[s.application].link.push({name: s.name, id: s._id});
}
return acc;
}, {});
}
function objToArray (obj) {
return Object.keys(obj).map(function (key) { return obj[key]; });
}
function convert (series) {
return objToArray(mergeEqApplications(series));
}
Category.series = convert(Category.series);
<table class="table">
<thread>
<tr>
<th scope="col" class="mytable">Series Name</th>
<th scope="col" class="mytable">Series Application</th>
</tr>
</thread>
<tbody>
<% Category.series.forEach(function (series) { %>
<tr>
<td>
<strong>
<% series.link.forEach(function (info) { %>
<a href="/categories/<%= Category._id %>/series/<%= info.id %>/products">
<%= info.name %>
</a>
<% }); %>
</strong>
</td>
<td>
<em><%= series.application %></em>
</td>
</tr>
<% }); %>
</tbody>
</table>
Related
I have a problem with iterating objects on EJS. I am connected to a DB on the backend, and I can console log the objects but when I run it through the front end, I get a result of [Object]
Here is the code on my code in the backend
app.get('/usageData', (req, res) => {
tableSvc.queryEntities('usageData', query, null, function (error, result, response) {
if (!error) {
Object.keys(result).forEach(function(key){
const final=result[key]
res.render("usage",{final})
})
} else {
console.log(error)
}
});
});
And on EJS:
<ul>
<table >
<table class="table table-hover">
<thead>
<tr class="indexs">
<th scope="col">PartitionKey</th>
<th scope="col">RowKey</th>
<th scope="col">Action</th>
<th scope="col">SelectedReports</th>
<th scope="col">reportInterval</th>
</tr>
</thead>
<tbody>
<tr>
<% for(var i in final) { %>
<tr style="font-size: 15px">
<td><%= final[i].PartitionKey %> </td>
<td><%= final[i].RowKey %> </td>
<td><%= final[i].Action %> </td>
<td><%= final[i].SelectedReports %> </td>
<td><%= final[i].reportInterval %> </td>
</tr>
<% } %>
</tr>
</tbody>
</table>
</table>
</ul>
Instead of calling res.render() in each loop iteration, build an array of data and pass that only once
if (error) {
console.error(error)
return res.status(500).send(error)
}
res.render("usage", {
final: Object.values(result)
})
Also, don't use for..in to iterate arrays
<tbody>
<% for(const usage of final) { %>
<tr style="font-size: 15px">
<td><%= usage.PartitionKey %> </td>
<td><%= usage.RowKey %> </td>
<td><%= usage.Action %> </td>
<td><%= usage.SelectedReports %> </td>
<td><%= usage.reportInterval %> </td>
</tr>
<% } %>
</tbody>
I have to update the status of mac device which i am selecting(checkbox) from html table.If i am selecting one mac from html table,it will show offline or online status of mac.Below code i am using for this.Problem is if i am selecting any mac only first row status column is updating.I want to update selected mac row status in respective column.
I am trying with below code but it is not working
var nextColumnCell = $(selected_device_mac).parent("tr").find(selected_device_id)
if(result.includes("On-line")){
nextColumnCell.html("");
nextColumnCell.append(result + " ✅")
}else if(result.includes("Off-line")){
$(selected_device_id).html("");
$(selected_device_id).append(result+" ❗");
}
Actual Code
function macDeviceClickedBox(checkBoxName){
var values = new Array();
var selected_device_id ;
var selected_device_mac ;
$.each($("input[name='"+checkBoxName+"']:checked").closest("td").next("td"), function () {
values.push($(this).text().trim())
});
document.getElementById("macaddress").value = values.join("\n");
selected_device_id = '#Selected_Device';
selected_device_mac = values.join("\n");
alert(selected_device_mac)
$('#cover-spin').show();
$.ajax({
method: "GET",
dataType: "text",
url: "getDeviceType",
data: {
mac : selected_device_mac.trim(),
},
success: function(result) {
$('#cover-spin').hide();
if (result !== "") {
if(result.includes("On-line")){
$(selected_device_id).html("");
$(selected_device_id).append(result+" ✅");
}else if(result.includes("Off-line")){
$(selected_device_id).html("");
$(selected_device_id).append(result+" ❗");
}
}else{
$(selected_device_id).html("");
$(selected_device_id).append("Not Selected ❗");
}
}
});
}
Html.erb
<table id="DeviceTable" class="table table-bordered">
<thead>
<tr class="info">
<th style="width: 10px;">Select</th>
<th>Device</th>
<th> Type</th>
<th> Model</th>
<th> Status</th>
</tr>
</thead>
<tbody class="parameter_table">
<% #devices.all.each do |parameter| %>
<tr id="device_<%=parameter.id %>">
<td >
<input type="checkbox" class="checkBox" name="checkBox[]" onchange="macDeviceClickedBox(this.name)">
</td>
<td id="macaddress" style="word-break:break-all;">
<%= parameter.mac_address%>
</td>
<td style="word-break:break-all;">
<%= parameter.device_type%>
</td>
<td style="word-break:break-all;">
<%= parameter.model%>
</td>
<td class="Selected_Device" id="Selected_Device">
<b id="Selected_Device" style="float: right;">!Not Selected</b>
</td>
</tr>
<% end %>
</tbody>
</table>
I am trying to render the data to EJS page but I was not able to send the data into EJS page. Currently, I am receiving the data as a recordset from MSSQL database. Below screenshot gives the outcome of console.log(rows).
[https://i.stack.imgur.com/CItXQ.jpg][1]
Coding for Database:
app.get('/data', receiveData);
function receiveData(req, res) {
db.executeSql("SELECT * FROM arduino", function (recordsets, err, ) {
var data = JSON.stringify(recordsets);
if (err) {
httpMsgs.show500(request, res, err);
}
else {
var Jdata = JSON.parse(data);
console.log(Jdata);
res.render('arduino',{Jdata:Jdata});
}
});
}
Coding for Ejs
<table border="1" cellpadding="7" cellspacing="7">
<tr>
<th> - </th>
<th>ID</th>
<th>Machine</th>
<th>Start Time</th>
<th>End Time</th>
<th>Length Time</th>
<th> Day/Night</th>
<th>Job Number</th>
</tr>
<% if(Jdata.length){
for(var i = 0;i < Jdata.length;i++) { %>
<tr>
<td><%=(i+1)%></td>
<td> </td>
<td><%=Jdata.recordset[0].Id %></td>
<td><%=Jdata.recordset[0].StartTime%></td>
<td><%=Jdata.recordset[0].EndTime%></td>
<td><%=Jdata.recordset[0].LengthTime%></td>
<td><%=Jdata.recordset[0].Day%></td>
<td><%=Jdata.recordset[0].JobNumber%></td>
</tr>
<% }
}else{ %>
<tr>
<td colspan="3">No Data</td>
</tr>
<% } %>
</table>
It would be great if anyone can help me out.
Thanks.
I hope below answer will fix your problem. You are using Jdata.length instead of Jdata.recordset.length. As per the console log, I understand this.
<table border="1" cellpadding="7" cellspacing="7">
<tr>
<th> - </th>
<th>ID</th>
<th>Machine</th>
<th>Start Time</th>
<th>End Time</th>
<th>Length Time</th>
<th> Day/Night</th>
<th>Job Number</th>
</tr>
<% if(Jdata.recordset.length){
for(var i = 0;i < Jdata.recordset.length;i++) { %>
<tr>
<td><%=(i+1)%></td>
<td> </td>
<td><%=Jdata.recordset[0].Id %></td>
<td><%=Jdata.recordset[0].StartTime%></td>
<td><%=Jdata.recordset[0].EndTime%></td>
<td><%=Jdata.recordset[0].LengthTime%></td>
<td><%=Jdata.recordset[0].Day%></td>
<td><%=Jdata.recordset[0].JobNumber%></td>
</tr>
<% }
}else{ %>
<tr>
<td colspan="3">No Data</td>
</tr>
<% } %>
</table>
Oh, that was easy, don't use <%, use <%- instead. For example:
<%- Jdata.length %>
<%= will render in HTML <%- will render variables (as they are, eval)
In my case, the error was that I was trying to access an array instead of an single object.
So, I changed model.find() to
model.findOne({username:req.params.username},(err,user)=>{
if(err) res.send(err)
res.render("home",{user:user})
})
on ejs you get these user proprieties :
<p><%=user.username%></p>.
I want to hide the value of column in table, the data of table is bind from database
This is my html code
<table id="datatable-responsive" class="table table-striped table-bordered dt-responsive nowrap" cellspacing="0" width="100%">
<thead>
<tr>
<th id="th_id_event">Id Event Category</th>
<th>Event Category</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<% objLOV.forEach(function (lov) { %>
<tr onclick="callme(this)">
<td id="td_id_event">
<%= lov.id %>
</td>
<td>
<%= lov.event_category %>
</td>
<td>
<%= lov.description %>
</td>
</tr>
<% }) %>
</tbody>
</table>
<% objLOV.forEach(function (lov) { %> is to get data from database
I have tried like this, but the only first column first row get hide, I want hide all the value of the column id
window.onload = function () {
document.getElementById("td_id_event").style.display = "none";
document.getElementById("th_id_event").style.display = "none";
};
my table
my table after i tried to disable
can anyone help me? thank you..
You can only validly have one element with a given id so attempting to reference multiple elements with the same id is unlikely to work. You could use a class for the element instead i.e. replace
<td id="td_id_event"
with
<td class="id_event"
and then use
window.onload = function () {
var ids = document.getElementsByClassName("id_event");
for (var i = 0; i < ids.length; i++) {
ids[i].style.display = "none";
}
I'm trying to get a popover for my webpage. It doesn't work for me on the first click but however works fine thereafter. I realize that it gets instantiated on the first click and therefore doesn't show up. Is there a better way to instantiate it, given that I'm using id's that are generated at runtime. I have looked at similar questions but they don't seem to work for me. Here is the code I have written,
<table id="userInfo">
<thead>
<tr>
<th>UserGroup</th>
</tr>
</thead>
<tbody>
<% #userdetails.each do |user| %>
<tr>
<td>
<a class='user_show_more' data-placement='left' id='<%= user %>'>[+]</a>
<!-- popover table starts here -->
<div id="<%= user %>_popover" style="display: none">
<table>
<thead>
<tr>
<th>UserNames</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<%= user['name'] %>
</td>
</tr>
</tbody>
</table>
</div>
<!-- popover ends here -->
<% user['group'] %>
</td>
</tr>
<% end %>
</tbody>
</table>
And my javascript code looks like this,
$('.user_show_more').on('click', function (e) {
var $this = $(this)
var popover_id = '#'+$this.attr("id");
$(popover_id).popover({
html : true,
content: function() {
var popover = '#'+$this.attr("id")+'_popover';
return $(popover).html();
}
});
});
You can add two click handlers to your popovers. The first one uses 'one' and the second one uses 'on'.
https://jsbin.com/kegovebufu/1/edit?html,js,console,output
HTML
<button type="button"
class="btn btn-lg btn-danger"
data-toggle="popover"
id="Temp"
>Stuff</button>
<script type="text/html" id="Temp_popover">
<div>
<table>
<thead>
<tr>
<th>UserNames</th>
</tr>
</thead>
<tbody>
<tr>
<td>blah</td>
</tr>
</tbody>
</table>
</div>
</script>
Javascript
function PopoverClick()
{
$(this).popover('toggle');
}
$('[data-toggle="popover"]').one('click',function(e){
console.log('once');
var _this = $(this);
_this.popover(
{
html:true,
content: function()
{
return $('#'+$(this).attr("id")+'_popover').html();
},
trigger: 'manual',
placement:'right'
}).popover('show');
_this.on('click',PopoverClick);
});