Angular.js : How to use ng-href in template? - javascript

I try to create a simple SPA with 1 index.html which include templates.
I got a problem with ng-href directive:
<a ng-href="#/myPage">myPage</a>
work in index.html but not in my templates, the link is unclickable. but href still works.
myPage
My app :
index.html:
...
<body ng-app="myApp">
<a ng-href="#/myPage" target="_self">link</a> <!-- work ! -->
<div class="container" ng-view=""></div>
</body>
...
app.js:
'use strict';
angular.module('myApp',
[ 'ngCookies', 'ngResource', 'ngSanitize', 'ngRoute' ]).config(
function($routeProvider) {
$routeProvider.when('/', {
templateUrl : 'views/main.tpl.html',
controller : 'MainCtrl'
})
.when('/myPage', {
templateUrl : 'views/page.tpl.html',
controller : 'MainCtrl'
})
.otherwise({
redirectTo : '/'
});
});
controller.js
'use strict';
myApp.controller('MainCtrl', function() {
this.myColor = 'blue';
});
page.tpl.html
<div>
<a ng-href="#/myPage" target="_self">link</a> <!-- Dont work -->
<a ng-href="#/myPage" target="_self">link</a> <!-- Dont work -->
<a ng-href="#/myPage{{}}">link</a> <!-- Dont work -->
<a ng-href="#/{{ 'myPage' }}">link</a> <!-- Dont work -->
link <!-- Work ! -->
</div>
I don't understand the problem with ng-href and why the result is different than href.
I use angular 1.2

ngHref is used to dynamically bind angular variables to the href attribute like so:
<a ng-href="#/{{myPathVariable}}"/>Take Me Somewhere</a>
Where in your scope:
$scope.myPathVariable = 'path/to/somewhere';
Then after angular compiles it, it looks like this:
<a ng-href="#/path/to/somewhere" href="#/path/to/somewhere" ... other angular attributes>Take Me Somewhere</a>
If your path is hardcoded into the page (you know where the link should take you on page load), you can just specify it in an href, which is why your third example works. Only use ngHref when you need angular to decide the route dynamically after the JS loads. This prevents your user from clicking links and going to an invalid route before angular has deciphered where the link should point. Documentation here

Related

Angular Material and md-nav-bar routing

I'm digging into Angular and have decided to use the Angular Material library to assist in my first application. So far I have some very basic code I copied from https://material.angularjs.org/1.1.0/demo/navBar which I have modified to fit my own needs. I'm having some trouble wrapping my head around routing and the md-nav-items.
<html>
<head>
<title>PRT - CIT</title>
<meta name="viewport" content="width=device-width, initial-scale=1" </meta>
<!-- Angular Material style sheet -->
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/angular_material/1.1.0/angular-material.min.css">
<link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Roboto:300,400,500,700,400italic"> </head>
<body ng-app="MyApp" id="bootstrap-overrides">
<div ng-controller="AppCtrl" ng-cloak="" class="navBardemoBasicUsage main">
<md-content class="md-padding">
<md-nav-bar md-selected-nav-item="currentNavItem" nav-bar-aria-label="navigation links">
<md-nav-item md-nav-click="goto('queue')" name="queue">Queue</md-nav-item>
<md-nav-item md-nav-click="goto('detail')" name="detail">Detail</md-nav-item>
<md-nav-item md-nav-click="goto('request')" name="request">Request</md-nav-item>
<!-- these require actual routing with ui-router or ng-route, so they won't work in the demo
<md-nav-item md-nav-sref="app.page4" name="page4">Page Four</md-nav-item>
<md-nav-item md-nav-href="#page5" name="page5">Page Five</md-nav-item>
--></md-nav-bar>
<div class="ext-content"> External content for `<span>{{currentNavItem}}</span>` </div>
</md-content>
</div>
<script src="node_modules/angular/angular.js"></script>
<script src="node_modules/angular-resource/angular-resource.js"></script>
<script src="node_modules/angular-animate/angular-animate.js"></script>
<script src="node_modules/angular-route/angular-route.js"></script>
<script src="node_modules/angular-aria/angular-aria.js"></script>
<script src="node_modules/angular-messages/angular-messages.js"></script>
<script src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/t-114/svg-assets-cache.js"></script>
<script src="node_modules/angular-material/angular-material.js"></script>
<script src="js/site.js"></script>
<link rel="stylesheet" href="/css/site.css">
</body>
</html>
Here's my JS:
(function () {
'use strict';
var MyApp = angular.module('MyApp', ['ngMaterial', 'ngMessages', 'material.svgAssetsCache', 'ngRoute']).controller('AppCtrl', AppCtrl);
function AppCtrl($scope) {
$scope.currentNavItem = 'queue';
}
MyApp.config(function ($routeProvider) {
$routeProvider.when('/', {
templateUrl: '/index.html'
, controller: 'AppCtrl'
}).when('/queue', {
templateUrl: '/partials/queue.html'
, controller: 'AppCtrl'
}).when('/detail', {
templateUrl: '/partials/detail.html'
, controller: 'AppCtrl'
}).when('/request', {
templateUrl: '/partials/request.html'
, controller: 'AppCtrl'
});
});
})();
I'm kind of lost as to how I should route the tabs. From what I've read, md-nav-bar has some routing built in, but I've found examples utilizing ngRoute as well ui-router.
I'm also confused as to actually populate my partial views in the
<div class="ext-content"> External content for `<span>{{currentNavItem}}</span>` </div>
I tried using md-nav-href instead of md-nav-click but it just ended up redirecting me to the pages, not populating the content below my tabs/nav-bar; I rolled back the JS I had written and that part of the HTML. I've read the other questions posted in this area that I could find but none addressed rendering different partials based on nav-bar item. Any suggestions? I was thinking I could monitor currentNavItem and have the right partial render based on the value of it, but again, I'm not sure how to actually do the rendering.
Here is a Plnker that doesn't render correctly in the preview for some reason, but the code is the same as what I have locally.
Here is an image of what it looks like running locally.
Thanks in advance!
Final Edit:
S/O to #Searching for helping me get it working below. I've updated the plnker link to reflect the changes. Note it gets a little laggy due to the base append script.
ngRoute: When $route service you will need ng-view container. This will be used to load all you routed pages.
You do not have a goto() so just use simple md-nav-href tags to navigate around. The currentNavItem is set by md-selected-nav-item which is not what you need. Let's route with your setup
index.html : update your links to look like this. Use md-nav-href
<md-nav-item md-nav-href="queue" name="queue">Queue</md-nav-item>
index.html : when using html5Mode you will need base tag. Instead of manually specifying it just use the script below. Make sure you load angular.js before this script.
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.js"></script>
<script type="text/javascript">
angular.element(document.getElementsByTagName('head')).append(angular.element('<base href="' + window.location.pathname + '" />'));
</script>
script : enable html5molde, why.. too many resources out there. I encourage you to lookup :)
MyApp.config(function ($routeProvider, $locationProvider) {
$locationProvider.html5Mode(true)
$routeProvider.when('/', {
templateUrl : 'index.html',
controller : 'AppCtrl'
}).when('/queue', {
templateUrl : 'queue_partial.html',//actual location will vary according to your local folder structure
controller : 'AppCtrl'
}).when('/detail', {
templateUrl : 'detail_partial.html',
controller : 'AppCtrl'
}).when('/request', {
templateUrl : 'request_partial.html',
controller : 'AppCtrl'
});
});

Login Page without Index.html Design - ngRoute (AngularJS)

I'm using ngRoute to do the routing of my AngularJS application (myApp) but I have a problem: I don't know how to NOT APPLY my index.html design (with all my sidebars) to my login.html page, which seems to be applied by default if it is defined as a view. I want a simple design for my login.html page: only two fields to fill out, without the design of my index.html, which is applied to all the views in myApp. Thereby, I don't know how to do my routing to accomplish such task. Thank you very much.
<-- This is a sample of how I do my routing in myApp (for only one view - "/view1") -->
Sample of app.js:
'use strict';
// Declare app level module which depends on views, and components
angular.module('myApp', [
'ngRoute',
'ngResource',
'ui.bootstrap',
'ngCookies',
'myApp.view1',
])
.config(['$routeProvider', function($routeProvider) {
$routeProvider.otherwise({redirectTo: '/view1'});
}]);
For each view there is a .js file associated where I defined its routing and controllers. For instance, for view "/view1" - view1.js:
'use strict';
angular.module('myApp.view1', ['ngRoute', 'ngResource'])
.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/view1', {
templateUrl: 'view1.html',
controller: 'View1Ctrl'
});
}])
.controller('View1Ctrl', ['$scope', function($scope) {
// something
}]);
And a sample of my index.html:
<!doctype html>
<html lang="en" ng-app="myApp">
<head>
<script src="view1.js"></script>
<-- MORE SCRIPTS ARE LOADED -->
</head>
<body class="hamburg" ng-controller="MasterCtrl">
<-- SIDEBARS ARE DEFINED -->
<div id="content-wrapper">
<div class="page-content">
<!-- Main Content -->
<div class="row">
<div class="col-xs-12">
<div class="widget">
<div class="widget-body">
<div ng-view></div>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
Given the situation above looks like you want two page layout (page design or page template), the first one is now used in index.html, and the second one you want to use in login.html which just has two fields to fill out. So angular-ui/ui-router (doc url: https://github.com/angular-ui/ui-router/wiki) could be the solution to this issue.
The idea behind that is ui-router has a very powerful tool named ui-view which you can see it as a layout or template. So when the path is on any page other than login page like /index or /home use one ui-view, and on /login page then use another different ui-view.
For a rough example:
index.html page:
<html>
<head></head>
<body>
<div ui-view="layout"></div>
</body>
</html>
I assume you will reuse the head part, so just wrap every thing from the body in the original index.html and put into the new index.html. Same to the login page login.html.
config file:
$stateProvider
.state('index', {
url: '/index',
views: {
layout: {
templateUrl: "/path/to/index.html"
}
},
controller: 'indexController'
}
.state('login', {
url: '/login',
views: {
layout: {
templateUrl: "/path/to/login.html"
}
},
controller: 'loginController'
})
So what does the code above do is very similar to what you did with $routeProvider, it defines on which url use which controller and to load which view.
Hope this can help you, if any question let me know please.
You need to create your login page as a diferente ngApp, store your sesion on the localSotarge in case of a successfull login and then redirect to you main ngApp.
In your main ngApp, validate if a session exists in the localStorage and redirecto to the loginApp if it dont.
I know it sounds a bit like overdoing stuff, but I have not found any other solution in my 3 years working with AngularJS. Now, keep in mind that this is necesary because you need to NOT TO APPLY your index.html, and the only way to do that is using another ngApp.
Routing is used for injecting views in angular SPA. What I get from from your question is you need a login dialog.
For that you may look ngDialog or uibDialog
In your case you need to load new layout. I understand, for login and for application there is mostly different layout. This operation is equal to redirecting page to new location. With new angular app and controllers for login. You can use:
$window.location.href="new/layout/template".
Read more # Angular Dev Docs.

Why does my AngularJS app not work when I add routing?

I'm new to AngularJS, I actually started today and I wanted to create a sample site for a company using AngularJS. My plan was to create a view for the products and a view for the about page.
This is my index.html code:
<!doctype html>
<html ng-app="myApp" ng-controller="myCtrl">
<head>
<title>{{ title }}</title>
<script src="https://code.angularjs.org/1.5.0/angular.min.js"></script>
<script src="https://code.angularjs.org/1.5.0/angular-route.js"></script>
<script src="js/app.js"></script>
<!-- Bootstrap -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css"
</head>
<body>
<nav class="navbar navbar-default">
<div class="navbar-header">
<a class="navbar-brand"> {{ title }}</a>
</div> <!-- navbar-header -->
<div class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li>Products</li>
<li>About</li>
</ul>
</div>
</nav>
<div ng-view></div>
</body>
</html>
And this is what I have in my app.js file:
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope){
$scope.title = "My company site";
});
app.config(['$routeProvider', function($routeProvider){
$routeProvider.
when('/products', {
templateUrl: 'partials/home.html',
controller: 'productsController'
}).
when('/about', {
templateUrl: 'partials/about.html',
controller: 'myCtrl'
}).
otherwise({
redirectTo: '/products'
});
}]);
app.controller('productsController', function($scope){
$scope.message = 'This will show my products page';
});
app.controller('aboutController', function($scope){
$scope.message = 'This will show my about page';
});
Whenever I click on a link on my navbar the view for the clicked link doesn't get rendered. Also the title of the site is displayed like that {{ title }} on the browser. These problems started when I added the code for the routing. If I remove the code from the routing the title displays correctly. Also whenver I have the routing code on the site I get this error in my browser.
Uncaught Error: [$injector:modulerr] and it gives me a link to this page. I've visited the site and after checking everything the module seems to be loading fine only when I don't have the code for the routing in the app.js. So what am I doing wrong here? I'm looking at this for about an hour and I can't figure it out.
You're trying to use ngRoute, which is a separate module and needs to be installed and included separately. The error page links to another page, which specifically tells you that $routeProvider is unknown in your current project. See the ngRoute page for installation instructions: https://docs.angularjs.org/api/ngRoute.
Most specifically:
Then load the module in your application by adding it as a dependent module:
angular.module('app', ['ngRoute']);
var app = angular.module('myApp', ['ngRoute']);
Add the dependency. Worked for me.
You are not loading ngRoute in your app. To load it you should do something like this :
var app = angular.module('myApp', ['ngRoute']);
Change var app = angular.module('myApp', []); to var app = angular.module('myApp', ['ngRoute']); you're missing the module injection.

AngularJS routing doesnt work

I'm new to AngularJS and I'm currently building a small application. I want my URL's like this /index (without the .html). I tried to use NgRoute for that, but it doesn't seem to work out well. When i go to /establishments, it says the route doesn't exists. Here is my code:
app.js
var app = angular.module('khApp', ['ngRoute','establishmentModule', 'queryModule', 'buildingBlockModule', 'categoryModule']);
app.config(['$routeProvider', function($routeProvider)
{
$routeProvider
.when('establishments', {controller:'testController', templateUrl: '../html/establishments.html'})
}]);
app.controller('testController', ['$http', function($http)
{
}]);
index.html
<div ng-controller="testController as test" class="container">
hi
<a href="establishments">
<button class="btn btn-default">Start</button>
</a>
</div>
<ng-view></ng-view>
<script type="text/javascript" src="../../bower_components/angular/angular.js"></script>
<script type="text/javascript" src="../../bower_components/angular-route/angular-route.js"></script>
<script type="text/javascript" src="../js/app.js"></script>
<script type="text/javascript" src="../js/buildingblock.js"></script>
<script type="text/javascript" src="../js/category.js"></script>
<script type="text/javascript" src="../js/establishment.js"></script>
<script type="text/javascript" src="../js/query.js"></script>
</body>
</html>
What am i doing wrong? Thanks in advance!
Depending on how your router is configured, typically you need to target routes beginning with a slash like so:
app.config(['$routeProvider',
function($routeProvider) {
$routeProvider
.when('establishments', {
controller:'testController',
templateUrl: '../html/establishments.html'
});
}]);
In addition, in your HTML, I think your HTML anchor tags need to begin with the hash navigation like so:
<a href="#/establishments">
<button class="btn btn-default">Start</button>
</a>
Reference: AngularJS Documentation Tutorial 7 - Routing & Multiple Views
AngularJS routing utilizes the fragment identifier (the # in the URL) to get its routes. That's because it can't manipulate the full URL without causing the browser to request a new page, thus making it not a SPA.
So the URL you need to request should be the form of <path to root>#/establishments. Assuming index.html is in /application/app/html, the URL to request would be:
/application/app/html/index.html#/establishments
If you also want to support the URL localhost:port/application/app/html/establishments then you need to configure your server side routing to perform a redirect to /application/app/html/index.html#/establishments.
#/establishments is what you need in your anchor tag
<a href="#/establishments">
<button class="btn btn-default">Start</button>
</a>
your route will be something like this:
app.config(['$routeProvider',
function($routeProvider) {
$routeProvider
.when('establishments', {
controller:'testController',
templateUrl: '../html/establishments.html'
});
}]);

Angularjs templateUrl couldn't find ngTemplate in ngInclude

I have trouble with templateUrl when it's have an ngTemplate in ngInclude.
My index.html
<div ng-include="'./html/root.html'"></div>
My root.html
<script type="text/ng-template" id="home.html">
<div class="content">
<div class="group">
<div ng-bind-html="content"></div>
</div>
</div>
</script>
<div ng-view></div>
My routeProvider.js
$routeProvider.when('/home', {
templateUrl: 'home.html',
controller: 'HomeCtrl'
})
This wasn't find home.html in ngTemplate. I think this couldn't find "home.html" because root.html has ng-view that in ngInclude.
Note 1: When I put my <script type="text/ng-template" id="home.html"> in index.html it's working.
Note 2: When I change my routeProvider.js with;
$routeProvider.when('/home', {
template: "<div ng-include=\"'home.html'\"></div>",
controller: 'HomeCtrl'
})
It's work too.
How can I fix that?
Please note a few things at first.
When you are using templateUrl, angular expects an url to which the html content is residing.(This is basically for accessing a file with the html markup).
What you can do is, keep the content in some a file with the name as home.html and provide the link to the file inside the templateurl.
Or You have to provide the templateUrl with the url of the physical file which contains the template and then use template to fetch the template with the specific Id.

Categories

Resources