I'm trying to make a web application that uses a Node server as the back end and Angular to take information from the Node server and create a responsive front end. Currently, in my simple application, I have two js files: server.js and controller.js. Here is the code for each file:
var express = require("express");
var bodyParser = require("body-parser");
var app = express();
var port = 8006;
app.use(express.static(__dirname));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.post('/data', function(req, res){
console.log(req.body);
res.send("Success!")
res.status(200);
res.end();
});
app.listen(port);
console.log("Server running on port " + port);
And here's the controller file:
(function(){
var app = angular.module("testApp", []);
var TileController = function($scope){
// add stuff to $scope as initilization
};
app.controller("TileController", ["$scope", TileController]);
})();
This code is sort of incomplete because I'm not sure where to go with it, but I know what I want to do with it.
The model that Angular uses is going to be constantly updated by information parsed by the Node server upon incoming HTTP requests (specifically POST). Node is going to handle these requests and somehow pass the data along to Angular (in the controller.js file), which is going to update the model, and update the view along with that.
My question is what is the best way to pass information along from the Node server to the controller.js and update the model/view when the information is added?
I made a very simple example using just HTTP requests, and $interval, which is angular's equivalent of window.setInterval.
Save all the files in a folder
Download the node modules (express, body-parser)
node server.js
open index.html
POST some data to server (http://localhost:3000)
index.html should show a list of every data that was POST'd to the server, delayed by ~3 seconds
server.js
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
var arr = [];
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.get('/', function(req, res) {
res.json({arr: arr});
});
app.post('/', function(req, res) {
console.log(req.body);
arr.push(req.body);
res.end('Data received');
})
app.listen(3000, console.log.call(console, 'Server started.'));
app.js (angular)
var app = angular.module('app', []);
app.controller('MainCtrl', function($scope, $interval, $http) {
$scope.arr = [];
var stop = $interval(function() {
$http.get('http://localhost:3000')
.then(function(res) {
$scope.arr = res.data.arr;
}, function(e) {
console.error(e);
});
}, 3000);
});
index.html
<!DOCTYPE html>
<html lang="en" ng-app="app">
<head>
<meta content="UTF-8">
<title>live data example</title>
<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.7/angular.js"></script>
<script type="text/javascript" src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
<ul>
<li ng-repeat="item in arr">{{item}}</li>
</ul>
</body>
Related
I've been trying to implement a paymentCtrl to handle the Stripe payments but am unable to get the express to work. When i execute this code i get the following error below. I'm quite new to this and would like to understand why i get this error.
error:
Unknown provider: appProvider <- app <- paymentCtrl
app.js:
angular.module('userApp', ['appRoutes', 'userControllers', 'userServices', 'ngAnimate', 'mainController', 'authServices', 'managementController', 'paymentController'])
.config(function($httpProvider) {
$httpProvider.interceptors.push('AuthInterceptors');
});
payment.html:
<div>
<form action="/charge" method="post">
<script
src="https://checkout.stripe.com/checkout.js"
class="stripe-button"
data-key="pk_test_..."
data-amount="3000"
data-name="walla"
data-description="this is not a dog"
data-locale="auto"
data-currency="gbp"
></script>
</script>
</form>
</div>
paymentCtrl:
angular.module('paymentController', [])
.controller('paymentCtrl', function(app, passport) {
app.post('/charge', function(req, res){
});
});
server.js:
var express = require('express'); // ExperssJS Framework
var app = express(); // Invoke express to variable for use in application
var port = process.env.PORT || 8080; // Set default port or assign a port in enviornment
var morgan = require('morgan'); // Import Morgan Package
var mongoose = require('mongoose'); // HTTP request logger middleware for Node.js
var bodyParser = require('body-parser'); // Node.js body parsing middleware. Parses incoming request bodies in a middleware before your handlers, available under req.body.
var router = express.Router(); // Invoke the Express Router
var appRoutes = require('./app/routes/api')(router); // Import the application end points/API
var path = require('path'); // Import path module
var passport = require('passport'); // Express-compatible authentication middleware for Node.js.
var social = require('./app/passport/passport')(app, passport); // Import passport.js End Points/API
var stripe = require('stripe')('sk_test_...');
app.use(morgan('dev')); // Morgan Middleware
app.use(bodyParser.json()); // Body-parser middleware
app.use(bodyParser.urlencoded({ extended: true })); // For parsing application/x-www-form-urlencoded
app.use(express.static(__dirname + '/public')); // Allow front end to access public folder
app.use('/api', appRoutes); // Assign name to end points (e.g., '/api/management/', '/api/users' ,etc. )
//
// <---------- REPLACE WITH YOUR MONGOOSE CONFIGURATION ---------->
//
mongoose.connect('mongodb://localhost:27017/tutorial', function(err) {
if (err) {
console.log('Not connected to the database: ' + err);
} else {
console.log('Successfully connected to MongoDB');
}
});
// Set Application Static Layout
app.get('*', function(req, res) {
res.sendFile(path.join(__dirname + '/public/app/views/index.html')); // Set index.html as layout
});
// Start Server
app.listen(port, function() {
console.log('Running the server on port ' + port); // Listen on configured port
});
Your angular controller should be injected with $http module, app is undefined in your client side code as client side would not inherit code from your server.
$http module contains .post method along side numerous other methods such as .get .put .delete etc.
angular.module('paymentController', [])
.controller('paymentCtrl', function(app, passport, $http) {
$http.post('/charge', {}, function(req, res){
});
});
The second parameters in the $http.post ({}) is the data you want to transmit to your controller.
Lastly, you need a server method which will retrieve the POST request.
app.post('/charge', function(req, res) {
// Your server endpoint for /charge POST action
// req.body contains passed data.
});
As you're trying to send data using Angular to your server, you'll need to bind the form data to your model, and remove the form or listen to form submit event and make a POST request yourself the way you want to.
As you have not included the whole HTML document, it is hard to see if there are any other errors included, such as missing ng-controller declaration in your document as comments stated.
I assume you followed this Stripe tutorial so all you need to do is:
The code you've written in paymentCtrl should be copied into server.js before app.listen
// Set Application Static Layout
app.get('*', function(req, res) {
res.sendFile(path.join(__dirname + '/public/app/views/index.html')); // Set index.html as layout
});
app.post('/charge', function(req, res){});
// Start Server
app.listen(port, function() {
console.log('Running the server on port ' + port); // Listen on configured port
});
Unknown provider: appProvider <- app <- paymentCtrl
This means that app variable you are trying to inject does not exist in your client side code.
I've been trying to learn the MEAN stack and wanted to do an application to test it out. The aim was to have a static variable (in this case 'hello') displayed by Angular in the HTML, I can't seem to get my $scope variable in my controller to display, having looked in the developer console on my browser I saw 'GET 127.0.0.1:3000/app.js 404 not found'.
This is my node server using express:
var express = require('express');
app = express();
app.get('/', function(req, res){
res.sendFile(__dirname + '/views/index.html');
});
app.listen(3000, function() {
console.log('I\'m listening on port 3000...');
});
This is my index.html file (a directory below in /views):
<!DOCTYPE html>
<html ng-app="myModule">
<head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/
angular.min.js"></script>
<script type="text/javascript" src="app.js"></script>
</head>
<body>
<h1>Sucess!</h1>
<div ng-controller="myController">
<p>Angular test: {{ message }}</p>
</div>
</body>
And this is my app.js file containing my module and controller (also in /views):
var myApp = angular.module('myModule', []);
myApp.controller('myController', ['$scope',
function($scope) {
$scope.message = 'hello';
}]);
I'd be very grateful if anyone could help out!
You will have to serve all the files, for example using express.static, not just index.html:
var express = require('express');
app = express();
app.use(express.static('views'));
app.listen(3000, function() {
console.log('I\'m listening on port 3000...');
});
I am really new to the whole MEAN-stack and are trying to create an application on openshift but are unable to render a new page.
I just keep getting this error and can't solve it with anything I've googled.
My Error: Failed to lookup view "/register" in public directory
It works completely fine to render the index page with app.get('/', func()) in server.js and tried to to the exact same thing with app.get('/register). I used to have the same problem with '/' at first but solved it using app.use(express.static(__dirname + '/public'));
Both index.html and register.html are located in the public directory.
These are extracts of my code:
index.html
<body ng-app="">
<div class="container" ng-controller="LoginController" >
<h1>Logg in</h1>
<input class="form-control" placeholder="ID"/>
<input class="form-control" placeholder="Password"/>
<button class="btn">Logga in</button>
<button ng-click="open()" class="btn">Register User</button>
</div>
</body>
logincontroller
function LoginController($scope, $http) {
console.log("Hello from Login");
$scope.open = function () {
console.log('open i login.js');
$http.get('/register')
};
};
server.js
var express = require('express');
var fs = require('fs');
var mongojs = require('mongojs');
var jade = require('jade')
var app = express();
var cors = require('cors');
var bodyParser = require('body-parser');
app.use(express.static(__dirname + '/public'));
app.use(express.bodyParser());
app.get('/env',function(req, res){
res.json(process.env);
});
app.get('/', function (req, res) {
res.render('/index', {});
});
app.get('/register', function (req, res) {
res.render('/register');
});
app.set('view engine', 'jade');
There are a couple of issues.
1) Don't use a slash for the 'register' file. This is a file in the /public folder, not a folder or route.
app.get('/register', function (req, res) {
res.render('register');
});
2) You have set jade as your rendering engine. This means you will be serving .jade files. Your public folder should have index.jade. And it should look like this:
html
body(ng-app='')
.container(ng-controller='LoginController')
h1 Logg in
input.form-control(placeholder='ID')
input.form-control(placeholder='Password')
button.btn Logga in
button.btn(ng-click='open()') Register User
A couple of notes:
Jade is a HTML templating engine, it's relatively straight forward, see http://jade-lang.com/tutorial/.
There is express-generator which will give you an example app, it's an excellent starting point: http://expressjs.com/en/starter/generator.html
By the way, there is also an HTML-2-Jade converter, I find this helpful sometimes: http://html2jade.org/
anytime I add a param or query on any angular route, my browser request adds that param to the url request for my css file as such.
I am using html5mode true (pretty urls)
.state('profile', {
url: "/profile/:steamId",
templateUrl: "app/profile/profile.html",
controller: "ProfileCtrl",
controllerAs: "profile",
data: {
contentPages: 1
}
});
$locationProvider.html5Mode(true);
My angular service
getProfile:function(steamId){
var self = this;
return $http.get('api/user/'+steamId).then(function(response){
$log.debug('getProfile', response.data);
return response.data;
}, function(err){
$log.error('Error user', err);
});
},
and in my server
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
// Launch ======================================================================
var server = app.listen(8000, function(){
logger.info('The dagger flies at 8000');
});
// Configuration ======================================================================
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(express.static(__dirname + '/public'));
// Routes ======================================================================
var users = require('./routes/users.route')(passport, logger);
// Middleware ======================================================================
app.use('/api/users', users);
app.get('/*', function(req, res, next) {
res.sendFile('index.html', { root: 'public' });
});
my index.html is set up for this
<link rel="stylesheet" href="builds/style.css"/>
Normally I see something like this in my network tab when I'm on localhost:8000/profile for example
http://localhost:8000/builds/style.css
but when I add a param like this
localhost:8000/profile/13456
In my network tab, I see this
http://localhost:8000/profile/builds/style.css
and therefore a bunch of unstyled html code.
How can I fix this? I have tried playing around with the express static middleware but no success.
Linking CSS or JavaScript is relative to your current directory. To overcome that, add a / in front of the path to reference it as absolute path:
<link rel="stylesheet" href="/builds/style.css"/>
I'm trying to make a simple Angular/Express todo-list app, and I ran into quite a bit of trouble. It's still in the works, but when I ran the code below on localhost:3000 I ended up getting {{ thing }} literally printed in the webpage.
My file paths are:
app
js
app.js
index.html
node_modules (here lies angular, express, etc)
index.js
package.json
Here is my code for index.html:
<!DOCTYPE html>
<html lang="en" ng-app='testApp'>
<head>
<meta charset="UTF-8">
<title>Angular-Express Test App</title>
<script type='text/javascript' src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.12/angular.min.js"></script>
<script type='text/javascript' src='js/app.js'></script>
</head>
<body ng-controller='TestCtrl'>
<table>
<thead>
<tr>
<td>Item</td>
<td>Remove</td>
</tr>
</thead>
<tbody>
<tr ng-repeat='item in items'>
<td>{{ item }}</td>
<td>Done?</td>
</tr>
</tbody>
</table>
</body>
</html>
Here is my code for index.js:
var express = require('express');
var app = express();
var http = require('http').Server(app);
var bodyParser = require('body-parser');
var jsonParser = bodyParser.json();
var urlencodedParser = bodyParser.urlencoded({ extended: false });
app.set('port', process.env.OPENSHIFT_NODEJS_PORT || 3000); //yes I plan to deploy to OpenShift
app.set('ipaddr', process.env.OPENSHIFT_NODEJS_IP || "127.0.0.1");
app.get('*', function(req, res){
res.sendFile(__dirname + '/app/index.html', res);
});
http.listen(3000, function () {
'use strict';
console.log('Express server listening on IP: ' + app.get('ipaddr') + ' and port ' + app.get('port'));
});
And app.js:
angular.module('testApp', ['ngRoute'])
.controller('TestCtrl', [$scope, function ($scope) {
'use strict';
$scope.items = ["foo", "bar"];
}]);
Here's a screenshot of what I see, though there really isn't much in it that I haven't mentioned already...: http://puu.sh/gyhjT/684fa116f7.png
I spent a ridiculous amount of time trying to figure out what went wrong, so any help at all would be greatly appreciated!
there are few mistakes in your code,
first , the major one, you are directing every request to index page, so no way to get js/app.js
so change:
app.get('*', function(req, res){
res.sendFile(__dirname + '/app/index.html', res);
});
to:
app.get('/', function(req, res){
res.sendFile(__dirname + '/app/index.html', res);
});
app.get('/js/:file', function(req, res){
res.sendFile(__dirname + '/app/js/'+req.params.file, res);
});
next is, ngRoute and $scope mistake, ngRoute is not part of angular.min.js, you have to include it seperately, for now, i just changed your js/app.js and it works for me
angular.module('testApp', [])
.controller('TestCtrl', ['$scope', function ($scope) {
'use strict';
$scope.items = ["foo", "bar"];
}]);
remove ['ngRoute'] because you don't use it. If you want to use, please include angular-route.js in head