IMAGEThis is how ist's displayed on the web
I want to access the object part to display the data using EJS. I have failed to reach the object data.
My Schema
let Subject = mongoose.Schema({
name:[],
crh:[]
});
let Program = mongoose.Schema({
name: String,
semester: Number,
subject:[Subject]
});
let School = mongoose.Schema({
name:{
type: String,
},
program:[Program]
})
POST METHOD TO ACCESS THE DATE FROM THE DB
router.post('/view',(req,res) =>{
let school = req.body.school;
let semester = req.body.semester;
let program = req.body.program;
All.find({name:school,"program.name":program,"program.semester":semester},(err,record) =>{
if(err) throw err;
if(!record){
req.flash("error","We couldn't find any relevant document! ");
res.redirect('/admin/view');
}
if(record){
console.log(record);
res.render("./admin/viewSub",{find:record});
}
})
})
Consoled data! How do i access the data of the object from ejs. I want to display the data inside the object in table. I just want to know how to access it, when i try to use "." to reach the points; i am unable to reach the data.
[ { program: [ [Object] ],
_id: 5a9045474b530750a4e93338,
name: 'sose',
__v: 0 } ]
Try this.
<ul>
<li><%= find.name %></li>
</ul>
<ul>
<%for (var prog in find.program){%> //to fetch data from array of array
<li><%= prog.name %></li>
<li><%= prog.semester %></li>
<ul>
<% for (var sub in prog.subject){%>
<li><%= sub %></li>
<%}%>
</ul>
<%}%>
</ul>
Related
I can retrieve the api data and console.log it and the for loop is displaying each card div element correctly but I cannot get the details to display for each item.
plant.js controller:
exports.postFindPlant = async (req, res) => {
const plantName = req.body.searchPlant;
const key = process.env.API_KEY;
const urlAPI = `https://trefle.io/api/v1/plants/search?token=${key}&q=${plantName}`;
try {
const response = await fetch(urlAPI);
const data = await response.json();
if (data.meta.total === 0) {
console.log('nada');
} else {
console.log(data.meta.total);
let plants = JSON.stringify(data);
res.render('plants', {
plants: plants,
pageTitle: 'Plants',
path: '/plants',
hasPlants: plants.length > 0
});
}
} catch (err) {
console.log(err);
}
};
plants.ejs:
<% for(var i=0; i < plants.length; i++) { %>
<div class="col s12 m4">
<div class="card">
<div class="card-image waves-effect waves-block waves-light">
<img class="activator" src="<%= plants[i].image_url %>">
</div>
<div class="card-content">
<span class="card-title activator grey-text text-darken-4"><%= plants[i].common_name %><i class="material-icons right">MORE</i></span>
</div>
<div class="card-reveal">
<span class="card-title grey-text text-darken-4"><%= plants[i].common_name %><i class="material-icons right">CLOSE</i></span>
<p><%= plants[i].scientific_name %></p>
<p>Plant Details</p>
</div>
</div>
</div>
<% } %>
In your Node.js code, you get the data from API with:
const data = await response.json();
Usually, some data returned from an API contains much information with keys, so it could be an Object. (I guessed, but confirmed in comments)
And then, if you want to access any info from an Object, you have to refer the value by it's key. For example:
> const person = { name: "Alan", age: 20 }
undefined
> person.name
'Alan'
> person.age
20
But if it's a object which contains an Array, and you want to access the Array's data, you can use Array index after refer the Array with it's key in the Object.
> const person = { name: "Alan", age: 20 }
undefined
> const person2 = { name: "Alice", age: 18 }
undefined
> const people = { type: "Human", data: [person, person2] }
undefined
> people
{
type: 'Human',
data: [ { name: 'Alan', age: 20 }, { name: 'Alice', age: 18 } ]
}
>
For example, how to get Alice in my code above?
> people.data
[ { name: 'Alan', age: 20 }, { name: 'Alice', age: 18 } ]
> people.data[1]
{ name: 'Alice', age: 18 }
> people.data[1].name
'Alice'
>
In your case, you parse the Object to JSON, and passed it into your Ejs code. It's still an Object, so I assume you know how to refer the values you want with correct keys in plants.ejs, and the things you need is only plants.data. Then, just change this line of your plant.js controller below:
let plants = JSON.stringify(data);
To something like:
let plants = JSON.stringify(data).data;
What makes the different? Take a look again to my examples above, this refer to people.data, which is an Array of Objects, instead of an Object which contains an Array of Objects.
So hope you have fully understand what is the problem, and how to solve it.
I'm trying to do "Orders page" that has a list of orders in a single page, but it should have seperate sections. One is for "Already made" and the other is for "Pending". It has a simple database with a field "isDone" that is either true or false. So as I imagine, if it is true, then it should appear on "Already made" section, but the problem is, that if statment doesn't work for some reason in .ejs.
<body class="container">
<main>
<div class="jumbotron">
<h1>Pending</h1>
</div>
<% orders_list.forEach(function(order){ %>
<% if(order.isDone == false) { %>
<div>
<h3><a href='<%= order.url %>'><%= order.name %></a> - <%= order.price %> euru</h3>
<hr>
</div>
<% } %>
<% }) %>
<div class="jumbotron">
<h1>Already made</h1>
</div>
<% orders_list.forEach(function(order){ %>
<% if(order.isDone == true) { %>
<div>
<h3><a href='<%= order.url %>'><%= order.name %></a> - <%= order.price %> euru</h3>
<hr>
</div>
<% } %>
<% }) %>
</main>
</body>
var express = require('express');
var router = express.Router();
var Order = require('../models/order');
router.get('/orders', function(req, res){
Order.find({})
.exec(function(err, list_orders){
if (err) {return next(err)};
// If Successful
res.render('../views/pages/index', {orders_list : list_orders});
});
});
module.exports = router;
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var OrderSchema = new Schema(
{
isDone: {type: Boolean, required: true},
name: {type: String, required: true},
quantity: {type: Number, required: true},
price: {type: Number, required: true},
phone: {type: Number},
});
OrderSchema
.virtual('url')
.get(function(){
return '/order/' + this._id;
});
module.exports = mongoose.model ('Order', OrderSchema);
I expect 'isDone' == true orders to go to 'Already made' section, and 'isDone' == false orders should go to the 'Pending' section. But not even single item appears. Database is connected successfully, if there are no if statments then orders appear on the page.
In your if condition you have quote your true value because ejs file is taking it as a value instead of a boolean value , so quote your true like this and it will work fine.
<% if(orders_list[i].isDone == 'true'){ %>
<div>
<h3><a href='<%= orders_list[i].url %>'><%= orders_list[i].name %></a> - <%= orders_list[i].price %> euru</h3>
<hr>
</div>
<% } %>
I have already added data to mongodb. I am using mongoose. I want to get data from mongodb database and display that in ejs page. I have searched a lot in the internet but I am getting errors while trying those. I do not understand what the error is. This is what I recently tried.
Mongoose schema
var mongoose = require("mongoose");
var Schema = mongoose.Schema;
var UserSchema = new Schema({
username:String,
_id:String,
dateOfBirth:Date,
telephoneNo:Number,
address:String,
email:String,
fb_Id:String,
jobTitle:String,
password:String
});
module.exports=mongoose.model('User',UserSchema);
Where I get data from mongodb
router.get('/', function(req, res){
user.find({}, function(err, profile){
res.render('AdminDatabase', { profile : profile});
});
});
Where I display in the ejs page
<div>
<ul>
<% for(var i=0; i<profile.length; i++) {%>
<li><%= profile[i].username %></li>
<li><%= profile[i]._id %></li>
<li><%= profile[i].dateOfBirth %></li>
<li><%= profile[i].telephoneNo %></li>
<li><%= profile[i].address %></li>
<li><%= profile[i].email %></li>
<li><%= profile[i].fb_Id %></li>
<li><%= profile[i].jobTitle %></li>
<% } %>
</ul>
</div>
But When I refresh the AdminDatabase page I get the error saying
ReferenceError: E:/Software project/Project/myProject/views/AdminDatabase.ejs:67
profile is not defined
Doesn't 'User' get turned into 'users', so the find code should look like
users.find({}...
..?
a user has fields in mongoose which will get updated if the user decided to update.
Here's the user schema
var User = Schema({
education: [{ type: String}],
});
So basically a user has fields that they could update or add, for example a user can add additional education and skills information using a form.
How do I properly do it in ejs and route?
my attempt in the route.js
router.post('/update-resume', function(req, res) {
User.findById(req.user._id, function(err, foundUser) {
// This part how do I update ?
if (req.body.education) foundUser.resume.education.push(req.body.education);
foundUser.save();
});
});
The value keeps pushing, i want to , I know that it is obvious that I'm pushing the data to the field, but how do I update it properly?
Form.ejs
<div class="form-group">
<label for="education">Education:</label>
<% for(var i = 0; i < user.resume.education.length; i++) { %>
<input type="text" class="form-control" name="education" id="education" value="<%= user.resume.education[i] %>">
<% } %>
</div>
Is it true that I need to for loop each field? if I want to update the specific data?
1st option:
Depending on how you use the application, you might not even care about updating - you could just delete the previous educations and save new ones instead.
2nd option:
To properly update you really need some kind of an ID that you can refer to when updating, right?
You'll still need to use your for loop, you just need to insert the id hidden field.
To do that you will need to pass an object and not an only-string value. I have made my object array look like this:
var education = [
{content:'Education 1',id:1},
{content:'Education 2',id:3},
{content:'Education 3',id:5},
{content:'Education 4',id:2},
];
Then you can do something like that:
<% for(var i = 0; i < education.length; i++) { %>
<input type="hidden" type="hidden" name="education_id" value="<%= education[i].id %>"/>
<input type="text" class="form-control" name="education" id="education" value="<%= education[i].content %>">
<% } %>
Array will always get passed the way you have sent it to the server. In my case, I'll get this (you can see that everything's in the order that it should be):
{education_id: [ '1', '3', '5', '2' ],
education: [ 'Education 1', 'Education 2', 'Education 3', 'Education 4' ] }
Now, let's look at the POST backend, you will need to tie everything back to an object (you don't really need to, but you can and probably should for the sake of sanity):
var education_i;
var education_req = [];
for(education_i=0;education_i<req.body.education.length;education_i++) {
console.log(req.body.education[education_i]);
education_req.push({
content:req.body.education[education_i],
id:req.body.education_id[education_i]
});
}
A few more notes:
You HAVE TO check for the user of every education record. You don't want to let anyone mess with the IDs and ruin someone else's profile.
You should probably save the array length variable separately, outside of the loops as it might cause performance issues on very large arrays because the length is parsed on every loop iteration.
This is the way I would do it:
The model:
var User = new Schema({
education: [{ content: String }]
});
The EJS/HTML:
<form id="education">
<% user.education.forEach(function(item) { %>
<input type="text" data-id="<%= item.id %>" value="<%= item.content %>" />
<% }); %>
<button type="submit">Save</button>
</form>
The client side javascript (JQuery):
$('#education').on('submit', function(e) {
e.preventDefault();
var data = [];
$(this)
.find('input')
.each(function() {
var $this = $(this);
// Collect the data with the id and value
data.push({
id: $this.data('id'),
value: $this.val()
});
});
$.ajax({
url: '/update-resume',
type: 'post',
data: { data: JSON.stringify(data) }
})
.done(function(data) {
if (data.success) {
// Lazy: refresh window
window.location.reload();
}
})
.fail(function() {
// Show an error or something fancy
});
});
The above javascript will read the data-ids from the input and the values and put them into an array of education objects. It will then stringify the object add and the string to the key 'data'. This means that you can pull the string in the route from req.body.data and parse it.
The server side javascript/in the route:
router.post('/update-resume', function(req, res, next) {
User.findById(req.user._id, function(err, user) {
var parsed = JSON.parse(req.body.data);
// update and remove
var results = user
.education
.filter(function(item) {
return parsed.some(function(input) {
return input.id === item.id;
});
})
.map(function(item) {
var related = getRelated(item.id, parsed);
return { content: related.value };
});
// Add new items
user.education = results
.concat(parsed.reduce(function(prev, curr) {
if (!getRelated(curr.id, results)) {
prev.push({ content: curr.value });
}
return prev;
}, []));
user.save(function(err) {
if (err) return next(err);
res.json({ success: true });
});
});
});
Get related helper:
var getRelated = function(id, arr) {
for (var i = 0; i < arr.length; i++) {
if (String(arr[i].id) === String(id)) return arr[i];
}
};
Mongoose will automatically give your education array items an id. The above will allow you to be able to add, remove and update existing education items on the page.
I am trying to display my mongodb data in a bootstrap template.
api.js
var Software = require('../models/dbSoftware.js');
exports.show = (function(req, res) {
Software.find({Publisher: req.params.format}, function(error, softwares) {
res.render('searchpage', { searchText: req.params.format, softwares: softwares});
})
});
Software Schema:
var mongoose = require('mongoose');
var softwareSchema = new mongoose.Schema({
SoftwareName: String
, Size: String
, Publisher: String
, Product: String
, Version: String
, Language: String
, License_Type: String
, Description: String
, License_Key: String
});
module.exports = mongoose.model('Software', softwareSchema);
searchpage.ejs
<td><%= softwares.Product %></td>
This returns undefined value. Any softwares.* returns 'undefined'.
When I edit searchpage.ejs to:
<td><%= softwares%></td>
The output is:
{ License_Key: 'computing', Description: 'Licensed', License_Type: 'English', Language: 'UNKNOWN', Product: 'Test Test', Publisher: 'Test', Size: '231.6MB', SoftwareName: 'Test.zip', _id: 5252c407d9b28d1e4c000001, __v: 0 }
//which is correct
When using .find(), softwares will be an Array for all successful (error == null) queries, regardless of the number of documents found:
<%= softwares.length %>
<%= softwares[0].Product %>
If you only want a single document, you'll want to use .findOne() instead:
Software.findOne({Publisher: req.params.format}, function(error, softwares) {
// ...
});
<% if (softwares != null) { %>
<%= softwares.Product %>
<% } %>
Or, you can iterate over softwares:
<% softwares.forEach(function (software) { %>
<%= software.Product %>
<% }) %>