From 1 to 3 controllers in Angular - angularjs

I'm new to angularJS so I'm still learning the "angular way" of doing things and therefore seek for advice.
I started building my login/register/forgotten_password views which now work perfectly fine. So the routing looks basically like this:
mainApp.config(function ($routeProvider) {
$routeProvider
.when('/login',
{
controller: 'loginCtrl',
templateUrl: 'views/login.html'
})
.when('/register',
{
controller: 'registerCtrl',
templateUrl: 'views/register.html'
})
.when('/dashboard',
{
controller: 'dashboardCtrl',
templateUrl: 'views/dashboard.html'
})
})
Now here's the problem and/or question I have :
After a successful login, you get redirected to the dashboard which gets loaded into ng-view. The dashboard is indeed the view but there should be more controllers and templates once you enter the app (sidebar, topbar, chat...).
How would you approach this ?
I also have a globalCtrl on the html element to handle other things, just in case that information might be helpful in any way.

You shouldn't think in controllers anymore. Rather think in "components". There are lots of articles on the internet on how to learn this (better) approach. Here is one to start: Refactoring Angular Apps to Component Style
tl;dr; Create a component (element directive) for every section/part of your view. In your case a <dashboard>, <sidebar>, <topbar>, ...
You can (and should) route to components! See this issue for more information. Here is a "real life" example on how to achieve this: https://github.com/ui-router/sample-app-ng1

This is the con giving of using $routeProvider in Angular JS. When you use a $routeProvider to define routes in angular JS, a single route can only point to a single view and there is no concept of nested views using $routeProvider.
And when you talk about having more than one template inside the view, you are talking about having nested views inside a single view. Unfortunately Angular's $routeProvider doesn't provide that. But now comes the ui-router, which replace the concept of route with states. You can define multiple sub states in a state and each sub state can point to different template. Look at the following link and follow simple steps to power up views and nested views in your app.
ui-router

Related

How to use angularjs config block?

I am new to angularJS and trying to learn it. I came across config function
where I see two different arguments as in below example.
Example 1
dashboardApp.config(function($stateProvider, $urlRouterProvider) {
//$urlRouterProvider.when('', '/add');
$stateProvider.state('add',
{
url:'/add?month&year',
templateUrl: 'partial/add.html',
controller: 'AddListController'
})
});
Example 2
gm.config(['$routeProvider', 'Path', function($routeProvider, Path) {
$routeProvider.when('/login', {
templateUrl: Path.view('application/authentication/login.html'),
controller: 'authController'
});
}]);
In the first example, config has a function parameter. And in second example config has array parameter.
Can someone please explain to me what is the difference between these two approaches and when to use which?
There are two differences here. The first example is providing configuration for Angular UI Router, whereas the second is using ngRoute.
The difference in syntax that you noted is the difference between having code that will not withstand minification (first example) and code that will withstand minification.
+1 to the previous answer pointing out $stateProvider is angular ui-router syntax. I would also point out that declaring $routeProvider has different syntax than other angular items like services and controllers.
You should use ui-route provider as it is better than ngRoute,
ui-router allows you to code your templates in a nested form

using ui.router to dynamic load pages

I'm a newbie in AngularJS, and I was using ui.router.
What I am trying to do is load html from different portals, like:
/s3/home
/goo/home
/gle/home
All prefix like s3, goo, gle are from backend, I have to get it first then load my pages, any idea for this, any way to put a variable in relative path, like
/{{portal}}/home
Mockup for expression:
angular.module('app')
.config(function ($stateProvider) {
$stateProvider
.state('{{portal}}.home', { //portal from backend
url: '/',
views: {
'content#': {
templateUrl: 'scripts/app/{{portal}}/home.html', //portal from backend
controller: 'MainController'
}
}
});
})
Find a way to do it, dynamic templateURL will do the same thing
http://fredparke.com/blog/angularjs-directive-dynamic-template
I want to use it in Javascript, is it possible
No i'm afraid not. Use Curly braces to bind expressions to elements in your html. I think you need to rethink more fundamentally your application and why you want to have "variable" template urls in such a way. Try and read up on REST as that's probably what you want to have for your backend. The frontend can then parameterise requests via url/query parameters

Unable to route non existing paths in Angularjs

I am unable to route the path code/:code in my website. I receive the following error:
Firefox can't find the file at /C:/Code/dola/mobileweb/app/code/123
default.htm is located in the app folder.
I am using the mobileangularui framework. I have the following routes declared (among others):
app.config(function ($routeProvider) {
$routeProvider.when('/', { templateUrl: 'codeview.htm', reloadOnSearch: false });
$routeProvider.when('/code/:code', { templateUrl: 'codeview.htm', reloadOnSearch: false });
});
Everything works fine, except when I try e.g. code/12345.
This route is intended for a call from outside, e.g. www.mywebsite.com/code/12345.
I see two issues. First is re-declaring the $routeProvider unnecessarily. The second is you don't have an "otherwise" clause to catch everything you aren't already.
Also, not an error, but good practice to follow; you are missing a controller and controllerAs explicit directive for each entry. Try this:
app.config(function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'codeview.htm'
, controller: 'HomeController'
, controllerAs: 'vm'
, reloadOnSearch: false
})
.otherwise({
redirectTo: '/'
})
});
This was based on the assumption that '/code/:code' is not its own page. The option is easy to add/change if this is not the case, following the above model.
Hope this helps.
-C§
-edit-
It looks as though the best way to do this (as with what I've done in my current project for such needs) is to store the code into a global (model) variable and call the redirect using $location.path('/');. Something like the below would be part of the click-function:
DataService.code = vm.code; //the code value selected
$location.path('/');
And the resulting page would have as part of its initialization routine:
vm.code = DataService.code; //retrieves the code from memory
//and uses it to populate the page appropriately
I'm unfamiliar with how to specify a URL and have it read what page it should populate based on the trailer, aside from using PHP to catch the URL extension with the index and a $_GET redirection process. I know this can be achieved using AJAX or a Jquery catch, but I'm still somewhat new to JavaScript as a whole and not sure what the process would look like.
Alternatively, you could designate a page for each possible code (ex: 12345.html || 12345.php).
Hope this also helps.
-C§

Is this the correct use for a Directive?

I have been tasked with setting up a initial application structure for a large angular application, I came across a few blog posts that basically said everything should be a directive (which I mostly agree with) but I have a feeling I have took this idea too far..
what I have got is basically - when you navigate to portal ui-router will load the portal template from the templates folder, all that's inside that actual template is <portal-view></portal-view.. the portalView directive basically the entire view wrapped up in a directive.
Route
angular.module('portal').config([
'$stateProvider', '$urlRouterProvider', function ($stateProvider, $urlRouterProvider) {
$stateProvider.state('portal', {
url: "/",
templateUrl: "templates/portal.tpl.html"
});
}]);
portal.tpl.html
<div class="container">
<portal-view></portal-view>
</div>
portalView directive
angular.module('portal').directive('portalView', function() {
return {
controller: 'portalController',
controllerAs: 'vm',
templateUrl: "/directives/portalView/portalView.tpl.html"
}});
portalView folder
portalView
portalView.controller.js
portalView.js
portalView.less
portalView.tpl.html
In my head this seems a good idea but I can it becoming a chore when we start adding more view to the application but I am hoping some angular pro will tell me this is the best way to do it :)
Any help, advice and links would be much appreciated!
Componentizing the view and putting it into directive looks like a smart idea to me. This will ease the migration to another router also if it takes place.
portal.tpl.html is unnecessary if you plan to follow this practice, template: '<portal-view></portal-view>' would be enough. But don't reject it if you have plans on using the template for css and js asset loading (using the scripts in templates isn't straight-forward, but it is possible), it would fit the scheme quite well.

AngularJS routing with ng-view relative to HTML page

I am quite new to Angular and now trying to make a simple routing with it. I have my landing page, currently called index2.html, containing some .js and .css includes and a div containing <ng-view></ng-view> where my content should go into.
My app.js looks like this:
var module1 = angular.module('module1', ['ngRoute']);
module1.config(function($routeProvider, $locationProvider){
$routeProvider.when("/",
{
templateUrl: "page1.html",
controller: "uiCtrl"
}
).when("/:param",
{
templateUrl: "page1.html",
controller: "uiCtrl"
}
).when("/transactions",
{
templateUrl: "page2.html",
controller: "uiCtrl"
});
});
But actually this does quite confusing things. Calling http://myurl.com/index2.html, the content of page1.html is properly loaded into the ng-view. So far, so good, but calling index2.html/123 gives my a Not Found instead of interpreting 123 as a parameter. I don't know why, but to make 123 a paremeter i have to call index2.html#123, which works, but then instantly updates the url to index2.html#/123.
Calling index2.html/transactions doesn't work at all. How can i call my /transactions route?
EDIT: If this is useful, i am using JQueryMobile as well in these pages.
I finally got what I want by getting the HTML5 mode work, which makes things so much easier.
After setting $locationProvider.html5Mode(true); I had to re-configure my webserver, what I wasn't able to manage until I found this nice guide: https://github.com/angular-ui/ui-router/wiki/Frequently-Asked-Questions#how-to-configure-your-server-to-work-with-html5mode
Now I can access each of my routes at the conventional way using a slash. Parameters can be passed with ? and &, as usual and I don't need to grapple with confusing hashtags and self-changing url's anymore.

Resources