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
Related
I am trying to include Angular module as a separate file.
Here is my app.js
var app = angular.module('app', ['ngRoute']);
app.controller("TodoController", function($scope) {
$scope.players = ["Tom", "Dick", "Harry"];
});
This is my index.html
<html ng-app="app">
<head>
<title>Hello Angular!</title>
</head>
<body ng-controller="TodoController">
<input type="text" name="" ng-model="name"> {{name}}
<ul>
<li ng-repeat="player in players">
{{ player }}
</li>
</ul>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.5/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.5/angular-route.min.js"></script>
<script src="scripts/app.js"></script>
</body>
</html>
I am using express with node. This is my server.js
var express = require('express');
var app = express();
var path = require('path');
var port = process.env.PORT || 5000;
app.get('/', function(req, res){
//res.sendfile('./index.html');
res.sendFile('index.html', { root: path.join(__dirname) });
});
app.listen(port);
console.log('Express app is listening on : ' + port);
When I am trying to execute I am getting http://localhost:5000/scripts/app.js 404 (Not Found)
Code is working well when everything put in to the index.html.
File Structure is like this.
-- index.html
-- server.js
-- scripts
-- app.js
I have found the solution. as mentioned on the comment issue was with Serving static files in Express. I have included this code to the server.js.
app.use(express.static('public'))
I also created the public folder and included app.js to the public folder.
My new code looks like this.
public/index.html
<html ng-app='app'>
<head>
<title>Hello Angular!</title>
</head>
<body ng-controller="TodoController">
<input type="text" name="" ng-model="name"> {{name}}
<ul>
<li ng-repeat="todo in todos">
<input type="checkbox" ng-model="todo.completed">
{{todo.title}}
</li>
</ul>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.5/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.5/angular-route.min.js"></script>
<script type='text/javascript' src="app.js" charset="UTF-8"></script>
<script type='text/javascript' src="app/controllers/TodoController.js" charset="UTF-8"></script>
</body>
</html>
Server.js
var express = require('express');
var app = express();
var path = require('path');
var port = process.env.PORT || 5000;
app.get('/', function(req, res){
res.sendFile('index.html', { root: path.join(__dirname, 'public') });
});
app.use(express.static(path.join(__dirname, 'public')));
app.listen(port);
console.log('Express app is listening on : ' + port);
public/controllers/TodoController.js
app.controller('TodoController', ['$scope', function ($scope) {
$scope.todos = [
{ title: 'Learn Javascript', completed: true },
{ title: 'Learn Angular.js', completed: false },
{ title: 'Love this tutorial', completed: true },
{ title: 'Learn Javascript design patterns', completed: false },
{ title: 'Build Node.js backend', completed: false },
];
}]);
public/app.js
var app = angular.module('app', []);
New file structure will be like this.
-- public
-- app
-- controllers
-- TodoController.js
-- app.js
-- index.html
-- server.js
-- package.json
Since you have only http://localhost:5000/ route which is exposed which renders index.html file.
app.get('/', function(req, res){
//res.sendfile('./index.html');
res.sendFile('index.html', { root: path.join(__dirname) });
});
Any other path will give you 404.
You cannot access http://localhost:5000/scripts/ directly.
To access scripts please add the following line in server.js
app.use(express.static(path.join(__dirname, 'scripts')));
Updated code for server.js will be.
var express = require('express');
var app = express();
var path = require('path');
var port = process.env.PORT || 5000;
app.use(express.static(path.join(__dirname, 'scripts')));
app.get('/', function(req, res){
//res.sendfile('./index.html');
res.sendFile('index.html', { root: path.join(__dirname) });
});
app.listen(port);
console.log('Express app is listening on : ' + port);
Now http://localhost:5000/scripts/app.js should not give 404.
Not just scripts/app.js, You can access any file which is in scripts folder now.
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/
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>
I'm using express static to point to public directory
//app.js
app.use(express.static( __dirname + '/public'));
how can I have it so most of the routing for UI is from AngularJS, as of now, it does not work unless on app.js I specify something like this
//app.js
app.get('/submit', function(req,res){
res.sendfile(__dirname + '/public/submit.html');
});
app.get('/schedule', function(req,res){
res.sendfile(__dirname + '/public/schedule.html');
});
if I remove the above part, and create /public/app.js instead, it does not work
// Declare app level module which depends on filters, and services
angular.module('myApp', ['page-ctrl']).
config(['$routeProvider', '$locationProvider', function($routeProvider, $locationProvider) {
$routeProvider.
when('/', {
templateUrl: 'index.html',
controller: LoginController
}).
when('/submit', {
templateUrl: 'submit.html',
controller: AddPostCtrl
}).
otherwise({
redirectTo: '/'
});
$locationProvider.html5Mode(true);
}]);
Simply said, what I need is to point to index.html on express, and afterward routing should be done by angular, that way I can do checking on login authentication and reroute to index page, if user not login and try to access other page.
this is what I have for app.js (express) --> /project/app.js
/*app.js*/
//dependencies
var fs = require('fs');
var http = require('http');
var https = require('https');
var express = require('express');
var mongoose = require('mongoose');
var bodyParser = require('body-parser');
//variables
var db;
if(process.env.ENV == 'Test')
db = mongoose.connect('mongodb://localhost/videoRequestAPI_Test');
else
db = mongoose.connect('mongodb://localhost/videoRequestAPI');
var app = express();
var port = process.env.PORT || 13337;
var debug = process.env.DEBUG || false;
/**/app.use(express.static( __dirname + '/public'));/**/
/**/app.use(bodyParser.urlencoded({extended: true}));/**/
/**/app.use(bodyParser.json()); /**/
// route middleware that will happen on every request
var routes = require('./routes');
//app.get('/', routes.index);
app.get('*', function(req, res){
res.sendfile(__dirname + '/public/index.html');
});
var httpServer = http.createServer(app);
httpServer.listen(80);
console.log("Server Running! Ports 80 open for traffic");
and this is the index.html --> myproject/public/index.html
<!DOCTYPE html>
<html ng-app="page-ctrl">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.16/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<link rel="stylesheet" type="text/css" href="css/bootstrap.css">
<link rel="stylesheet" type="text/css" href="css/abc.css">
<script src="js/scripts/bootstrap.min.js"></script>
<script src="js/scripts/angular-local-storage.min.js"></script>
<script src="js/scripts/ui-bootstrap-custom-0.13.0.js"></script>
<script src="js/scripts/ui-bootstrap-custom-tpls-0.13.0.js"></script>
<script src="js/controllers/pageController.js"></script>
<script src="js/controllers/loginController.js"></script>
<script src="js/services/services.js"></script>
</head>
<body>
<nav class="navbar navbar-fixed-top" >
<aside class="col-sm-7" text-align="center">
<img src="img/sd.png" class="logo">
</aside>
<ul class="nav nav-pills">
<li role="presentation" class="nav-btn">Submit Content</li>
<li role="presentation" class="nav-btn">Scheduled Content</li>
<li role="presentation" class="nav-btn active">Pending Content</li>
</ul>
</nav>
<div class="container">
<div ng-controller="LoginController">
<input ng-model="email" type="email" class="form-control limit" placeholder="Email">
<input ng-model="credentials" type="password" class="form-control limit" placeholder="Credentials">
<button ng-click="login()" class="btn btn-primary btn-default" type="button" data-dismiss="modal">Login</button>
</div>
</div>
<footer class="footer">
© (June 2015)
</footer>
</body>
</html>
In your router.js to do all your API routes first, then a wildcard route for Angular, like this:
//API routes first
app.get('/API/users', UserController.getUsers);
app.get('/API/user/:id', UserController.getUserById);
//Then let Angular handle the rest of the routes
app.get('*', function(req,res){
return res.sendFile(__dirname + '/public/index.html');
});
The index.html being the starting point of your Angular application.
One more thing, make sure the index.html has the following in the "head" tag:
<base href="/">
EDIT:
A good starting point is to check out this great example:
https://github.com/scotch-io/starter-node-angular
and structure your application the same way:
I usually create a routes and api folder.
Each folder contains bunch of request handler functions (req, res, next). Ordered in different files based on the resource or function they serve.
Each folder has a main file (routes.js / api.js in my case) which maps all functions to the appropriate url / HTTP method. And also invokes authentication on those routes.
This allows you to very easily use different auth methods for API routes and normal routes.
If someone requires for instance a missing static asset or and undefined route, and 404 handler is invoked. So that the pages does not return the index page on all requests.
For example routes.js
module.exports = function(app) {
function ensureAuthenticated(req, res, next) {
// Authenticate....
}
function ensureAdmin(req, res, next) {
// Check for admin
}
// Resource puppies
app.all('/puppies*', ensureAuthenticated)
// Series (File Upload & Conversion)
app.get('/puppies', require('./puppie').someRoute)
// Admin*
app.all('/admin*', ensureAuthenticated, ensureAdmin)
// Admin > User
app.get('/admin/users', require('./admin').find)
app.all('/', ensureAuthenticated, ensureActive, require('./index').index)
// All undefined asset or api routes should return a 404
app.route('/:url(api|auth|components|app|bower_components|assets|views)/*')
.get(function(req, res, next) {
var err = new Error('Resource not found: ' + req.url)
res.status(404).send(err)
})
// Index
app.all('/*', require('./index').index)
}
In app.js you can then use these routes like so
require('./routes/routes')(app)