I am learning how to display mongodb data in html, but the code cannot work when I learn from network. I want to create the button to change the page to view data, and I don't know how to render data to ejs.
I try to find some method to solve the problem in network, but most of them are not the problem which I get.
code of find data
app.post('/viewdata', function (req, res) {
res.render('staffDisplay');
try{
MongoClient.connect(uri, function(err, client) {
if(err) {
console.log('Error occurred while connecting to MongoDB Atlas...\n',err);
}else{
var game=[];
var collection = client.db("GameDB").collection("Game");
var result = collection.find();
result.forEach(function(error,result){
if(error){
console.log(error);
}else{
if(result != null){
game.push(result);
}else{
console.log(game);
res.render('views/staffDisplay.ejs',{game:result})
}
}
})
console.log('show');
client.close();
}
});
}catch(ex){
throw new Error(ex.toString());
}
});
display.ejs
//skip the html code
<ul>
<% for(var i=0;i<=game.length;i++) {%>
<li><%=game[i].gName%></li>
<li><%=game[i].gDesc%></li>
<li><%=game[i].gDate%></li>
<%}%>
</ul>
the result is display 'game is not define', how can I do?
Can you try to remove this res.render('staffDisplay'); on the first part then replace res.render('views/staffDisplay.ejs',{game:result}) with this res.render('staffDisplay.ejs',{game:result})
Related
I have a router which returns a specefic user's information based on the unique Object_id from MongoDB. This works fine, and I get the correct results, but they are returned on a "blank" page as a JSON object. I want to simply fetch the result and render them on my ejs page. Here are my route:
//Here are my router.js:
router.get('/user/get:id', function (req, res) {
MongoClient.connect(DBUri,{useUnifiedTopology: true }, function (err, db) {
let dbo = db.db(DBName);
const query = {_id: objectId(req.params.id)}
dbo.collection("Users").find(query).toArray(function(err, resultTasks) {
if (err) throw err;
res.send(resultTasks)
db.close();
});
});
});
//Here are my file.ejs:
<div class="card" v-for="post in filteredList">
<a v-bind:href="'/user/get' + post.id">{{ post.name }}</a>
</div>
Im still new so I know this is properly basic. I guess I have to change the res.send to something else, but now sure how.
You need to loop over resultTasks in your ejs template, something like:
<% resultTasks.forEach((post) => { %>
<div class="card" v-for="post in filteredList">
<a v-bind:href="/user/get/<%= post.id %>"><%= post.name %></a>
</div>
<%}); %>
Also, you probably need to change send in your endpoint with
dbo.collection("Users").find(query).toArray(function(err, resultTasks) {
if (err) throw err;
db.close();
res.render('<path of your ejs file>', {
resultTasks: resultTasks, // pass data from the server to the view
});
});
I am new to Apostrophe and trying to create a contact us form with file attachment in Apostrophe by following the tutorial.
https://apostrophecms.org/docs/tutorials/intermediate/forms.html
I have also created the attachment field in my index.js and it works fine from the admin panel.
Now, I am trying to create my own html for the form with file submission.
// in lib/modules/contact-form-widgets/public/js/always.js
apos.define('contact-form-widgets', {
extend: 'apostrophe-widgets',
construct: function(self, options) {
self.play = function($widget, data, options) {
var $form = $widget.find('[data-contact-form]');
var schema = self.options.submitSchema;
var piece = _.cloneDeep(self.options.piece);
return apos.schemas.populate($form, self.schema, self.piece, function(err) {
if (err) {
alert('A problem occurred setting up the contact form.');
return;
}
enableSubmit();
});
function enableSubmit() {
$form.on('submit', function() {
submit();
//I can access file here
// console.log($form.find('file'))
return false;
});
}
function submit() {
return async.series([
convert,
submitToServer
], function(err) {
if (err) {
alert('Something was not right. Please review your submission.');
} else {
// Replace the form with its formerly hidden thank you message
$form.replaceWith($form.find('[data-thank-you]'));
}
});
function convert(callback) {
return apos.schemas.convert($form, schema, piece, callback);
}
function submitToServer(callback) {
return self.api('submit', piece, function(data) {
alert("I AM AT SUBMIT API ")
if (data.status === 'ok') {
// All is well
return callback(null);
}
// API-level error
return callback('error');
}, function(err) {
// Transport-level error
alert("I AM HERE AT API ERROR")
return callback(err);
});
}
}
};
}
});
//and my widget.html is
<div class="form-group">
<input name="custom-file" type="file">
</div>
When I run this I get following errors
user.js:310 Uncaught TypeError: Cannot read property 'serialize' of undefined
at Object.self.getArea (user.js:310)
at Object.self.getSingleton (user.js:303)
at Object.convert (user.js:686)
at user.js:164
at async.js:181
at iterate (async.js:262)
at async.js:274
at async.js:44
at setImmediate.js:27
at runIfPresent (setImmediate.js:46)
My question is, how do I handle file submission? Is there any better approach for this?
This is much easier to do using the apostrophe-pieces-submit-widgets module, which allows you to define a schema for what the user can submit. You can include a field of type attachment in that, and this is demonstrated in the README.
I made a drop-down which gets its links from some data I get with mongoose.
However its not persistent. With the exact same code, I don't always get my data for the links.
(It's like this for all my things actually, but my drop-downs are simple)
My drop-down (made with EJS and bootstrap)
<div class="dropdown-menu" aria-labelledby="navdrop">
<% schools.forEach((school) => { %>
<%= school.name %>
<% }); %>
</div>
(Sorry for the shitty format above, the editor wouldnt let me make it better).
This is my route for handling my index page.
server.get('/',
async function(req, res) {
let schools = await schoolService.getAll();
res.render('public assets/pages/index', {
page_title: "Langaming.dk - Index",
schools: schools
});
}
);
This is my schoolService.getAll();
"getAll": () => {
return new Promise(function(resolve, reject){
School.find({}, function (err, schools) {
if (err)
return reject(err)
else
return resolve(schools)
});
})
}
I will try and explain it a bit better. When I go onto my page, sometimes the links show up, and other times they don't. (Mostly they don't). It's the same code all the time.
The project is running express for route handling.
Why does this happen?
Might be that for some reason your database doesn't have documents (are you wiping out data between requests?) and it's not going to throw an error just because of it.
"getAll": () => {
return new Promise(function(resolve, reject){
School.find({}, function (err, schools) {
if (err)
return reject(err)
if (!schools) {
console.log('there are no documents');
return reject();
}
else
resolve(schools)
});
})
}
I have the following basic document in mongo:
connecting to: test
> db.car.find();
{ "_id" : ObjectId("5657c6acf4175001ccfd0ea8"), "make" : "VW" }
I am using express, mongodb native client (not mongoose) and ejs.
collection.find().toArray(function (err, result) {
if (err) {
console.log(err);
} else if (result.length) {
console.log('Found:', result);
mk = result;
console.log('mk = ', mk);
} else {
console.log('No document(s) found with defined "find" criteria!');
}
//Close connection
db.close();
});
}
});
Here is the render code:
// index page
app.get('/', function(req, res) {
res.render('pages/index', { make: result });
});
And i want to pass the data make: VW into my index.ejs file:
<h2>Cars:</h2>
<h3>My favorite make is <%= make %>
This should be real simple and straightforward but i just don't understand how to pass the "mk" variable (which i can console.log to the screen) to be rendered by the ejs view?
You should use the find method inside the route (or with a callback) to get the result and render it:
app.get('/', function(req, res) {
collection.find().toArray(function(err, result) {
if(err) {
console.log(err);
res.status('400').send({error: err});
} else if(result.length) {
console.log('Found:', result);
mk = result;
console.log('mk = ', mk);
res.render('pages/index', {make: mk});
} else {
console.log('No document(s) found with defined "find" criteria!');
res.status('400').send({error: 'No document(s) found'});
}
//Close connection
db.close();
});
});
Very simple, your are outputting an array of JSON objects
Here is one way to visualise it:
[{a:b},{a:b},{a:b},{a:b}];
If you want the first result it would be array[0].a
so you simply need to call it this way:
<%= make[0].(your database key here) =>
//example
<%= make[0].name =>
A more sensible way to get this done would be to iterate through the array and output only the result you want on the server side. If you send all your data to your client you might have security issues depending on what you send.
It should be simple, but you are defining mk just like this: mk = result So because you want to pass a variable to an ejs file you need
"var mk = result"
Have a good day, Ben.
Im trying to implement some way to stop my code to redirect me before I get the response from the omdb api I am using.
My function for making a search for a movie and saving all titles in a session looks like this:
app.post('/search', isLoggedIn, function(req, res) {
function getMovies(arg, callback){
console.log('In getMovies');
console.log('searching for '+arg);
omdb.search(arg, function(err, movies) {
if(err) {
return console.error(err);
}
if(movies.length < 1) {
return console.log('No movies were found!');
}
var titles = [];
movies.forEach(function(movie) {
// If title exists in array, dont push.
if(titles.indexOf(movie.title) > -1){
console.log('skipped duplicate title of '+movie.title);
}
else{
titles.push(movie.title);
console.log('pushed '+movie.title);
}
});
// Saves the titles in a session
req.session.titles = titles;
console.log(req.session.titles);
});
// Done with the API request
callback();
}
var title = req.body.title;
getMovies(title, function() {
console.log('Done with API request, redirecting to GET SEARCH');
res.redirect('/search');
});
});
However I dont know if I implement callback in the right way, because I think there can be a problem with the api request actually executing before the callback, but not finishing before. And therefor the callback is working..
So I just want 2 things from this question. Does my callback work? And what can I do if a callback won't solve this problem?
Thankful for all answers in the right direction.
Add
callback();
To, like this
omdb.search(arg, function(err, movies) {
if (err) {
return console.error(err);
}
if (movies.length < 1) {
return console.log('No movies were found!');
}
var titles = [];
movies.forEach(function(movie) {
// If title exists in array, dont push.
if (titles.indexOf(movie.title) > -1) {
console.log('skipped duplicate title of ' + movie.title);
} else {
titles.push(movie.title);
console.log('pushed ' + movie.title);
}
});
// Saves the titles in a session
req.session.titles = titles;
callback();
});
omdb.search is asynchronous function that's why callback executed before omdb.search