Im using Angular with Node and would to send a response to the client-side controller from a GET request.
The line of code Im using to send the response seems not to be working when I use native Node as opposed to Express.js
Here is my angular controller:
app.controller('testCtrl', function($scope, $http) {
$http.get('/test').then(function(response){
$scope = response.data;
});
});
This is routed to essentially the following server script:
http.createServer(function onRequest(req, res){
if(req.method==='GET'){
var scope = 'this is the test scope';
res.json(scope); // TypeError: res.json is not a function
}
}).listen(port);
res.json() throws an error unless I use an express server
var app = express();
app.all('/*', function(req, res) {
if(req.method==='GET'){
var scope = 'this is the test scope';
res.json(scope); // OK!
}
}).listen(port);
I was pretty sure the json() function came with node. How do I send a response back to angular when using a native Node server?
res.json is not in the API for HTTP response.
The standard way would be to use res.write() (docs) and then res.end() (docs). But in your case, since you're not sending a lot of data you can use a shortcut and just use res.end() with a data parameter :)
Related
I can't manage to inject data from a Json file into my html.
I get a good response, I can log it into chrome console.log of my response
but i can't inject it in my html.
here is my angularJs code :
<p ng-bind-html="essaiJson.titre"></p>
var app = angular.module('monApp', ['ngSanitize']);
app.controller('monControl', function($scope, $http, $compile){
$scope.maVariable = "MEAN Stack";
$http.get('/JavaScript/mean.json')
.then(function(response){
$scope.essaiJson = response.data;
console.log($scope.essaiJson);
});
when I log $scope.essaiJson.titre I get a good response, but when I bind it there is nothing !
my node.js code :
var express = require('express'),
app = express(),
http = require('http').createServer(app);
app.get('/', function (req, res) {
res.sendFile(__dirname + '/app/ex11.html');
});
http.listen(8080);
use <p>{{essaiJson.titre}}</p>
instead of <p ng-bind-html="essaiJson.titre"></p>
ng-bind-html evaluates the expression and inserts the resulting HTML into the element in a secure way.
In your case, you just need to bind the json data into your html, which can be done using
<p>{{essaiJson}}</p>
Here is an example of what you are trying to acheive:
https://stackblitz.com/edit/angularjs-cuhtns
I am currently new to the MEAN stack and essentially I have a basic application.
I am running the node server on localhost so the Node.js serves the index page
var index = require('./routes/index');
app.use('/', index);
And the router looks like this:
var express = require('express');
var router = express.Router();
router.get('/', function(req, res, next) {
});
module.exports = router;
So nothing fancy, it's an empty router. First I'm trying to understand how this router is serving that HTML page? Shouldn't I have to do a render() or something?
My next question is, how do I take data from the Node.js and serve it to the initial GET request and use that data on the Angular side?
I know another method could be to send another GET request and use the response data and bind it to a scope variable. What I mean by this:
var app = angular.module('myApp');
app.controller('myController', function($scope, $http){
$scope.data = [''];
getData(); //Call getData to go to server and retrieve the data I want
function getData() {
$http
.get('/')
.success(function(data){
$scope.data = data;
});
});
}
});
Basically, from my point of view, there is 2 GET requests being made. When I go to localhost:3000/ and my HTML page is loaded and then when the controller is loaded in the HTML page (which is done through getData). Is there a way to reduce this to one GET request (preferably in the initial request)?
Take a look at this express docs page about templating engines
What you would do is give a template instead of html for your index file. First we need to tell our express app what rendering engine we want
app.set('view engine', 'ejs');
Now we want to define our index route, where the index route returns our html + data inserted in a particular way.
app.get('/', function (req, res) {
res.render('index', { allThemDatas: { username: 'pleb', password: 'password' } })
})
You could rewrite your index file to use a particular templating syntax. ejs is one that would make doing so pretty easy so we will go with that one. We just want to take our original index.html file and add the following into the head or where ever:
...
<head>
<script>
var userdata = <%= allThemDatas %>;
</script>
</head>
...
From here, you can either just use window.userdata, or a more testable angular way of doing this is to use angular constants instead.
angular
.module('userdata', [])
.constant("data", <%= allThemDatas %>)
As a completely other alternative, by using angular ui-router and using resolve's, you could fetch the data from the server using $http, and the resolve will inject the results of the $http request into your view's controller for you.
Your node router sets up a route, which your angular service method can make a GET request to.
So, to illustrate:
router.get('/', function(req, res, next) {
res.send("something");
});
This actually makes the GET request and collects the response, should you choose to do it. As illustrated above, you can send whatever response you want–in this case, the string "something." Think of it as an endpoint.
And in your angular service (not the controller, in my opinion), you could make a GET request:
app.service('DataService', function(DataService){
function getData() {
$http
.get('/')
.success(function(data){
$scope.data = data; // data will be "something"
});
});
}
});
This is actually making a request to that endpoint and providing your controller with the response. You may want to use this response in the view or do something with it.
Then, inject this service in your controller like so:
app.controller('MyController', ['DataService', function(DataService){
//...
DataService.getData().then(function(data){
// do something with data
});
I'm very new to AngualarJS and Node.js, and I have a problem with my $http.get method's success callback block not being executed. When the request fails, my error callback block works, but when it succeeds, nothing happens.
This is what I have in my server.js:
var express = require('express');
var app = express();
// This is for testing GET connection with server
app.get('/test', function (req, res) {
console.log("Got a GET request from my angular app");
res.send('Hello ANGULAR');
})
var server = app.listen(8081, function () {
var host = server.address().address
var port = server.address().port
console.log("Example app listening at http://%s:%s", host, port)
})
This is what I have in my app.js:
$http.get("http://localhost:8081/test")
.success (function (response) {
alert("GOT A RESPONSE");
})
.error (function() {
alert("SERVER GET TEST FAILED THO");
});
Does anyone know what I'm doing wrong?
Your server's app.get block is missing a response sending :
Try adding :
res.sendStatus(200);
or res.status(XXX).send(*object/string*);
at the end.
Here's the documentation : http://expressjs.com/en/4x/api.html#res
The angular and node.js code look fine. But there could be any number of problems between network, configuration, etc.
The best way to figure this out is to use Chrome Dev tools network panel. Click "Inspect" on your page or Command-ALT-i (Mac).
Click the "network" panel tab to see your request and the response received.
try this :
$http.get('http://localhost:8081/test').then(
function successCallback(response) {
console.log("ok")
},
function errorCallback(response) {
console.log("error") ;
}
);
According to the official documentation, don't use success :
Deprecation Notice
The $http legacy promise methods success and error have been deprecated. Use the standard then method instead. If $httpProvider.useLegacyPromiseExtensions is set to false then these methods will throw $http/legacy error.
Say I have this code in node.js:
app.post('/stuff', function(req, res){
res.send('hello world');
});
app.route('*').all(function(req,res,next){
res.write('Hello World');
});
There are 2 routes here - one is a catch-all for any request to the server and the other is what to do if a post request with a route of /stuff is sent.
Is it possible to pass a value local to the post request into route?
Intended Program flow: initial request to the server goes through route (which has controls not illustrated to ignore post requests) and the connection is left open, then a post request is sent from the initial request and is dealt with by app.post - can a value found within the closure of post be passed to the initial request that is still open?
I am trying to avoid using Global variables, and res.local only has a local scope. Also trying to keep clean so if I can use native express or node.js all the better. Much obliged for any help.
then a post request is sent from the initial request
Why don't you simply pull out the POST function and call it from both handlers, that way you don't need to send a seperate request from inside your app.
var postHandler = function(req, res) {
res.send('hello world');
// Just return whatever you want back to the calling function
return someValue;
};
// Set it as the handler for post.
app.post('/stuff', postHandler);
app.route('*').all(function(req,res,next){
// Call function.
var returnValue = postHandler(req, res);
res.write('Hello World');
});
app.route('*').all(function(req,res,next){
if (req.originalUrl === '/stuff') {
req.variable = 'some value';
return next();
};
res.write('Hello World');
});
app.post('/stuff', function(req, res){
var value = req.variable;
res.send('hello world');
});
You can try this code. Please take the order of app.all and app.post.
The second way, your can try app.locals http://www.expressjs.com.cn/4x/api.html#app.locals
The app.locals object is a JavaScript object, and its properties are
local variables within the application.
I am trying to build an application with backbone.js and express.js. I have an issue to return the values from express to backbone. I had the same problem with a simple Curl request (i could display req.params on the server side but impossible to get it on the client side, even using JSON.stringify() on it).
I did the same code with a simple echo json_ecode() in php and it works well...
Here is the code of a simple test on the server side:
var express = require("express");
var app = express();
app.get('/user/:id/:pass', function(req, res){
res.status(200);
res.send({"id": "1"});
});
On the client side, i don't get any of the success or error callaback...
var U1 = new User();
U1.fetch({
success: function(data) {
console.log('User fetched.');
},
error: function(model, error) {
console.log('user Error: '+error);
}
});
What is wrong with my answer on express.js ?
Thanks !
Ok i found the solution by adding res.header("Access-Control-Allow-Origin", "*"); in my express route.
As long as the User model sets it's url to the same /user/login/password then it should work, see: http://backbonejs.org/#Model-url Did you already create a url method on the User model?
I posted a couple articles on backbone.js and express ... http://www.pixelhandler.com/blog/2012/02/29/backbone-js-models-views-collections-to-present-api-data/ backbone example using API data from express app: http://pixelhandler.com/blog/2012/02/09/develop-a-restful-api-using-node-js-with-express-and-mongoose/