i'm new to angular, the journey is going quite well for now but it's also a bit challenging. Managed to fix some issues with the application like insert dating successfully in the server and so on, but trying to retrieve it inside a listview in angular seems like its not working. Please assist
I am struggling to create a listview using data from nodejs in mysql.
angular is not giving me the data.
index.html:
<div class="message-list">
<ul class="message-thread">
<li ng-repeat="ppPack in data.pp"
>
{{data.pp}} Posted by {{data.username}}
</li>
</ul>
</div>
controller
$scope.selectFeed = () => {
appService.getFeedList().then( (response) => {
$scope.$apply(() => {
let ppPack = {
fromUserId: document.querySelector(" from_user_id").value,
post: document.querySelector("#post").value
}
});
$scope.data.pp = response.pp;
}).catch( (error) => {
console.log(error);
alert('Unexpected Error, Try go back and redo somethings you did!.');
});
}
helper class
async getFeedList(){
try {
return await this.db.query(
`SELECT * FROM posts ORDER BY id ASC`,
[params.from_user_id,params.posts]
);
} catch (error) {
console.warn(error);
return null;
}
}
service class
getFeedList() {
return new Promise((resolve, reject) => {
this.httpCall({
url: '/getPosts',
'posts': $scope.data.pp,
'from_user_id': $scope.data.username
}).then((response) => {
resolve(response);
}).catch((error) => {
reject(error);
});
});
}
ng-repeat uses the value that you pass to the dom.
Starting with your helper class, you need to pass out the value in which you want to collect from the db, even though it seems like you query everything, giving params value to them will make it easier for you to understand the logic of the code, which means you query should be:
async getFeedList(posts, from_user_id)){
try {
return await this.db.query(
`SELECT * FROM posts ORDER BY id ASC`,
[params.from_user_id,params.posts]
);
} catch (error) {
console.warn(error);
return null;
}
}
And in your service class, also pass the params
getFeedList(posts, from_user_id) {
return new Promise((resolve, reject) => {
this.httpCall({
url: '/getPosts',
'posts': posts,
'from_user_id': from_user_id
}).then((response) => {
resolve(response);
}).catch((error) => {
reject(error);
});
});
}
and in your controller file should be outside other scopes since they won't be called out unless they requesting the service on their own like this:
appService.getFeedList()
.then((response) => {
$scope.$apply(() => {
$scope.postsData = response.postsData;
//output to see the array before commit to the scope
console.log(response);
});
})
.catch((error) => {
console.log(error);
alert("error code!.");
});
and then finally in your home.html you can call
<div class="list-group">
<ul class="list-group-item"
ng-repeat="post in postsData">
{{post.post}} Posted by <strong>{{post.from_user_id}} </strong</ul>
</div>
Some best practise tips from the official angular site:
Best Practice: If you are working with objects that have a unique identifier property, you should track by this identifier instead of the object instance, e.g. item in items track by item.id. Should you reload your data later, ngRepeat will not have to rebuild the DOM elements for items it has already rendered, even if the JavaScript objects in the collection have been substituted for new ones. For large collections, this significantly improves rendering performance.
Related
I have this piece of code inside a controller:
exports.getintroDetails = async (req, res) => {
try {
const details = await IntroModel.find();
return res.render("final", { details , user:req.user });
} catch (error) {
console.log(error.message);
}
};
This code, as expected, renders the final.ejs file with the given data.
But instead, I want to show raw html which we get after rendering final.ejs with the given data. Is there any way to store the raw html as a string instead of rendering it?
So, instead of:
return res.render("final", { details , user:req.user });
I want something like this:
return res.send( view-source( res.render("final", { details , user:req.user }) ) );
Is there any function like view-source() as described above?
According to docs you can provide a callback which will be executed with the rendered html. When the callback is provided the response won't automatically be made.
exports.getintroDetails = async (req, res) => {
try {
const details = await IntroModel.find();
return res.render("final", { details , user:req.user }, (err, html) => {
console.log('rendered html!', html)
// now, the response has to be made manually.
res.status(200).send(html)
});
} catch (error) {
console.log(error.message);
}
};
It is also possible, to render it using app.render() for only receiving the html.
From the docs
Think of app.render() as a utility function for generating rendered view strings. Internally res.render() uses app.render() to render views.
app.render('final', function (err, html) {
// ...
})
I have a simple api to communicate with my mobile app and i have some updates to do.
I want to make 2 updates at the same function (or th same route) but i dont know if its possible.
Here is the dboperation part:
async function updateCusto() {
try {
let pool = await sql.connect(config);
let updateCusto = await pool.request()
.input('input_parameter1', sql.Int, CodOS)
.input('input_parameter2', sql.Int, CodProduto)
.query("update osproduto set custounit=produto.precocusto, valorunitario=produto.precosugerido from OSProduto INNER JOIN Produto ON OSProduto.CodProduto = Produto.Codigo where codproduto=#input_parameter2 and codos=#input_parameter1")
.query("Update OSProduto set sub=qtde*valorunitario where codos=#input_parameter1") //the second one, doenst work
return updateCusto.recordsets;
}
catch (error) {
console.log(error);
throw error;
}
}
and here is the route part:
router.route("/updateCusto").post((request, response) => {
CodOS = request.body.CodOs;
CodProduto = request.body.CodProduto;
dboperations.updateCusto(CodOS, CodProduto).then(result => {
console.log(result);
response.json("Update ok!");
})
.catch(error => response.json({ error }))
})
How can i do this? Is there a way to run the 2 updates on the same operation? Or do i need to create another operation to use on the same route, after the first update is made (and if so, how can i do that?).
It's definitely possible, in fact I would do it as a transaction, this way if one of the queries fails a rollback would be made in order to preserve the state of your database.
Here are my suggestions:
Read about database transactions
Replace pure SQL with an ORM such as Sequelize or KnexJS, it will help you to prevent errors by making queries calling methods such as await OsProduto.update({ where: { id: 0 }}, newData);
I have two tables, one for users, one for todos and I use the following code to get all todos when the todo button is click. I want to use the same function to get all users.
index.html:
displayItems() {
fetch('/getItems',{
method: "get",
}).then(response => {
return response.json();
}).then((data)=>{
this.items = data
});
}
app.js:
app.get('/getItems', (req,res)=>{
db.getDB().collection(tableName).find({}).toArray((err,documents)=>{
if(err)
console.log(err);
else {
console.log(documents);
res.json(documents);
}
});
});
This works fine as long as I set tableName in app.js but then I have to write separate functions to get the items from the two different tables.
Is there a way to pass on the table name when I call fetch in my index.html depending on which button was clicked?
you send a parameter to your displayItems function and send it as a get paramater like
displayItems(tableName) {
fetch('/getItems?table='+tableName,{
method: "get",
}).then(response => {
return response.json();
}).then((data)=>{
this.items = data
});
}
and then you can access it on your server side using req.query like
app.get('/getItems', (req,res)=>{
db.getDB().collection(req.query.table).find({}).toArray((err,documents)=>{
if(err)
console.log(err);
else {
console.log(documents);
res.json(documents);
}
});
});
First I'm trying to get all projects from the database by given userId from URL. I'm doing it in ngOnInit(). Each project has it's field Languages which is a list of objects from another table Languages. One record in this table has a field named projectId by which I'm trying to get all languages for each project. I think I have a problem with receiving data asynchronously because projects are received properly but languages field in each Project object is null. What should I do?
ngOnInit() {
this.userId = this.route.snapshot.params['id'];
this.getAllProjectsByUserId(this.userId);
this.getLanguagesByProjectId();
}
getAllProjectsByUserId(id: number) { //receivng all projects for given userId
this.portfolioAppService.getAllProjectsByUserId(id).subscribe((data) => {
this.projectsList = data;
console.log(this.projectsList);
},
error => console.error(error)
);
}
getLanguagesByProjectId() { //receiving all languages for each project
this.projectsList.forEach(x => {
this.portfolioAppService.getLanguagesByProjectId(x.id).subscribe((data) => {
x.languages = data;
console.log(this.projectsList);
},
error => console.error(error)
);
});
}
Move the call to getLanguagesByProjectId() to when the projects have been received:
getAllProjectsByUserId(id: number) { //receiving all projects for given userId
this.portfolioAppService.getAllProjectsByUserId(id).subscribe((data) => {
this.projectsList = data;
console.log(this.projectsList);
this.getLanguagesByProjectId();
},
error => console.error(error)
);
}
As otherwise this.projectsList property has not the needed values yet.
I'm fetching data from a API that returns a JSON object:
fetch("api.php")
.then(function(response) {
console.log("Status: " + response.status);
if (response.ok) {
return response.json();
} else {
throw Error(response.status);
}
}).then(function(json) {
json.forEach(function(item) {
// 'datas' contains the items extracted from the JSON response
datas.add(item);
});
}).catch(function(err) {
console.log(error);
});
If I want to query the data with jinqJs I can change the code slightly to:
}).then(function(json) {
var result = new jinqJs()
.from(json)
.where('start_date = 2017-03-10')
.select();
result.forEach(function(item) {
datas.add(item);
});
}).catch(function(err) {
and it works really well.
My question is: due to the fact that by fetching only once the API I actually download ALL the needed data how can I query it 'outside' the forEach fetch?. I mean: I already have all the data with one call to the API, I can easily do queries on the data with jinqJs why should I call the API every time I need to query it? Is it possible to query datas once the forEach has added all the items?
For example, outside the forEach (notice the .from(datas) instead of .from(json)) I could do:
var result = new jinqJs()
.from(datas)
.where('start_date = 2017-03-10')
.select();
and get the same result.
As I'm trying to build a mobile app, this would be handy because I would bind the above code to specific buttons and query the data accordingly and I would connect to the internet only the first time the app is started rather than every time a query is needed.
Assign the "JSON" promise to a variable
var something = fetch("api.php")
.then(function(response) {
console.log("Status: " + response.status);
if (response.ok) {
return response.json();
} else {
throw Error(response.status);
}
});
Now you can use something as many times as you like
something
.then(json => console.log(json))
.catch ...
something.then(json => new jinqJs()
.from(json)
.where('start_date = 2017-03-10')
.select()
.forEach(function(item) {
datas.add(item);
});
).catch ....