I am attempting to get data returned from a database rendered in my web page, but have been unable to do so. I am using using ejs as my templating engine, bookshelf(orm) and express as my node framework.
My model looks like this:
'use strict';
var bookshelf = require('../bookshelf');
var Contact = bookshelf.Model.extend({
tableName: 'contacts',
});
module.exports = Contact;
My controller looks like this:
function list(req, res, next) {
new Contact().fetchAll()
.then(function(contacts) {
var contacts = contacts.toJSON();
var contacts = JSON.stringify(contacts);
console.log(contacts)
res.render('contacts', {
contacts: contacts
});
}).catch(function(error) {
console.log(error);
res.send('An error occured');
})
}
And my template looks like this:
<% include partials/header %>
<h1><%= test %></h1>
<ul>
<% contacts.forEach(function(contacts){ %>
<li><%= contacts.firstName%></li>
<% }) %>
</ul>
<% include partials/footer %>
What I wish to happen is for that for each contact their first name shold be displayed on the page. However nothing is displayed even though the console.log statement (in the controller) displays this in the console:
[{"id":1,"firstName":"tom","lastName":"jones","emailAddress":"joney#test.com"},{"id":2,"firstName":"don","lastName":"jon","emailAddress":"don#test.com"}]
So data is returned from the DB, just not rendered in my view. Can anybody help me out with what I am doing wrong?
Method 2:
Below is a new way I have tried to do this. However this just results in the JSON been displayed on my web page.
function list(req, res) {
Contact.fetchAll()
.then(contacts => res.json({
contacts
})
).catch(function(error){
console.log(error);
res.send('An error occured');
})
}
It seems that bookshelf orm return a collection object, and you can use .toArray() method to transform it to an array and then pass it to your view without calling JSON.stringify, Try this:
function list(req, res, next) {
new Contact().fetchAll()
.then(function(contacts) {
res.render('contacts', {
contacts: contacts.toArray()
});
}).catch(function(error) {
console.log(error);
res.send('An error occured');
});
}
You seem to be double toJSON()-ing your contacts collection. There is no need to call toJSON() explicitly if you're going to call JSON.stringify() afterwards, since that method already calls .toJSON() on its own.
However, that's not the problem here. The real problem is that you're stringifying the collection, meaning it's a string when used on the template, so it's not possible to treat it like an object.
If you just remove the JSON.stringify(contacts); part it should work fine.
Related
Good day,
I've been trying to learn a bit of angular and nodejs. I found a tutorial on a realtime chat app and made some few adjustment to some function of the code. But the one aspect that I cannot seem to get right is the ability for the user to post to a feed. The login process works, the user is already logged in but the user can't post. I would also like to be able to get all they data i insert from all the user to show up like a normal feedview will. Please assist.
Here are my files:
FROM MY CONTROLLER HERE IS THE CODE WHEN THE BUTTON IS PRESSED
$scope.postDatatoDd = () => {
appService.httpCall({
url: '/posts',
params: {
'posts': $scope.data.info,
'from_user_id': $scope.data.username
}
})
.then((response) => {
// $scope.$apply();
})
.catch((error) => {
alert(error.message);
});
}
and here is my route file:
this.app.post('/posts', async(request,response) => {
const reqResponse = {}
const data = {
posts : request.body.postDatatoDd,
from_user_id: request.body.username
};
if (data.posts === ''){
reqResponse.error = true;
reqResponse.message = `error, input`;
response.status(412).json(reqResponse);
} else {
const result = await helper.insertFeed(data);
if (result === null) {
reqResponse.error = true;
reqResponse.message = `they was an error.`;
response.status(417).json(reqResponse);
} else {
reqResponse.error = false;
reqResponse.userId = result.insertId;
reqResponse.message = `posted succesfully`;
response.status(200).json(reqResponse);
}
}});
and in my helper file there is this function to insert data:
async insertFeed(params){
try {
return await this.db.query(
`INSERT INTO posts (from_user_id,posts) values (?,?)`,
[params.from_user_id,params.postDatatoDd]
);
} catch (error) {
console.warn(error);
return null;
}
}
On the client side here is the button with :
<label for="postDatatoDd">Post</label>
<input type="text" id="postDatatoDd"
ng-model="data.postDatatoDd"
class="feed form-control"
placeholder="post your data here?"
/>
<button ng-click="postDatatoDd()" class="btn btn-primary">Post</button>
</div>
--- EDIT 1---
Data is being inserted now, but it is receiving the values as (NULL, NULL).
--- EDIT 2 ---
After closely looking at the code and fixing some naming variables the code works fine, the data is being inserted in mysql as it should.
Other than a lot of typos when it comes to the variables reference. The code seem to be fine.
Assuming that you using appservice class somewhere in your code and its functioned, then everything else will work.
You are getting the (NULL, NULL) because you are parsing parameters that are not being properly parsed out to your helper file, please close attention to that.
appService
.httpCall({
url: "/posts",
params: {
posts: $scope.data.postbuzz,
from_user_id: $scope.data.username,
},
})
.then((response) => {
$scope.$apply();
})
.catch((error) => {
alert(error.message);
});
make sure that the data that you calling from this above function is similar to $scope parameter you passing in your route file that your requesting:
const data = {
posts : request.body.posts,
from_user_id: request.body.from_user_id}
and in your database helper class you running:
`INSERT INTO posts (from_user_id,post) values (?,?)`,
[params.from_user_id,params.posts]
Hope this was helpful
You seem to have an understand already. your question may help a lot more people in the future.
params should be as following, since the data object has properties from_user_id and posts
`INSERT INTO posts (from_user_id,posts) values (?, ?)`,
[params.from_user_id,params.posts]
Might be useful https://www.w3schools.com/nodejs/nodejs_mysql_insert.asp
--- EDIT 2 ---
After closely looking at the code and fixing some naming variables the code works fine, the data is being inserted in mysql as it should.
If you are new to Angular you can use the code as reference.
I am routing from one page to another, and am trying to display the contents of the database query on the next page in my user display.js
exports.list = (req, res) => {
console.log("we have activated userdisplay.js\n");
db.query('SELECT * FROM User', (error, results, fields) =>
{
console.log('we did a query');
if(error)
{
console.log("Error: ",error);
res.send({
"code": 400,
"failed": "Error occurred"
});
} else {
console.log("Results: ",results);
/*res.send({
"code": 200,
"success": "Database successfully logged"
});*/
res.render('tempdisplay.html', {data: results});
}
});
}
So I have the data, but now I need to display it. I tried using handlebars to convert the data object sent by res.render() in the tempdisplay.html file to strings using
<script>
var user = [
{{#each data}}
{
email: '{{email}}',
fname: '{{fname}}',
lname: '{{lname}}',
pass: '{{pass}}'
}
{{/each}}
];
</script>
When I try to run this to convert them to strings it gives me a "Invalid regular expression: missing / in file" Error. This error only happens when this script is present. I have jquery and handlebars included in the file, and my other files work with the pathways/cdn. I don't really seem to understand how I would go about using handlebars to display the data. If I make another js file, I won't be able to see the data object returned to tempdisplay, but if I try to make a handlebars script in the html file it gives me syntax errors.
To display data on the client, the usual method is to insert it into a template on the server:
// fill tempdisplay.hbs with results, send to client
res.render('tempdisplay', {data: results});
An example of a template file tempdisplay.hbs is this:
<table>
<tbody>
{{#each data}}
<tr>
<td>{{this.fname}}</td>
<td>{{this.lname}}</td>
</tr>
{{/each}}
</tbody>
</table>
I’m new to web development in general and wonder why the the cursor method for mongoose only returns the first document in the collection and not all of them?
My goal is to pass these documents to a jade template.
I'm using MongoDB and Express
The code:
var array = [];
var stream = MyModel.find({}).cursor();
stream.on('data',function(task){
array.push(task)
});
stream.on('error', function(err){
//Handle error
});
stream.on('close', function(){
res.render('dashboard', { title: 'Dashboard', csrfToken: req.csrfToken(), array: array});
});
Since I'm new to this my "code-jargon" might not be spot on so i'll be happy to specify if necessary.
You can try something like
MyModel.find({},function(err,docs){
res.render('dashboard', { title: 'Dashboard', csrfToken: req.csrfToken(), array: docs});
});
according to mongoose doc, you can attach a callback to the query, so it will turn the cursor into an array of documents.
I have a sample code that goes like this:
Client Helper:
getUsername: function (userId) {
Meteor.call("getUsername", userId, function (err, result) {
if(!err) {
Session.set("setUsername", result);
else {
console.log(err);
}
});
return Session.get("setUsername");
}
Server
Meteor.methods({
"getUsername": function (userId) {
var x = Meteor.users.find({_id: userId}, {fields: {username:1}}).fetch()[0];
return x.username;
}
});
The result of this code is an infinite loop of username passing to the client. Is there a way to stop the loop and pass only the data that is needed on the client? I believe the reactivity is causing the data to loop infinitely and I am not sure how to stop it. I tried using "reactive":false on my query in the server but it does not work.
If you want to access username everywhere in client templates (so thats why you put it into session), I would not set it in template helper. I would set it on startup and get username from session in template helpers (without calling server method)
If you need username just in one template, so you want to return its value from your template helper, do not put it into session, just return it in your server method callback.
Based on your sample code, I assume, you have a set of posts and you are retrieving user name based on user id for each post. Then instead of doing it this way, you should use publish composite package to publish related users as well.
Meteor.publishComposite('getPosts', function (postIds) {
return [{
find: function() {
return Posts.find({ _id: { $in: postIds }});
// you can also do -> return Posts.find();
// or -> return Posts.find({ /* or what ever your selector is to get the posts you need*/ });
},
children: [{
find: function(post) {
return Meteor.users.find({
id: post.userId //or the correct field in your post document to get user id
}, {
fields: {
"profile": 1
}
});
}
}}
}]
});
This way your publication will take care of publishing related users along with posts. You don't need to use methods and call them each time.
Starting out with MEAN.io and they provide a sample "articles" model which is basically something like a blog post that comes with a title and body.
The example comes with an index.html file that displays a list of articles when you navigate to it. In this file, it calls a find method defined in the public controller as such
$scope.find = function() {
Articles.query(function(articles) {
$scope.articles = articles;
});
};
I see a server controller that defines the following method
/**
* List of Articles
*/
exports.all = function(req, res) {
Article.find().sort('-created').populate('user', 'name username').exec(function(err, articles) {
if (err) {
return res.json(500, {
error: 'Cannot list the articles'
});
}
res.json(articles);
});
};
When I add a constraint to the find method in the server controller, I can effectively define where filters to the query, which is reflected in the view.
Is there some connection between these two controllers that is implicitly handled by the framework? I can't find any information about how all of these are related.
imho no.
if there was a filtering connection, code have to be like this
/**
* List of Articles
* use GET /api/v1/articles?published=true to filter
*/
exports.all = function(req, res) {
Article
.find(req.query) //this is filtering!
.sort('-created')
.populate('user', 'name username')
.exec(function(err, articles) {
if (err) {
return res.json(500, {
error: 'Cannot list the articles'
});
}
res.json(articles);
});
};