So I'm trying to learn how to use Angulars routing, following tutorials online, and I can't seem to figure out where I'm going wrong. I have the following code:
var app = angular.module('gamersplane', ['controllers', 'ngCookies', 'ngRoute']);
app.config(['$routeProvider', function ($routeProvider) {
$routeProvider.when('/pms/:box?', {
controller: 'pmList'
}).when('/pms', {
controller: 'pmList'
}).otherwise({
controller: 'pmList'
});
}])
var controllers = angular.module('controllers', []);
controllers.controller('pmList', function ($scope, $cookies, $http, $routeParams) {
console.log($routeParams);
});
However, no matter what I do, the controller doesn't get hit. I have otherwise in the router, so isn't that where it should hit if all else fails?
Yes it will hit otherwise but you can only define the redirect path into it and that redirect path will tell the url and the controller to set for the $route.current :-
redirectTo: '/pms'
Doc
You need to add a template to each route:
app.config(['$routeProvider', function ($routeProvider) {
$routeProvider.when('/pms/:box?', {
controller: 'pmList',
template: 'test.html'
}).when('/pms', {
controller: 'pmList',
template: 'test.html'
}).otherwise({
controller: 'pmList',
template: 'test.html'
});
}])
squiroids suggestion regarding otherwise was correct, you won't see a change in your test application though.
Routing is meant to be used to navigate between regions of your application. You could have an app with two routes: pms which shows a list of PMs and pms/:box zu view a particular PM Box. The main task for ngRoute is to replace a placeholder in your application (ng-view) with a given template. Without using a template on the individual routes, your $routeProvider will not navigate as expected.
Given you have two views for the regions (pmBox.html and pmList.html), you could configure your $routeProvider zu setup routing like this: https://gist.github.com/kpko/bd0231ccefbaf8c415c7
Related
I have a situation where a third party library adds "#checkout" at the end of the URL (it's Snipcart) but Angular cannot seem to detect it and it just goes back to the /test page (localhost:3000/test).
The reason the URL is: /test is intentional as I have html5mode enabled.
This works well in a normal static HTML project (so not Angular) but when I used ui.router with Angular 1.x, it doesn't work.
My angularApp.js file:
var mainApp = angular.module('mainApp', ['ui.router']);
mainApp.config(function($locationProvider, $stateProvider, $urlRouterProvider) {
$locationProvider.html5Mode(true);
$urlRouterProvider.otherwise(function(){
console.log('otherwise activated');
});
var helloState = {
name: 'root',
url: '/',
templateUrl: '/partial/main.html',
controller: 'mainController'
}
var aboutState = {
name: 'test',
url: '/test',
views: {
'#': {
templateUrl: '/partial/yamuna.html',
controller: 'testController'
}
}
}
$stateProvider.state(helloState);
$stateProvider.state(aboutState);
});
mainApp.controller('mainController', ['$scope', '$rootScope', function($scope, $rootScope){
console.log('mainController activated');
}]);
mainApp.controller('testController', ['$scope', '$rootScope', function($scope, $rootScope){
console.log('testController activated');
}]);
So the paths below work as expected:
localhost:3000/ ##mainController activated
localhost:3000/test ##testController activated
But, Snipcart appends the path to:
localhost:3000/test#checkout - which I want to be able to go to the otherwise route and not fall back to localhost:3000/test#
Any way around this? As Angular 1 is quite old, I will have to come up with a workaround myself.
Edit
I can detect the path change with: (FYI this one below is in ngRoute as I was playing around with the various options):
mainApp.run(
['$rootScope', '$location', '$window', function($rootScope, $location, $window) {
$rootScope.$on("$routeChangeStart",
(event, current, previous, rejection) => {
console.log($window.location.href);
})
}])
But - what do I do after that? I can filter out only that specific path where #/checkout is hit but where do I redirect the site to? Not sure if this is even worth an edit but I thought I will mention it for completeness.
My ONLY option it seems is to upgrade to Angular 8 or higher but as I am so close to the deadline, I will like to explore all the options with Angular 1.x first.
Thanks
I am using two app modules in this app. Why do I get this error? I define the navCtrl in my index.html file where ng-view is like this:
<body ng-app="ciscoImaDashboardApp" ng-controller="navCtrl">
Error: [ng:areq] Argument 'navCtrl' is not a function, got undefined
What am I doing wrong? Am I getting this because I define angular.module in all my js files?
Routes JS:
angular.module('ciscoImaDashboardApp', ['ciscoImaDashboardAdmin', 'ngRoute'])
.config(function ($routeProvider) {
$routeProvider
.when('/admin', {
templateUrl: 'views/admin.html'
})
.when('/', {
templateUrl: 'views/welcome.html',
controller: 'welcomeCtrl'
})
.when('/overall-results', {
templateUrl: 'views/overall.html',
controller: 'overallCtrl'
})
.when('/swim-lane-results', {
templateUrl: 'views/swim-lane.html',
controller: 'swimlaneCtrl'
})
.when('/key-exemplifiers', {
templateUrl: 'views/key-exemplifiers.html',
controller: 'petalCtrl'
})
});
Second Module:
angular.module('ciscoImaDashboardAdmin',[])
.controller('minisCtrl', function ($scope) {
});
Nav JS:
angular.module('ciscoImaDashboardApp',['ciscoImaDashboardAdmin'])
.controller('navCtrl', function($scope, navService, $location, dummyData) {
});
right way :
angular.module('ciscoImaDashboarAdmin')
.controller('minisCtrl', function ($scope) {
});
remove dependency practice in the second time
from angular js documentation you can find below block check the link here
Only one AngularJS application can be auto-bootstrapped per HTML document. The first ngApp found in the document will be used to define the root element to auto-bootstrap as an application. To run multiple applications in an HTML document you must manually bootstrap them using angular.bootstrap instead. AngularJS applications cannot be nested within each other.
I understand how to make a basic single page app with ng-view, and routing the templates into the index.html. However, I want to separate the website into the Home section (views: Home, About, Registration, Login), then when the user logs in they go to a dashboard which has its own set of views. The Dashboard (/dashboard/user:id) and Home Section (/, /about, etc.) would have separate base templates.
Would this just be two separate apps altogether with different base templates? Anyone have experience setting something like that up?
If you are talking about only changing the views you can use the $routeProvider to define your templates, controllers, etc. Have a look at ui-route "Nested States & Views" at https://github.com/angular-ui/ui-router
$routeProvider
.when('/', {
templateUrl: 'template/home/home.tpl.html',
controller: 'LomeCtrl',
controllerAs: 'vm'
})
.when('/dashboard/user:id',{
templateUrl: 'template/dashboard/dashboard.tpl.html',
controller: 'dashboard',
controllerAs: 'vm'
})
.otherwise({
redirectTo: '/'
});
Another approach you can take it to create a provider to display the template based on user login status.
angular.module('myApp', ['ngRoute', 'loginService'])
.config(['$routeProvider', 'loginCheckerProvider', function($routeProvider, loginCheckerProvider) {
$routeProvider.
when('/', {
templateUrl: (loginCheckerProvider.isLoged()) ? 'loggedin.html' : 'loggedout.html'
//controller: 'aboutCtl',
})
.otherwise({
redirectTo: '/'
});
}]);
And the provider:
(function () {
'use strict';
function loginChecker() {
this.$get = angular.noop;
//Do your logics to check if user is loggedin and add the result to the return below
//toggle the return below between true and false
this.isLoged = function(){
return true;
}
}
angular.module('loginService',[])
.provider('loginChecker', loginChecker);
})();
I created a plunker to test and it is working. To test it go to loginservice.js file and toggle the return to true/false, you will see the template updating.
Is there a way to build an URL based on the defined Angular routes? Something like Symfony does (http://symfony.com/doc/current/book/routing.html#generating-urls).
Here is an example of how it would be used:
app.config(['$routeProvider', function($routeProvider) {
$routeProvider
.when('/document/:documentId', {
name: 'document',
templateUrl: 'partials/document.html',
controller: 'documentController'
});
}]);
Then in templates we could use something like:
View document
That would be compiled into:
View document
I have user $stateParams (from angular-ui-router) for this.
.controller('MainCtrl', function ($scope, $stateParams) {
$scope.link = $stateParams.documentId;
});
UI Router wiki on Github
I am trying to create an Angular Dynamic Routing. My routing is like this:
angular.module('myApp', ['myApp.filters', 'myApp.services', 'myApp.directives']).
config(['$routeProvider', function ($routeProvider) {
$routeProvider.when('/', { templateUrl: 'partials/blank.html' });
$routeProvider.when('/:name', { templateUrl: 'partials/blank.html', controller: PagesController });
$routeProvider.otherwise({redirectTo: '/'});
}]);
Here I am using $http to get a template file inside a controller and compile it to a div id like this:
function PagesController($scope, $http, $route, $routeParams, $compile) {
$route.current.templateUrl = 'partials/' + $routeParams.name + ".html";
$http.get($route.current.templateUrl).then(function (msg) {
$('#view-template').html($compile(msg.data)($scope));
});
}
In the template view, I have a div like this:
<div id="view-template" ng-view></div>
I thought the above code will compile and add the html data to the div but I am receiving the error that says: $ is not a function. What have I got wrong here?
EDIT: After the help from the comments and answers below
SOLUTION:: I was playing around with this a bit more and I went with another solution for this. I added the $route.current.templateUrl to the $scope.theTemplateUrl and then used ng-include in the template file. That did the trick and I also dont need to use the jquery $ function to manipulate the DOM.
Please make a fiddle. The limited scope of this snippet inhibits help :)
By just looking at what you are doing I can only make a few recommendations. But I think your issue lies in .html().
Stop using jQuery while you learn Angular.
Use $scope to change content on page. Instead of
$('#view-template').html($compile(msg.data)($scope));
do this
$scope.viewTemplate = msg.data
then use angular in your view :)
Only use the controller to coordinate the flow of information. There should not be and DOM manipulation happening here. The DOM should reflect a state of the controller.
Define routes in your app config. This is not correct.
$route.current.templateUrl = 'partials/' + $routeParams.name + ".html";
I have some example site in my github repo that you can look at if you want to see a few full sites working: https://github.com/breck421
It seems like you have missed some key parts of Angular. Make sure you take your time and learn it right. It will make you life much easier later.
Thanks,
Jordan
Added for a route provider example:
MyApp.config(['$routeProvider', function($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'js/views/index.html',
controller: 'AppController',
activeTab: 'home'
})
.when('/home', {
templateUrl: 'js/views/index.html',
controller: 'AppController',
activeTab: 'home'
})
.when('/thing1', {
templateUrl: 'js/views/thing1.html',
controller: 'Thing1Controller',
activeTab: 'thing1'
})
.otherwise({redirectTo: 'home'});
}]);
Then use links like this: Components
EDIT Adding a compile directive per request:
angular.module('CC.directive.Compile', [], function($compileProvider) {
$compileProvider.directive('compile', ['$compile', function($compile) {
// directive factory creates a link function
return function(scope, element, attrs) {
scope.$watch(
function(scope) {
return scope.$eval(attrs.compile);
},
function(value) {
element.html(value);
$compile(element.contents())(scope);
}
);
};
}]);
});
The $ function is defined by jQuery, not angular. Make sure that you have included the jQuery library in order to use $