AngularJS and nodeJs Express: routes and refresh - javascript

My app is "working" fine, but, when I press F5 in browser my problem appears.
My app is organized this way:
nodeJs + express, in Express :
app.use(express.static('public'));
app.use( app.router );
app.use(function(req, res) {
res.sendfile(__dirname + '/public/index.html');
});
my angular routes:
app.config(function($locationProvider, $routeProvider) {
$locationProvider
.html5Mode(true)
.hashPrefix('!');
$routeProvider
.when('/', { templateUrl: '/page/home.html'})
.when('/activate/:token', { templateUrl: '/page/activate.html'})
.otherwise({ redirectTo: '/' });
});
and everything is working fine until i refresh the page,
if i'm on localhost:1234/activate/999
it appear refreshing good the page, but it stamp in console this error
Error: Template must have exactly one root element. was:<!DOCTYPE html>
<html ng-app=app xmlns="http://www.w3.org/1999/html">
<head>
<title>title</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
bla
bla
bla
all my index.html!
what can be the problems?
any solutions?
edit:
my home:
<div>
<section id="feature_slider" class="">
//...
</section>
<div id="showcase">
//...
</div>
<script type="text/javascript" src="/js/index-slider.js"></script>
</div>
mi activate:
<div>
test
</div>
my index.html
<!DOCTYPE html>
<html ng-app=app xmlns="http://www.w3.org/1999/html">
<head>
<title>tite</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- Styles -->
<link href="/css/bootstrap.min.css" rel="stylesheet">
<link href="/css/bootstrap-responsive.min.css" rel="stylesheet">
<link href="/css/bootstrap-overrides.css" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="/css/theme.css">
<link rel="stylesheet" href="/css/index.css" type="text/css" media="screen" />
<link rel="stylesheet" type="text/css" href="/css/lib/animate.css" media="screen, projection">
<link rel="stylesheet" href="/css/sign-in.css" type="text/css" media="screen" />
<link rel="stylesheet" href="/css/myCss.css" type="text/css"/>
</head>
<body class="pull_top">
<navbar>
//...
</navbar>
<ng-view> Loading...
</ng-view>
<!-- starts footer -->
<footer id="footer">
//...
</footer>
<!--Preload-->
<script src="/js/jquery-1.10.1.min.js"></script>
<!-- Scripts -->
<script src="/js/bootstrap.min.js"></script>
<script src="/js/theme.js"></script>
<!--Angular-->
<script type="text/javascript" src="/js/angular.min.js"></script>
<!--<script type="text/javascript" src="/js/angular-ui.min.js"></script>-->
<script type="text/javascript" src="/js/ui-bootstrap-0.5.0.min.js"></script>
<script type="text/javascript" src="/angular/app.js"></script>
<!--Angular Controller-->
<script type="text/javascript" src="/angular/login/loginController.js"></script>
<script type="text/javascript" src="/angular/menuNavBar/menuController.js"></script>
<script type="text/javascript" src="/angular/login/logOutController.js"></script>
<script type="text/javascript" src="/angular/login/registerController.js"></script>
<!--Angular Services-->
<script type="text/javascript" src="/angular/alertBox/messageBoxController.js"></script>
<!--Router-->
<script type="text/javascript" src="/angular/router/router.js"></script>
</body>

This is a problem commonly encountered when using a "catch-all" route that returns index.html (which you have to do when using Angular's html5 mode).
I don't know what your public folder structure looks like, but your Angular is making a request for activate.html that doesn't match its actual location (as served by Express). It may be because you have a leading slash in your templateUrl:
{ templateUrl: '/page/activate.html'})
but that depends on what your public folder looks like. "/page/activate.html" assumes that the "page" folder is at the root of your public folder. If it isn't, then that's your problem. You should have:
{ templateUrl: 'path/relative/to/public/folder/page/activate.html'})
which I'm guessing in your case would be something like:
{ templateUrl: 'views/page/activate.html'})
(It doesn't seem likely there would be a folder called "page" at the root of public/.)
Your express middleware attempts to handle the request for
http://localhost:1234/page/activate.html
but nothing successfully handles it, so your catch-all route just returns index.html, which has multiple root elements, causing Angular to throw a fit. Angular expected activate.html but it got index.html instead.
This will happen whenever the client makes a request that Express can't handle, because the catch-all router will return index.html. You can get your browser in an infinite loop as it continuously loads index.html, which loads Angular, which (erroneously) loads index.html, which loads Angular, etc.
Look at the request your browser is making for activate.html and make it match the actual location (as served by Express) of activate.html.

Try use the specify the templateUrl with the absolute path from the root of the views.
For example, suppose you have configured and views is in the public folder
app.set('views', __dirname + '/public');
then change the path to the template to
/public/page/home.html

Related

Providing an HTML page with JS in Node.js

I'm working in a Node.js app and I'm having trouble with a specific html page. All the pages I've done to this point are simply html and css, but in this case I have a multistep page that runs a script to move through the steps (showing diferent forms). In my case it won't load this script so the page doesn't work at all. The get request looks like this:
router.get("/reservaAula", eToken, (req, res) => {
jwt.verify(req.token, keyDocente, (err, data) => {
if (err) {
res.sendStatus(404);
} else {
res.render("reservaAula.html");
}
});
});
And the page is (the important part):
<!DOCTYPE html>
<html lang="en" id = "html">
<head>
<title>Reserva de Aula</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="/css/style.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<script src="/js/script.js"></script>
<script src="js/reservarAula.js"></script>
</head>
<body>
...
I've placed the script in the public folder, just like I placed my css, but no matter what I try it won't work. In the rest of the pages loads the other scripts in js folder correctly (like reservarAula.js), but not with script.js.
CSS and JS should be in the static folder and in your sub-folder. It should then work.
Example file location
/static/css/stylesheet.css
How to refer to it
/css/stylesheet.css
(You can do the same with JS)

How can I update a view (in node js) with a payload received from a webhook?

I am working on an express js project. I configured a webhook and I am receiving it's post request on my index.js file. Now what I want is to update the index view with the received payload. I have tried res.render and even tried to redirect to another test view but it didn't work.
Is there a way to do it? Or do I have to store it to db and retrieve it again?
Any help would be appreciated.
Here is a snippet from my index.js file
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', { message: 'Testing-initial'});
});
//capture webhooks
router.post('/', function (req, res) {
msgText = req.body.messages[0].text;
console.log('meg received from channel' + msgText);
res.render('index', { message: msgText });
});
following is my layout.hbs
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, shrink-to-fit=no">
<title>...</title>
<link href="assets/css/style.css" rel="stylesheet" type="text/css" />
</head>
<body class="alt-menu sidebar-noneoverflow">
{{{body}}}
<!-- BEGIN GLOBAL MANDATORY SCRIPTS -->
<script src="assets/js/libs/jquery-3.1.1.min.js"></script>
<script src="bootstrap/js/popper.min.js"></script>
<script src="bootstrap/js/bootstrap.min.js"></script>
<script src="plugins/perfect-scrollbar/perfect-scrollbar.min.js"></script>
<script src="assets/js/app.js"></script>
<script>
$(document).ready(function () {
App.init();
});
</script>
<script src="assets/js/custom.js"></script>
<!-- END GLOBAL MANDATORY SCRIPTS -->
<!-- BEGIN PAGE LEVEL SCRIPTS -->
<script src="assets/js/apps/mailbox-chat.js"></script>
<!-- END PAGE LEVEL SCRIPTS -->
</body>
</html>
I guess I don't have issues with it as I can GET the home with the text Testing-initial injected into it.
One last note: I have tried earlier to achieve this through WebSockets and it worked but I faced another issue which is missing payloads that come while there is no socket connection. Therefore, I am trying to do it without socket.io

Angular 5 include javascript files

I'm using Angular 5 and I want to include my script files .js
I'm using the script tag in the index.html
When I refresh the page everything works fine, but when i'm using SPA routing my js files does not included
Here's an exemple :
If I refreshed the page
When i'm using SPA navigation
Here's index.html where i include all my script whith script tag
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<base href="/">
<title>Listeo</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
<link rel="stylesheet" href="../assets/css/style.css">
<link rel="stylesheet" href="../assets/css/colors/main.css" id="colors">
</head>
<body>
<app-base></app-base>
<script type="text/javascript" src="../assets/scripts/jquery-2.2.0.min.js"></script>
<script type="text/javascript" src="../assets/scripts/mmenu.min.js"></script>
<script type="text/javascript" src="../assets/scripts/chosen.min.js"></script>
<script type="text/javascript" src="../assets/scripts/slick.min.js"></script>
<script type="text/javascript" src="../assets/scripts/rangeslider.min.js"></script>
<script type="text/javascript" src="../assets/scripts/magnific-popup.min.js"></script>
<script type="text/javascript" src="../assets/scripts/waypoints.min.js"></script>
<script type="text/javascript" src="../assets/scripts/counterup.min.js"></script>
<script type="text/javascript" src="../assets/scripts/jquery-ui.min.js"></script>
<script type="text/javascript" src="../assets/scripts/tooltips.min.js"></script>
<script type="text/javascript" src="../assets/scripts/custom.js"></script>
<script type="text/javascript" src="../assets/scripts/switcher.js"></script>
</body>
</html>
and here's the navigation bar :
<nav id="navigation" class="style-1">
<ul id="responsive">
<li>
<a [routerLink]="['home']" [routerLinkActive]="['current']">Home</a>
</li>
<li>
<a [routerLink]="['restaurants']" [routerLinkActive]="['current']">Restaurants</a>
</li>
</ul>
</nav>
When I'm using the href everything wirks fine, but with [routerLink] I'm facing the problem.
Are you using the Angular CLI?
Then you can put your custom js files into .angular-cli.json
"scripts": [
"<path_to_script",
"<path_to_second_script"
]
Then you don't have to reference them in the index.html.
You need to manually trigger the script
From looking at the documentation ( http://rangeslider.js.org/), the way to trigger the script is
$('input[type="range"]').rangeslider();
So what you probably need to do is trigger this in your component's ngAfterViewInit method (the one using rangeslider). This need to be in ngAfterViewInit to make sure that the dom elements have been created.
//component.ts
ngAfterViewInit()
{
$('input[type="range"]').rangeslider();
}

AngularJS ng-view not showing view

I'm developing a web app with AngularJS for the frontend and i'm trying to set the routing and showing the views, so far even ng-include and other stuff work for me but not ng-view
I'm developing in visual studio and when i run the app it's using a local server (localhost)
here's my directory structure
- ASP.NET project
---- Css
---- Scripts
-------- App
-------- app.js
----------- Home
-------------- Controllers
------------------ index-controller.js
---- Views
------- Partials
---------- navbar.html
------- home.html
- index.html
Here's mi index.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Scolaris</title>
<!--Import materialize.css-->
<link type="text/css" rel="stylesheet" href="Content/materialize/css/materialize.css" media="screen,projection" />
<!--Let browser know website is optimized for mobile-->
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
</head>
<body ng-app="app_module">
<ng-include src="'Views/Partials/navbar.html'"/>
<div ng-view></div>
<!--Import jQuery before materialize.js-->
<script type="text/javascript" src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
<script type="text/javascript" src="Content/materialize/js/materialize.js"></script>
<script type="text/javascript" src="Scripts/angular.js"></script>
<script type="text/javascript" src="Scripts/angular-route.js"></script>
<script type="text/javascript" src="Scripts/App/app.js"></script>
<script type="text/javascript" src="Scripts/App/Home/Controllers/index-controller.js"></script>
<script type="text/javascript" src="Scripts/initialization.js"></script>
</body>
</html>
Here's my app.js
'use strict';
var app_module = angular.module('app_module', ['ngRoute']);
app_module.config(['$routeProvider', function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: '/Views/home.html',
controller: 'indexController'
})
.otherwise({
redirectTo: '/'
});
}]);
/* tried with ../../Views/home.html, ../Views/home.html, etc and nothing */
When i load the site it loads correctly and if i see the requests i can clearly see that it's requesting the home.html with 304 status code, the thing is the div with ng-view is not showing the html inside home.html, what could this be due to?
I've solved the issue by changing the <ng-include> tag with an <div ng-include="srctoview"> tag. If anyone is having this issue i'd recommend doing this, or doing it like in this answer using a controller
Thanks to #Sourabh- for leading me to an answer.
close <ng-include> directive properly as browser is wrapping ur <ng-view> inside of <ng-include>. it will solve the problem. as #pankaj has already suggested.

Phonegap works on desktop but not on mobile Android

I'm developing a mobile application with Phonegap and AngularJS, and the application is working fine so far in desktop browser. Although, when I build it into an APK, some of the code of the application doesn't work.
First of all, I've seen this topic Phonegap - app works on desktop, not on mobile and the issue continues.
index.html
<!DOCTYPE html>
<html ng-app="home">
<head>
<meta charset="utf-8" />
<title>My new Application</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="viewport" content="user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimal-ui" />
<link rel="shortcut icon" href="/favicon.png" type="image/x-icon" />
<link rel="stylesheet" href="public/css/angular/mobile-angular-ui-hover.min.css" />
<link rel="stylesheet" href="public/css/angular/mobile-angular-ui-base.min.css" />
<link rel="stylesheet" href="public/css/angular/mobile-angular-ui-desktop.min.css" />
<link rel="stylesheet" href="public/css/global.css" />
</head>
<body>
<div class="app">
<div ng-include="'application/views/header.html'" style="margin-bottom: 51px"></div>
<div ng-view="">
</div>
<div ng-include="'application/views/footer.html'"></div>
</div>
<script srC="cordova.js"></script>
<script type="text/javascript" src="public/js/angular/angular.min.js"></script>
<script type="text/javascript" src="public/js/angular/angular-route.min.js"></script>
<script type="text/javascript" src="application/controllers/home.js"></script>
</body>
</html>
home.js
var app = angular.module('home', [
'ngRoute'
]);
app.config(function($routeProvider) {
$routeProvider
.when('/', {
templateUrl : '/application/views/home/home.html',
controller : 'home_controller'
})
});
app.controller('home_controller', ['$scope', '$location', function($scope, $location){
console.log('im here..');
alert('im here..!!');
}]);
I tried to "debug" by setting console.log and alert messages, but none of them shows up.
For debug, I'm using http://debug.build.phonegap.com/ weinre.
Conclusion: my application shows up normally, it loads the header.html and the footer.html, but not the home.html (nor shows up messages).
I also tried to set up the controller in the body ng-controller="home_controller" but the route configuration should do the same.

Categories