Updating $scope after $HTTP.post - node.js

new at this.
I have 2 div's;
When I use one to post new value into the server, the post action works fine.
How do ensure this post updates the scope in the other div? (to update the div with the new entry using ng-repeat)
The HTTP.post action seems to be working as the data appears on refresh.
I have tried $scope.apply() but it doesn't appear to be working.
// this is the controller to get the data from the server
app.controller('projectsController',
function projectsController($scope, projectsFactory){
$scope.projects = projectsFactory.query();
});
and the factory to get the data from server
app.factory('projectsFactory',
function($resource,localStorage, $rootScope, $http){
return $resource('/api/project:id', {id: '#id'});
});
This is the controller to take the user input and post to back to the server
app.controller('projectEditController', function($scope, projectEdit){
$scope.projectEdit = projectEdit;
});
And the service to post the data to the server
app.service('projectEdit',
function projectEdit(localStorage,$rootScope, $http) {
var self = this;
self.add = function(newProject,projects) {
newProject = angular.copy(newProject);
var newProject = (JSON.stringify(newProject));
return $http.post('/api/project', newProject )
.then(function(response) {
newProject.id = response.data.id;
});
};
Which seems to be fine as it posts the data to the Sever fine.
What I am trying to figure out is how to get the
"$scope.projects = projectsFactory.query();" to update once the post operation is complete.
this will update the display in the HTML, which is the goal.
Hopefully this is an easy solve for a good developer, but I am stumped!
Thanks for your time.
Conor

Create 1 wrapper div, and set your controller to it with ng-controller.
Put your 2 divs in the wrapper div. Now the scope created by your controller is available in both divs, this is the easy way. When something updates data in that scope, and you have other things in the dom referencing that variable, then the dom will refresh like you want.
If you really want different controllers for each child div, that's fine, just be careful around inherited scopes. It really is much easier to just have one controller in a situation like this.
By the way, I saw that you mentioned scope.apply(). Be careful, apply() is a real javascript function, and NOT the one you want. You should call scope.$apply(), $apply is the angular function, and to avoid confusion, you could call scope.$digest instead.

Related

Find a class instance inside a function (JS) or how to write good self-documented code

Probably everyone was facing the issue when Postman documentation will be barely up-to-date with the code currently running in dev or production.
Almost every time the source of that problem is "a little change" or adding a new column into the database.
So I would like the code to be self-documented, starting from the validator.
There is the wrap-implementation over the JOI validator
class Validator {
_schema = {};
static TYPES = Joi;
setRule(field, rule){
this._schema[field] = rule;
}
validate(data){
let schema = Joi.object(this._schema);
try {
Joi.assert(data, schema, {abortEarly: false});
}
catch(error){
const message = error.details.map(detail => detail.message);
throw new ValidationError(message);
}
}
}
The controller uses this wrap just like that
const validator = new Validator();
validator.setRule('sts', Validator.TYPES.string());
validator.validate(body);
Every time the crucial code change happens, it usually affects the incoming body validation.
So the idea behind self-documentation is why not to use validator class as a source of the API documentation? We could get almost every piece of information about the endpoint using router + validator.
But how can you collect the data about that for every endpoint (especially, controller).
We should somehow get access to every instance of the Validator class inside each controller?
Or shall we just read the source file to get an information about the rules?
There are several implementations of Swagger-like docs, but they are all based on decorators code style, from which we are trying to get rid of.

Make data persist in form using mongodb node express

Hi I can connect to and store to mongodb using mlab but I can't get the data in the form to remain on refresh.
The form takes in user input from input-boxes.
Any help would be great.
Thanks
If being able to get the same form data for all the requests (no matter where they are made from)is what you want, then a possible workaround could be as follows:
1) Store the initial form data(probably empty) in the database, get the ObjectId and hard code it in your code, this way all the updates would be made to that specific MongoDB document only.
2) The form route (below one) should do nothing except for serving the file which has the form
app.get('/form1', function (req, res) {
res.sendFile(__dirname + '/public');
//record.find({"_id": ObjectId("MLAB ID")})......dont do this
});
3) There should be another route that sends form data
app.get('/getdata', function(req, res) {
record.find({"_id": ObjectId("MLAB ID")}, function(err, doc) {
res.send(doc)
})
});
4)The static file that you send to the client should have a javascript function such that it asks for the form data as soon as your window loads and then sets the value of input elements from that data recieved:
window.onload = function() {
//make a GET request to /getdata to get form data....store it in obj
//then set the input values
document.getElementById("yourchoice").value = obj.yourchoice;
//and set the value of other input fields ....in similar amnner
}
5) The POST request you make should update that specific document( findOneAndUpdate?? )
Disadvantage of this method:
For one operation we request a file from server and then another request to get form data, so two requests for one operation, since we cannot use both res.sendFile() and res.json() together...one way to get around this is to hide the form data as well in the HTML document using a template engine. More about this can easily be found. Anyways the above method does solve your purpose.
I hope I correctly understood the problem statement.
Happy coding!!
Edit:Although the above mentioned points are explainatory, I have written a sample snippet at : https://pastebin.com/AvgVyx7b
It works perfectly fine

Load Node 'code' from database while server running

I'm looking to build my project in a modular fashion so that API endpoints can be added while the server is added.
Adding routes dynamically I should be able to figure out, it's getting the recently uploaded server code running that I can't figure out.
My project has a 'class-per-endpoint' structure. An endpoint has a class attached that can run code and do this and that.
An endpoint can also be dependent on another endpoint/class, so what I want to be able to do is call the constructor of a dynamically added class and run the code efficiently on the server (without the API calling itself).
Example where "NewAdder" endpoint was just added. Rudimentary stuff, but I just hope it's clear what I'm trying to achieve. Basically trying to add to the server's code base dynamically.
modifier.ts
class Modifier {
constructor(initiatedBy) {
this.initBy = initiatedBy;
this.modifierValue = db.getValue("modifier", {user = this.initBy})
}
function modify(toModify) {
return toModify * this.modifierValue
}
}
newAdder.ts
class NewAdder {
constructor(initiatedBy) {
this.initBy = initiatedBy;
}
modifier = new Modifier(this.initBy);
function addAndModify(a,b) {
return modifier.modify(a + b)
}
}
router.ts (this would be dynamic in real life)
app.get('/newadder/addandmodify/', function(req, res){
adder = new NewAdder(req.params.user);
res.send(adder.addAndModify(req.params.first, req.params.second);
});
Hope I made some sense.
After some more research I suppose I could use http to get and then require the module dynamically.
The code will come from our own server, so it should be safe to run in the server.
But if anyone has any idea how to go about this, would be much appreciated.

iterative render with node and express

New to node and async and still struggling with concepts.
Trying to use express/handlebars render with a callback to iteratively build an html body with content from an array. End goal is to send a response with a number of emails each one individually rendered using a view.hbs.
Got this far but realised it was never going to work. res.render can't pass my html variable back in the callback and res.send would run before the renders have completed???
function buildRes (req, res, email) {
var html = '';
Object.keys(email).forEach(function (i) {
res.render('emailPanel', {subject: email[i].subject, body: email[i].body},
function(err, renOut) {
if err throw err;
html=html+renOut;
}
)
})
res.send(html);
}
Any suggestions on how I should be approaching this problem?
Started out trying to use handlebars #each helper to do the iteration but all of the examples show a simple list whereas in my case there a multiple array parameters to be passed to the render.
I'm still not sure what you're trying to accomplish with this, but one is for sure, I think it's better for you to do all looping inside your view by passing the entire array (filtered) with res.render to your view. Also note that you can respond only once per request.

follow a link without using window.location

I hope you are all well!
A question for an app that uses Backbone.js and node.js.
I'm in a situation where I want to create a model, and then automatically go to a different uri that is constructed using the newly created model :
MessageView = Backbone.View.extend({
events : {
'click #button' : 'go here'
}
go here : function(model) {
var message = new Message({model : model)};
var id = message.get('id');
// go to uri '/messages/id'
Now I have set up my app using Express, and so I would like to have a real GET request to the server here invoking the data from the newly created model. So I would like to load the page and not just change the view.
One way to do this (I think) would be to just have
window.location = 'messages/'+id;
as the last line above, but I seem to have the impression this is not good practice for Backbone in general.
Otherwise, could just create the message model inside of the render method, and then write its id directly into the href of the button when the view is rendered, but this also seems messy :
render : function() {
var message = new Message({model : model)};
var id = message.get('id');
$('a #button').attr('href', '/messages/'+id);
}
Any ideas on how I could set this up in a more elegant way? Thanks in advance!
Are you sure you want to actually change the browser page to a new window location? Doing that will cause all your javascript and everything else to have to reload. if you need to invoke a GET to the server to get the information for that model id, you just need to call fetch on a model with an id attribute.
From the little code you have here, this may be more along the lines of what you're trying to do:
MessageView = Backbone.View.extend({
events : {
'click #button' : 'go_here'
},
go_here : function(model) {
//myID is the id of your message you want to get from the server
//I'll leave it up to you on how you get the id of what you
//want from that button
//I'll also assume that you have a router setup somewhere
//to handle navigation
MyApp.MyRouter.navigate("messages/"+id, {trigger: true});
}
});
Then, in your router you'd have a route setup to watch for that:
routes: {
"messages/:id" : "showMessage"
}
And in your showMessage function:
showMessage: function(id) {
var message = new Message({id: id});
message.fetch({success: function(model) {
//render view of for the message to be shown
var messageView = new MessageView({model: model});
messageView.render();
});
}
When you create the view this way, it will be created with a model that already has all the data for your message in its attributes.

Resources