How to make tabs in angularJS have separate controllers? - angularjs

Right now i am using routeProvider to change between views which works awesome. But now i want to create a view which contains 4 different tabs which should contain 4 different controllers. ive read here that it could be done with stateProvider:
Angular ui tab with seperate controllers for each tab
here is my code:
var WorkerApp = angular.module("WorkerApp", ["ngRoute", 'ngCookies', "ui.bootstrap", "ngGrid", 'ngAnimate', 'ui.router']).config(function ($routeProvider, $stateProvider) {
$routeProvider.
when('/login', {
templateUrl: 'Home/Template/login', resolve: LoginCtrl.resolve
})
.when('/register', { templateUrl: 'Home/Template/register', resolve: RegisterCtrl.resolve })
.when('/', { templateUrl: 'Home/Template/main', resolve: MainCtrl.resolve })
.when('/profile', { templateUrl: 'Home/Template/profile', controller: "ProfileController" })
.when('/contact', { templateUrl: 'Home/Template/contact', controller: "ContactController" })
$stateProvider.state('tabs', {
abstract: true,
url: '/profile',
views: {
"tabs": {
controller: "ProfileController",
templateUrl: 'Home/Template/profile'
}
}
}).state('tabs.tab1', {
url: '/profile', //make this the default tab
views: {
"tabContent": {
controller: "ProfileController",
templateUrl: 'Home/Template/profile'
}
}
})
.state('tabs.tab2', {
url: '/tab2',
views: {
"tabContent": {
controller: 'Tab2Ctrl',
templateUrl: 'tab2.html'
}
}
});
});
but i cant get it really to work because default of routeprovider is set to send over to work because my routeprovider is sending over to "/" on default, which makes "/tabs" invalid. so i cant actully figure out if it is possible to switch to states on specific url. Or change state on specific URL in routeProvider?

I can't tell you for sure exactly what's wrong with the code you've provided, but I'm using Angular UI-Router with the same use case you described, and it's working for me. Here's how I have it configured and how it's different from your configuration:
I don't use $routeProvider at all (none of your $routeProvider.when statements). I'm pretty sure you should not be using $routeProvider since you're using $stateProvider.
I have one use of the $urlRouterProvider with an 'otherwise' statement to specify a default URL:
$urlRouterProvider.otherwise("/home");
My calls to $stateProvider.state is a little different from yours. Here's the one for the parent view of the tabs:
$stateProvider.state('configure', {
url: "/configure",
templateUrl: 'app/configure/configure.tpl.html',
controller: 'ConfigureCtrl'
});
Here's an example of the child state (really the same except for the state name being parent.child format, which you already have in your code; and I added a resolve block but you could have that on the parent as well):
$stateProvider.state('configure.student', {
url: "/student",
templateUrl: 'app/configure/student/configure.student.tpl.html',
controller: 'ConfigureStudentCtrl',
resolve: {
storedClassCode: function($q, user, configureService) {
return configureService.loadMyPromise($q, user);
}
}
});
Also, I'm using version 0.2.8 of Angular UI-Router with version 1.2.9 of Angular. I think this would work with any version of Angular 1.2.0 or later.

Related

AngularJS ui-route $state, $scope and controller event loading

I'm kinda new with this UI-Route I know it's very powerful but i'm having problem working on it, I have use AngularJS before but not that often and this time i really want to use it so given that my questions goes like this (I've search everywhere regarding this but no luck for me):
The scenario is I have Index.html on that page I have two views
which are "News" and "Testi" both are confined on a div
So knowing that I added App.js (which will contain the initial code for my AngularJS implementation):
var app = angular.module('wrcheese', ['ui.router']);
app.config(function ($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/home');
$stateProvider
.state('home', {
url: '/home',
templateUrl: '/Views/Index.html',
views: {
'main': {
templateUrl: '/Views/App/home.html'
},
'testi': {
templateUrl: '/Views/App/testimonial.html'
}
},
controller: 'HomeCtrl'
})
});
and my controller goes like this (homeController.js)
'use strict';
app.controller('HomeCtrl', function ($scope, $state) {
$scope.welcomeMessage = 'Welcome to WeRCheese';
});
my problem is that I'm trying to access that "welcomeMessage" on my home.html page but wasn't able to, what strange is that when i put in a breakpoint on my controller it wasn't hit it seems the controller does not exist.
Maybe I'm doing it wrong because I don't have any problem when i use ngRoute before.
Lastly, how do you add in a factory?
app.controller('HomeCtrl', function ($scope, $state, homeFactory) {
});
or
app.controller('HomeCtrl', ['$scope', '$state', 'homeFactory', function ($scope, $state, homeFactory) { }]);
TIA.
I was having problem adding a comment my mistake for not realizing that I need to edit my question here. Anyway for my problem I was able to load the controller via different page but I'm still having problem loading the controller on the Index.html i tried updating the .state -> tried on different approach i.e. use '', '/', 'index' in the views.
.state('home', {
url: '', or '/', or 'index',
templateUrl: '/Views/Index.html',
controller: 'HomeCtrl'
But still the controller is not loading, to be specific I have tried adding this line on my Index.html {{ welcomeMessage }} just to verify that the controller was/has been loaded properly.
When you have add views property to a state, the original template, templateUrl properties will be ignored, so you have to bind controllers in views.
$stateProvider.state('home', {
url: '/home',
templateUrl: 'Views/Index.html', <----- will be ignored
views: {
'main': {
templateUrl: 'Views/App/home.html',
controller: 'HomeCtrl'
},
'testi': {
templateUrl: 'Views/App/testimonial.html',
controller: 'HomeCtrl'
}
},
controller: 'HomeCtrl' <----- will be ignored
})
For factory: after defined it, you can inject it by both the ways you posted.
refer this plunker.
var app = angular.module('wrcheese', ['ui.router']);
app.config(function ($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/home');
$stateProvider
.state('home', {
url: '/home',
views: {
'main': {
templateUrl: '/Views/App/home.html',
controller : 'HomeCtrl'
},
'testi': {
templateUrl: '/Views/App/testimonial.html',
controller : 'HomeCtrl'
}
},
})
});
you can do this
.state('home', {
url: '/home',
views: {
'#': {
templateUrl: '/Views/Index.html',
controller: 'HomeCtrl',
controllerAs: 'vm'
},
'main#home': {
templateUrl: '/Views/App/home.html'
},
'testi#home': {
templateUrl: '/Views/App/testimonial.html'
}
}
});
using controllerAs is a best practice

Ionic controllers alias not working when using sidebar

I have an app built using ionic framework, I follow the instructions on ionicframework learn page and now I am using the native sidemenu. The problem is, I can't use controller alias. Here is a snipet of my app.js with the route config:
angular.module('checklist-atendimento', [
'ionic',
'oc.lazyLoad',
'ngStorage',
'ngCordova',
'ngMask'
])
.config(function($stateProvider, $urlRouterProvider, $httpProvider) {
$urlRouterProvider.otherwise('/app/atendimento/1');
$httpProvider.interceptors.push('TratamentoDeErrosService');
$stateProvider
.state('app', {
abstract: true,
url: '/app',
views: {
'conteudo': {
templateUrl: 'app/templates/menu.html'
}
}
})
.state('app.inicio', {
url: '/inicio',
views: {
'menuContent': {
templateUrl: 'app/views/inicio.html',
controller: 'InicioController',
}
}
})
.state('app.atendimento', {
url: '/atendimento/:codMenu',
views: {
'menuContent': {
templateUrl: 'app/views/atendimento.html',
controller: 'AtendimentoController',
controllerAs: 'atendimentoCrl'
}
}
})
});
As you can see, I have 2 states, one without controllerAs (InicioController) and the other using controllerAs (AtendimentoController).
In controller I put
$scope.test ="TEST!!!"
and in the view I put
<b>{{atendimentoCtrl.test}}<b>
Nothing happens, if I use just {{test}}, but the text is shown.
Anyone knows how to do it ?
EDIT:
HERE there is a example of what a talking about:
http://plnkr.co/ohL5HE
Look inside ItemCtrl and inside index.html, on item.html.
I tried use an alias to controller but it don't works.
You need to change
$scope.test ="TEST!!!"
to:
this.test ="TEST!!!"
The issue here is just a typo... This is a controller state
.state('app.atendimento', {
url: '/atendimento/:codMenu',
views: {
'menuContent': {
templateUrl: 'app/views/atendimento.html',
controller: 'AtendimentoController',
controllerAs: 'atendimentoCrl'
}
}
})
where we can see 'atendimentoCrl'. And here is a view statement
<b>{{atendimentoCtrl.test}}<b>
where we can see atendimentoCtrl (compare Ctrl suffix and Crl above)
So, there is missing t in the controllerAs

ui-router named views with route and url

just a quick question. Can named views in the ui-router for angular have routes and an url? And if so, how can I activate them?
I searched through the wiki, but can't find any info on that.
What I want is a app with three different child routes so only one can be active at a time, but they're supposed to be in different views, so I can nicely animate between them with an accordion effect.
Any help there?
Thanks!
EDIT: Here's some code of my routing so far:
function routeConfig($stateProvider, $urlRouterProvider, $locationProvider) {
$stateProvider
.state('home', {
url: '/',
//templateUrl: 'app/main/main.html',
//controller: 'MainController',
//controllerAs: 'main',
views: {
'' : {
templateUrl: 'app/main/main.html',
controller: 'MainController',
controllerAs: 'main'
},
'contact': {
templateUrl: 'app/contact/contact.html',
controller: 'ContactController',
controllerAs: 'contact'
},
'profile': {
templateUrl: 'app/profile/profile.html',
controller: 'ProfileController',
controllerAs: 'profile'
},
'works': {
templateUrl: 'app/works/works.html',
controller: 'WorksController',
controllerAs: 'works'
}
}
});
$urlRouterProvider.otherwise('/');
$locationProvider.html5Mode(true);
}
I'd recommend just creating different states for each view. There's no reason you can't animate smoothly between different states.
So:
function routeConfig($stateProvider, $urlRouterProvider, $locationProvider) {
$stateProvider
.state('home', {
url: '/',
templateUrl: 'app/main/main.html',
controller: 'MainController',
controllerAs: 'main'
})
.state('home.contact', {
templateUrl: 'app/contact/contact.html',
controller: 'ContactController',
controllerAs: 'contact'
})
.state('home.profile', {
templateUrl: 'app/profile/profile.html',
controller: 'ProfileController',
controllerAs: 'profile'
params: {
"user" : {}
}
})
.state('home.works', {
templateUrl: 'app/works/works.html',
controller: 'WorksController',
controllerAs: 'works'
})
}
});
$urlRouterProvider.otherwise('/');
$locationProvider.html5Mode(true);
}
In your ui-sref links, you can pass data to those views using parameters, like this: <a ui-sref="home.profile({user: contact.user}) along with the 'params' section in the state definition as I've included above.
Routing is serverside so if you call any address your serverside routing needs to launch proper html or javascripts which will let you render what you want.
For more accurate answer please respond with more details: what is your serverside engine, which version of angular you use etc.

Configure UI-Router for Multiple Modules

I'm making a project in Angular 1.4, and i'm using ui-router, I have split my project in several sub-modules, there's one 'parent' module (not sure if i'm using the concept of parent and child right) and several 'child' modules.
The 'parent' has routes for the global login, and the two main menus of each group, the groups are: guides, projects; each one of them has it's own 'child' modules some of them are: guides[Web, Mobile, Desktop], projects[Business, Community]. Each module has it's own routes, and what i want is to be able to route the app though each module.
The main routes are:
/
/login
/guides
/guides/login
/guides/web
/guides/mobile
/guides/desktop
/projects
/projects/login
/projects/business
/projects/community
The site has somehow same login concept of SE, people can have a global account, or a single account on a specific module.
What i've tried so far if to make the routes as Doc says:
angular.module('main', ['main.guides', 'main.projects']).config(function ($stateProvider) {
$stateProvider.
state('main', {
url: '/',
templateUrl: './views/index.html',
controller: 'IndexCtrl'
}).
state('login', {
url: '/login',
templateUrl: './views/login.html',
controller: 'LoginCtrl'
}).
state('guides', {
url: '/guides',
templateUrl: './views/guides-menu.html',
controller: 'GuidesCtrl'
}).
state('projects', {
url: '/projects',
templateUrl: './views/projects-menu.html',
controller: 'ProjectsCtrl'
});
});
angular.module('main.guides', []).config(function ($stateProvider) {
$stateProvider.
state('main.guides-login', {
url: '/login',
templateUrl: './views/login.html',
controller: 'LoginCtrl'
}).
state('main.guides-menu', {
url: '/login',
templateUrl: './views/menu.html',
controller: 'LoginCtrl'
}).
state('main.guides-web', {
url: '/web',
templateUrl: './views/web/list.html',
controller: 'ListCtrl'
}).
state('main.guides-mobile', {
url: '/web',
templateUrl: './views/mobile/list.html',
controller: 'ListCtrl'
});
});
angular.module('main.projects', []).config(function ($stateProvider) {
$stateProvider.
state('main.projects-login', {
url: '/login',
templateUrl: './views/login.html',
controller: 'LoginCtrl'
}).
state('main.projects-business', {
url: '/business',
templateUrl: './views/business/list.html',
controller: 'ListCtrl'
}).
state('main.projects-menu', {
url: '/business',
templateUrl: './views/menu.html',
controller: 'ListCtrl'
}).
state('main.projects-community', {
url: '/business',
templateUrl: './views/community/list.html',
controller: 'ListCtrl'
})
});
But don't know how to access to those urls... also would like some opinion about this approach, would there be a better practice?
I created a plunkr to demo your states. I altered the code to use templates instead of templateUrl but that shouldn't change what you are trying to figure out. I made some assumptions about your layout based on the urls provided. If you pop it out into the external viewer you can see the urls being used. Find it here:
http://plnkr.co/edit/9lPQ3GlmH0AEqhzX7lj9?p=preview
Urls in the ui-router are used as part of what specifies the state. So when you want /projects/business you have a state that is a child of projects that has a url of /business. Something like:
state('projects.business', {
url: '/business',
template: '<div> projects business</div>',
controller: 'ListCtrl'
})
The dot notation in the state definition tells the ui router that this is child state of projects. The url value provided is added to the parent state url.
I think your module strategy is solid. You just need to wrap your head about the parent child relationships used in the ui.router.

AngularJS with ui-router and additional state on first request

I am writing an AngularJS Application using ui-router. The states 'home' and 'book' are loaded into the (parent) - ui-view element
My setup for the routes is as following :
.config(function ($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("/home");
$stateProvider
.state('home', {
url: '/home',
templateUrl: '/home2/app'
})
.state('book', {
url: '/book',
templateUrl: '/book/index'
})
.state('book.overview', {
url: '/overview',
templateUrl: '/book/overview'
})
.state('book.edit', {
url: '/edit/:bookid',
templateUrl: '/book/detail',
controller: 'bookeditcontroller'
})
.state('book.create', {
url: '/create',
templateUrl: '/book/detail',
controller: 'bookeditcontroller'
});
});
When the user tiggers the 'book' state (through a href), the template from '/book/index' is loaded and displayed successfully. But on this first request, i also want to load the template from '/book/overview' and displaying it in the child ui-view.
i've already read the topics about the default states under https://github.com/angular-ui/ui-router/wiki/Frequently-Asked-Questions#how-to-set-up-a-defaultindex-child-state
But this is not exactly the behavior i want. Is there a way to tell ui-router when parent state 'book' is loaded, also load 'book.overview' into its (child) ui-view ?
Thanks for you help!
I would say that you will need
Multiple Named Views
This allows us to think in one state - many views
State would look like this
.state('book', {
url: '/book',
views : {
'' : { templateUrl: '/book/index', },
'#book': {templateUrl: '/book/overview' },
}
})
this way, we will place two views into one state.
The first will be injected into index.html/root <div ui-view=""></div>
The second will be placed inside of the templateUrl: '/book/index',
That's how we can play with many views in one (or even more parent, grand parent...) state.
I created a plunker with layout, which does show a bit similar example. The code snippet of the state with many views is:
$stateProvider
.state('index', {
url: '/',
views: {
'#' : {
templateUrl: 'layout.html',
controller: 'IndexCtrl'
},
'top#index' : { templateUrl: 'tpl.top.html',},
'left#index' : { templateUrl: 'tpl.left.html',},
'main#index' : { templateUrl: 'tpl.main.html',},
},
})

Resources