MEAN stack - Error while loading AngularJS script - javascript

I'm 100% new to MEAN stack and currently trying to self-study it with the help of this video by Michael Moser (If you're reading this, thank you for making such an easy-to-understand video! :) ). I'm trying to make a very basic program with CRUD functionalities, but I can't get past this particular error message when loading the Angular JS file. Can somebody point me in the right direction?
Here are my codes:
package.json
{
"name": "starter-node-angular",
"main": "server.js",
"dependencies": {
"body-parser": "~1.4.2",
"express": "^4.5.1",
"method-override": "~2.0.2",
"mongoose": "~3.8.0"
}
}
server.js
// modules needed
// express - middleware
var express = require('express');
var app = express();
// listens for request to server and throws main.html as response
app.get('/', function(req,res) {
res.sendfile(__dirname + '/client/views/main.html');
});
// listens for request to server with 'scripts' in it and returns the appropriate file declared
// in the script tag
app.use('/scripts', express.static(__dirname + '/client/scripts'));
app.listen(3000, function(){
console.log("Ready...");
});
HTML
<html ng-app="ProductApp">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.js" type="text/javascript"></script>
<script type="text/javascript" src="/client/scripts/main.js"></script>
<!-- stylesheets -->
<link href="/styles/main.css" rel="stylesheet" type="text/css">
</head>
<body class="main-background" ng-controller="MainController">
<!-- Area for Logo and Search Bar -->
<div class="header">
<div class="main-logo">
STUFF - Product Inventory v1.0
</div>
<div class="main-search">
<input type="text" class="search-field" placeholder="What are you looking for?" />
<img src="images/search-icon.png" title="Search" class="search-ico" />
</div>
</div>
<!-- Area for Add Button -->
<div class="add-container">
<div class="add-button" ng-click="addProduct(test);">
<img src="images/add-icon.png" title="Add" class="add-ico" />
<span class="add-text">Add Product</span>
</div>
</div>
</body>
</html>
AngularJS
'use strict';
var app = angular.module('ProductApp', []);
// Main controller
app.controller('MainController', ['$scope', function ($scope) {
// Search Products
$scope.searchProduct = function (param) {
// Search fxn goes here...
}
// Add products
$scope.addProduct = function (param) {
alert('Add product');
}
// Edit Products
$scope.updateProduct = function (param) {
// Update fxn goes here...
}
// Delete Product
$scope.deleteProduct = function (param) {
// Delete fxn goes here
}
}]);
I came from a background where calling JS files was simply declaring the full path in the src. Tbh, I find the entire MEAN setup a bit complex, with the "middleware" concept and all. :( I appreciate MongoDB's role in it, though.
Anyways, any help and advice would be greatly appreciated. God knows I need a lot of it right now.
Thank you.
Update 1:
I tried changing how my <script> tag calls my angular like so, with no success:
<script type="text/javascript" src="C:/users/myusername/documents/practice/product db/client/scripts/main.js"></script>
Also, am I right in thinking that localhost:3000 refers to Product DB in the following directory structure? I'm aware that 3000 is the port number; after looking at my error logs, I was thinking that localhost is just an alias for the source folder of the app.
Complete path is C:\users\myusername\documents\Practice\Product DB...
Thank you, as always. :)

You have included ng-app in the HTML tag, try adding that in the body of the page.
Do this:
<body class="main-background" ng-app="ProductApp" ng-controller="MainController">
Update:
you have done few mistakes while fetching stylesheets and scripts both. You need to define a proper static route which will work for all the static files(stylesheets and scripts).
you had defined yous static routed like this:
app.use('/scripts', express.static(__dirname + '/client/scripts'));
This will tell the node app to look into client/scripts folder, if any static route starts with /scripts. But you are trying to fetch your script using src="/client/scripts/main.js" which will not get anything, as /client is not defined , nor default '/' route is defined. It should be src="/scripts/main.js" instead.
One more mistake is while fetching stylesheets. you are using href="/styles/main.css", where again neither /styles nor / is defined, thus it will not be able to get the css file.
Try this instead:
Server.js
//define static routes like this
app.use(express.static(__dirname + '/client'));
// this will tell node app to look into the client folder, for any static file
HTML:
Fetch all your files like below:
To get stylesheets :
use /styles/filename
<link href="/styles/main.css" rel="stylesheet" type="text/css">
This will look into styles folder inside client folder.
To get scripts :
use /scripts/filename
<script type="text/javascript" src="/scripts/main.js"></script>
This will look into scripts folder inside client folder.

Related

Express.js Avoid reload the whole page

currently I have no solution for a site which I am trying to build. The page is not that big but I want to achieve that the complete site does not reload when I am opening a new tab in the navbar. I am using express.js and mustache as the template engine.
My goal is, that only the content reloads and not the whole site including the Navbar.
Do I have to use Ajax here? and
Is my structure correct to do this?
On the Server.js file I have this general structure I am not sure if there is a trick with views to only reload the content part of a page:
app.get('/home', function(req, res) {
res.render('index.html')
});
app.get('/navitem1', function(req, res) {
res.render('navitem1.html')
});
app.get('/navitem2', function(req, res) {
res.render('navitem2.html')
});
If you are trying to make sure your webpage doesn't reload while switch tabs and you're webpage isn't that big. I would recommend containing all your information within one .html file, have each "page" contained by a div with a targetable id, then simply hide/show the content that is selected. You might want to check out page.js and jquery they make this process much easier.
This is a quick demo of how to implement this:
note: you will need to npm init and npm i page
index.html:
<html>
<head>
<title></title>
</head>
<body>
<div id="title-area">
<h1>--your title--</h1>
<nav>
<ul>
<li>Home</li>
<li>Another Page</li>
</ul>
</nav>
</div>
<div id="home">
--home content--
</div>
<div id="another-page">
--other page content--
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="vendors/scripts/page.js"></script>
<script src="scripts/controllers/routes.js"></script>
</body>
</html>
scripts/controllers/routes.js:
sorry about globally scoped the IFFE functions, this is copy pasted.
'use strict';
(function(module){
const homeController = {};
homeController.init = function(){
$('#another-page').hide();
$('title').html('Home');
$('#home').fadeIn('slow');
}
module.homeController = homeController;
})(window);
(function(module){
const anotherpageController = {};
anotherpageController.init = function(){
$('#home').hide();
$('title').html('anotherpage');
$('#another-page').fadeIn('slow');
}
module.anotherpageController = anotherpageController;
})(window);
page('/', homeController.init);
page('/anotherpage', anotherpageController.init);
page();
if you'd like a better demo you can check out the app I built (where most of this content was ripped) https://github.com/loganabsher/portfolio-2.0

Node.js and expressjs routing to another folder

I need help with routing using ui.router.
My folder structure looks like this:
In my app.js under javascripts looks like this:
var app = angular.module('testing', ['ui.router']);
app.config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('home', {
url: '/home',
templateUrl: '/home.html'
})
.state('client_form', {
url: '/request',
templateUrl: '/client.html',
controller: 'MainCtrl'
});
$urlRouterProvider.otherwise('home');
}]);
My index.ejs looks like this:
<!DOCTYPE html>
<html>
<head>
<title>Testing</title>
<link href="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet">
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.10/angular.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.10/angular-ui-router.js"></script>
<script src="/javascripts/app.js"></script>
</head>
<body ng-app="testing">
<div class="col-md-6 col-md-offset-3">
<ui-view></ui-view>
</div>
</body>
</html>
home.ejs:
<div class="page-header text-center" style="font-size:45px">
Hacker List
</div>
<div class="text-center">
<a href="worker.html">
<button type="submit" class="btn btn-primary btnBig">Worker</button>
</a>
<br />
<a href="Client.html">
<button type="submit" class="btn btn-primary btnBig">Client</button>
</a>
</div>
When I do npm start and go to the website, I get an infinite loop of it not finding home.html.
I can make the code in home.ejs appear if I make it inline inside index.ejs using <script type="text/ng-template" id="/home.html">HOME_CODE_HERE</script>; however, I don't want to do that.
I'm not sure how to fix this.
The ui.router is AngularJS, not NodeJS.
Probably the infinite loop problem is in your front-end, not in NodeJS routes.
Out of the AngularJS problem, I would say that Express routes are in the back-end, so after a request (from Angular, browser, link, redirection etc) the responsibility and configuration needed to work is in NodeJS + Express + EJS.
Let's say you make a request to your /index.html. Once the request gets in the back-end, NodeJS will assume how to handle it.
So, to make sure you don't have a problem in NodeJS, check your app.js (used in node - probably in the root of your project). It could have the routing config similar with this:
var express = require('express');
var app = express();
// EJS template config
app.set('views','./views');
app.set('view engine','ejs');
app.use(bodyParser.urlencoded({ extended: true })); //support x-www-form-urlencoded
app.use(bodyParser.json());
// This is your routes
app.get('/', function(req, res) {
// Your code for index
res.render('views/index', { param : "This is a EJS test" });
});
app.get('/index.html', function(req, res) {
// Your code for index
res.render('views/index', { param : "This is a EJS test" });
});
app.get('/anotherPage.html', function(req, res) {
// Your code for another page: can include validations here
res.render('views/anotherPage', { param : "This is a EJS test" });
});
Now you would have your route set in NodeJS, then you could set your EJS files. Your home.ejs can be exactly the same.
The index.ejs file would be a little different. Maybe you could write it like this (I removed AngularJS from it for testing purposes):
<!DOCTYPE html>
<html>
<head>
<title>Testing</title>
<link href="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
This is a parameter from the back-end: <%= param %>
This is the index of EJS template. Below the snipped inserted:
<div class="col-md-6 col-md-offset-3">
<% include home.ejs %>
</div>
</body>
</html>
There are some good examples about routes and EJS in Express github page:
https://github.com/expressjs/express/tree/master/examples
I think that eliminating the problem with NodeJS can help you to fix the problem that seems to be in AngularJS.
Hope it's somehow helpful.

AngularUI Router + Ionic - routing works in browser, but not within Ionic View?

I have the most simple little Ionic App that works as expected when run in the browser using ionic serve.
However, when the app is run in Ionic View (view.ionic.io), the routing appears to be failing (the index.html is loaded, but nothing within <div ui-view=""></div> is loaded. This is done using ionic upload.
My simple index.html looks like:
<body ng-app="app">
my app!
<div ui-view=""></div>
</body>
My app.js contains:
angular
.module("app", [
"ionic",
"ngCordova",
"ui.router"
])
.config(function ($stateProvider, $urlRouterProvider) {
$stateProvider.state("splash", {
url: "/splash",
templateUrl: "components/splash/splash.html",
controller: "SplashController"
}).state("login", {
url: "/login",
templateUrl: "components/login/login.html",
controller: "LoginController"
});
$urlRouterProvider.otherwise("/splash");
});
I have a SplashController that has:
var SplashController = (function () {
function SplashController($scope) {
this.test = null;
this.scope = null;
$scope.vm = this;
this.scope = $scope;
this.test = "Hello world!";
}
SplashController.$inject = ["$scope"];
return SplashController;
})();
App.SplashController = SplashController;
angular.module("app").controller("SplashController", App.SplashController);
And my really boring splash.html is:
<div class="padding">
<h4 class="title dark">splash.html</h4>
<h4 class="title dark">{{ vm.test }}</h4>
</div>
In my browser (ionic serve) I see:
And on my device (ionic upload / Ionic View app) I just see my app!
What am I doing wrong? Is this an issue with the Ionic View app? Has anyone else run into this?
A few other things to note:
The JavaScript is compiled from TypeScript.
I had attempted <ion-nav-view></ion-nav-view> / excluding ui.router and the results were the same (works in the browser, but not on the device). I actually dislike the Ionic view animations and prefer to use the standard ui-router, if I can.
Well this turned out to be the strangest of issues. After further debugging, I realized that not only was the router not working, but Angular was not working at all ({{ 1 + 1 }}) displayed literally.
For some reason, the native app did not like my generated JavaScript in a .tsout directory. I removed it and placed the same exact file in the same directory as my index.html. I'm sure something else was going on behind the scenes, but re-structuring my project files seemed to solve the problem.
The setup with the error:
Project structure:
/www
/.tsout
app.js // both .tsout and app.js are created through my gulp-typescript task
/components
/css
/img
/lib
/typings
index.html
HTML head:
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
<title></title>
<link href="css/ionic.app.min.css" rel="stylesheet">
<link href="css/style.css" rel="stylesheet">
<script src="lib/ionic/js/ionic.bundle.js"></script>
<script src="lib/ionic/js/ng-cordova.min.js"></script>
<!-- cordova script (this will be a 404 during development) -->
<script src="cordova.js"></script>
<script src=".tsout/app.js"></script>
</head>
The solution:
My project structure after I found success both in the browser and on the device:
/www
/components
/css
/img
/lib
/typings
index.html
app.js // just app.js is created through my gulp-typescript task
The script tag in the head then looks like:
<script src="app.js"></script>
Hope the outcome of this wonkiness can be helpful to someone else!

Meteor iron-router splash screen error on deploy only

I'm using Meteor 1.0.3.1 on my local machine, and I'm deploying with node v0.10.36. However, the deploy machine only ever displays the iron-router splash screen... "iron:router" "Organize your Meteor application" ...
There are several other stacks about fixing this exact problem, including removing the tag and removing the projects npm.js file (left over from bootstrap). None of these are working.
project.js file is as follows:
Router.route('/', function () {
this.render('home');
});
Router.route('/about', function () {
this.render('about');
});
Router.route('/contact', function () {
this.render('contact');
});
Router.route('/legal', function () {
this.render('legal');
});
Router.route('imitationgamereview', function () {
this.render('imitationgamereview');
});
if (Meteor.isClient) {
}
if (Meteor.isServer) {
Meteor.startup(function () {
// code to run on server at startup
});
}
project.html file is as follows:
<head>
<title>my sample project</title>
<link rel="shortcut icon" href="/favicon.ico?v=2" />
</head>
<template name="home">
test
</template>
Totally going bonkers! WTF iron-router? I'm so in love with you, then you do stuff to me like this!
Perhaps it has to do with the file location of your routing file (project.js). Moving the it to /lib solved the problem for me.
I was getting the same splash screen on x.meteor.com and --production emulation until i made sure that every
Meteor.publish({});
is in an if(Meteor.isServer) statement e.g.
if(Meteor.isServer) {
Meteor.publish('files', function() {
return Files.find();
});
}
This fixed the problem for me.
I've just had a similar problem, and i don't know if this applies to you, but in my case it was the fact that i had two templates (two HTML files) with the same template name. Once i removed one of them, all came back to normal.
I.e., i had this line in both file1.html and file2.html :
<template name="sampleList">
Nothing really indicated where the problem lied.

AngularJS multiple ngApps each with its own ngRoute definitions, lazyloaded and bootstrapped on one page

My question comes from the need to lazy load different/separate ngApps on one page(bootstrapping them with angular.bootstrap), each of them using its own ngRoute definitions(defined in such a way that they do not overlap each other).
Now I have a working plunkr example and all seems to function well, but somehow I have the feeling that this is not the correct approach so that's why Im asking here for advice.
<!DOCTYPE html>
<html>
<head>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<link rel="stylesheet" href="style.css">
<script src="script.js"></script>
</head>
<body>
<div class="container">
<div class="col-xs-6 well" id="app1">
<h3>App1</h3>
Route 1
Route 2
Route 3
<div class="well" ng-view></div>
</div>
<div class="col-xs-6 well" id="app2">
<h3>App2</h3>
Route 1
Route 2
Route 3
<div class="well" ng-view></div>
</div>
</div>
<script type="text/javascript" src="https://code.angularjs.org/1.2.21/angular.min.js"></script>
<script type="text/javascript" src="https://code.angularjs.org/1.2.21/angular-route.min.js"></script>
<script>
var app1 = angular.module('app1', ['ngRoute']);
app1
.config(function($routeProvider) {
$routeProvider
.when('/:app/:param', {
template: 'app = {{app}}, param = {{param}}',
controller: 'Ctrl1'
})
})
.controller("Ctrl1",['$scope','$routeParams', function($scope,$routeParams) {
$scope.app = $routeParams.app;
$scope.param = $routeParams.param;
}]);
var app2 = angular.module('app2', ['ngRoute']);
app2
.config(function($routeProvider) {
$routeProvider
.when('/:app/:param', {
template: 'app = {{app}}, param = {{param}}',
controller: 'Ctrl2'
})
})
.controller("Ctrl2", ['$scope','$routeParams', function($scope,$routeParams) {
$scope.app = $routeParams.app;
$scope.param = $routeParams.param;
}]);
angular.bootstrap(document.getElementById("app1"), ['app1']);
angular.bootstrap(document.getElementById("app2"), ['app2']);
</script>
</body>
</html>
http://plnkr.co/edit/Y7A9bc3bDUyAXIS13JMZ?p=preview
FYI: I have already checked out ui-router to load separate states on one page, but it all requires for the source code to be loaded upfront(and have a single app.config with all routes in it) which is something I do not want as the Project is quite huge. So for the sake of keeping it simple and modular Im looking for something like the above example.
UPDATE to answer HockeyJ question:
OK I will try to keep this as short as possible. Very basically put - as I said the project could potentially become quite huge, from source code and module dependency perspective. This is why I want to make it in such a way, that each module can be totally separate App, able to be injected at any place and tested separately(thats not really an issue with AnJS). In the same time however the whole project, should be a single page app. As such there should not be screen reloads(to load an App jscript files) etc. Hence comes the lazy loading of scripts on demand and bootstrapping apps to DOM elems. The only possible intersection point of all apps is the URL routing which has strict naming convention for routes i.e. /reports/whatever ; /transactions/whatever etc. and should be managed by ngRoute.
UPDATED:
Checkout overmind project for angular and the demo here
Shows a project broken up into several apps: nav, home, profile, and admin. The nav app is always on the page and is the only app bootstrapped on pageload.
Just take routing out of angular and use something like sammy.js , history.js etc for client side routing.
Use
angular.bootstrap(module, node)
in the routes of your sammy handlers
Also you might want to take a look at react.js (with or without flux) and tide it up with sammy the same way. Consider this example from todombc : https://github.com/tastejs/todomvc/tree/gh-pages/architecture-examples/react

Categories