AngularJS uiRouter access controller from other view - angularjs

I have simple hierarchical state:
angular
.module('App.Module.Suppliers', [])
.config(function($stateProvider) {
return $stateProvider
.state('suppliers', {
url: '/suppliers',
views: {
main: {
templateUrl: 'views/layouts/wrapper.html'
}
}
})
.state('suppliers.edit', {
url: '/:id',
views: {
entity_view: {
templateUrl: 'views/layouts/foo.html'
}
}
})
.state('suppliers.edit.details', {
url: '/edit',
views: {
entity_sub_view: {
controller: function () {
this.foo = {bar: "TEST HEADER"};
},
controllerAs: 'vm',
templateUrl: 'views/layouts/main.html'
}
}
});
});
main and entity_view views are generic for all entities and only entity_sub_view changes with core information.
Now in entity_view I want to use some value like <h2>{{vm.foo.bar}}</h2> but it seems that I can't access vm inside these parent states.
Is there a way to pass this and other parameters to parent states to use?

So I found solution that fits my need. Basically you can set controllerAs to top-most state and access it via $scope:
angular
.module('App.Module.Suppliers', [])
.config(function($stateProvider) {
return $stateProvider
.state('suppliers', {
url: '/suppliers',
views: {
main: {
templateUrl: 'views/layouts/wrapper.html'
controller: function () {
this.foo = null;
}
controllerAs: 'mainCtrl'
}
}
})
.state('suppliers.edit', {
url: '/:id',
views: {
entity_view: {
templateUrl: 'views/layouts/foo.html'
}
}
})
.state('suppliers.edit.details', {
url: '/edit',
views: {
entity_sub_view: {
controller: function () {
this.foo = {bar: "TEST HEADER"};
},
controllerAs: 'vm',
templateUrl: 'views/layouts/main.html'
}
}
});
});
And in some controller do
this.$scope.mainCtrl.foo = {bar: "TEST HEADER"};
In view
{{mainCtrl.foo.bar}}

Related

How do I get URL parameters on AngularJS SPA when using stateProvider for routing

For example, on the last state on the below code I want to get the value of "category" URL parameter so that I can use it to retrieve some from the database
var app = angular.module("myApp",["ui.router"]);
app.config(function($stateProvider, $urlRouterProvider){
$urlRouterProvider.otherwise("/");
$stateProvider
.state("main", {
url: "/",
views: {
"slider": {
templateUrl: "slider.html"
},
"departments": {
templateUrl: "departments.html"
},
"brands": {
templateUrl: "brands.html"
}
}
})
.state("cart", {
url: "/cart",
views: {
"cart": {
templateUrl: "../account/cart.php"
}
}
})
.state("department", {
url: "/department/:category",
views: {
"department": {
templateUrl: "department.php"
}
}
});
});
Create a controller, pass stateParams and instantiate the controller within the views of the last state
.state("department", {
url: "/department/:category",
views: {
"department": {
templateUrl: "department.php",
controller: "myController"
}
}
});
});
app.controller('myController', function($stateParams) {
var param = $stateParams.category;
document.getElementById("category").value = param;
});

Passing resolved data to child state in Ui-Router

So, I have a state where the resolve spits out an array which shows correctly on the frontend.
But I can't seem to be able to pass the parent resolve data to the child state.
$stateProvider.state('berliner', {
url: '/berlinerliste',
params : {search: 'Berliner 2017'},
resolve: {
fair: function(SearchService, $stateParams) {
return SearchService.getAllExhibitors($stateParams.search);
}
},
views: {
'header': {
templateUrl: 'header.htm'
},
'main':{
templateUrl: 'bl2017.htm',
controller: function($scope, fair){
$scope.fair = fair;
console.log($scope.fair);
}
}
}
})
.state('berliner.exhibitor', {
url: '/{id}',
resolve: {
exhibitor: function($stateParams, fair) {
var slug = $stateParams.id;
return slug;
}
},
views: {
'header': {
templateUrl: 'header.htm'
},
'wop':{
templateUrl: 'exhibitor.htm',
controller: function($scope, exhibitor, $filter){
$scope.fairs = $scope.fair;
console.log($scope.fair);
$scope.chosenexhibitor = $filter("filter")($scope.fairs, {'slug':exhibitor}, true);
console.log($scope.chosenexhibitor);
}
}
}
})
All the console log come out undefined.
What am I missing?
PLUNKR
Here's a Plunkr to examplify the issue.
I would say, that the concept should work.. just:
controller belongs to view. not to all views: {}
E.g. this (wrong)
// each view can have controller,
// but views : {} property 'controller' is not used at all
views: {
'header': {
templateUrl: 'header.htm'
},
'wop':{
templateUrl: 'exhibitor.htm',
},
controller: function($scope, exhibitor, $filter){
$scope.fairs = $scope.fair;
console.log($scope.fair);
$scope.chosenexhibitor = $filter("filter")($scope.fairs, {'slug':exhibitor}, true);
console.log($scope.chosenexhibitor);
}
should be adjusted as that:
views: {
'header': {
templateUrl: 'header.htm'
controller: function($scope, exhibitor, $filter){
$scope.fairs = $scope.fair;
console.log($scope.fair);
$scope.chosenexhibitor = $filter("filter")($scope.fairs, {'slug':exhibitor}, true);
console.log($scope.chosenexhibitor);
}
},
'wop':{
templateUrl: 'exhibitor.htm',
controller: ...
There is an example, how
parent does resolve
child view's controller consumes it
states:
.state('parent', {
url: "/parent",
templateUrl: 'tpl.html',
resolve: {
example: ['$timeout', function($timeout){
return $timeout(function(){
return {x: 1}
},100)
}],
},
})
.state('parent.child', {
url: "/child",
templateUrl: 'tpl.html',
controller: 'ChildCtrl',
})
child controller
.controller('ChildCtrl', ['$scope', 'example', function ($scope, example) {
console.log(JSON.stringify(example));
}])
Check it here

Set a defaults for views in Ionic AngularJS

I'm learning Ionic framefork to develop an app.
I defined an abstract state like this:
.state('app', {
url: '',
abstract: true,
templateUrl: "templates/default.html"
})
My default.html looks like this:
<ion-side-menus>
<ion-side-menu-content>
<div ui-view="headerview"></div>
<div ui-view="contentview"></div>
</ion-side-menu-content>
<div ui-view="menuview"></div>
And then I declared all my actual states
.state('app.contacts', {
url: '/contacts',
views: {
'headerview': {
templateUrl: "templates/common/header.html" ,
controller: 'headerControllers'
},
'menuview': {
templateUrl: "templates/common/menu.html"
},
'contentview': {
templateUrl: 'templates/contacts.html',
controller: 'contactControllers'
}
}
})
.state('app.partners', {
url: '/partners',
views: {
'headerview': {
templateUrl: "templates/common/header.html" ,
controller: 'headerControllers'
},
'menuview': {
templateUrl: "templates/common/menu.html"
},
'contentview': {
templateUrl: 'templates/partners.html',
controller: 'partnerControllers'
}
}
})
This works like a charm, but I noted that header and menu views will be the same in almost all of my states! That's not very DRY. There is a way to define a default that I can overwrite when needed?
Thank you,
one way to do this is to create store your path in a variable and use it for all your state.
in the begining of your function make :
var defaultHeader = 'templates/common/header.html';
var defaultHeaderController = 'headerControllers';
var defaultMenu = 'templates/common/menu.html';
then during the init of your state you will be able to do :
.state('app.contacts', {
url: '/contacts',
views: {
'headerview': {
templateUrl: defaultHeader ,
controller: defaultHeaderController
},
'menuview': {
templateUrl: defaultMenu
},
'contentview': {
templateUrl: 'templates/contacts.html',
controller: 'contactControllers'
}
}
})
.state('app.partners', {
url: '/partners',
views: {
'headerview': {
templateUrl: defaultHeader ,
controller: defaultHeaderController
},
'menuview': {
templateUrl: defaultMenu
},
'contentview': {
templateUrl: 'templates/partners.html',
controller: 'partnerControllers'
}
}
})
Like that if you want to overwrite the default view you can.
And to update it you have only one place to modify the code.

AngularJS UI-router stateprovider issue

Im currently using Ionic and was playing with a app with tabs. (I.e has a bottom bar with icons).
Right now I want to remove it but ended messing up the routing. The devtools does not show any errors. I cannot transit from login page to main "posts" page. On login, clicking the login button does do anything. I have edited the state.go('') in the controllers accordingly.
Ill show before and after the changes.
Would it make sense to remove views :{} totally? I find it complicates things and I do not use nested views. Not sure if modal page requires views.
Appreciate some help/ advice on how to get around the error.
Before
.state('tab', {
url: '/tab',
abstract: true,
templateUrl: 'templates/tabs.html'
})
// --------Authenticate states ----------------
.state('auth', {
url: '/auth',
templateUrl: 'templates/auth.html',
controller: 'StartCtrl'
})
.state('register', {
url: '/register',
templateUrl: 'templates/register.html',
controller: 'AuthCtrl',
})
.state('login', {
url: '/login',
templateUrl: 'templates/login.html',
controller: 'AuthCtrl',
})
// ---------- Main states ---------------------
.state('tab.posts', {
url: '/posts',
views: {
'tab-posts': {
templateUrl: 'templates/tab-posts.html',
controller: 'PostsCtrl'
}
}
})
.state('tab.newpost', {
url: '/newpost',
views: {
'tab-posts': {
templateUrl: 'templates/tab-newpost.html',
controller: 'NavCtrl'
}
}
})
.state('tab.posts.view', {
url: '/posts/:postId',
views: {
'tab-posts#tab': {
templateUrl: 'templates/tab-showpost.html',
controller: 'PostViewCtrl'
}
}
})
.state('tab.profile', {
url: '/users/:userId',
views: {
'tab-posts': {
templateUrl: 'templates/tab-profile.html',
controller: 'ProfileCtrl',
}
}
})
After
.state('/', {
url: '/',
abstract: true,
templateUrl: 'templates/tab-posts.html'
})
// --------Authenticate states ----------------
.state('auth', {
url: '/auth',
templateUrl: 'templates/auth.html',
controller: 'StartCtrl'
})
.state('register', {
url: '/register',
templateUrl: 'templates/register.html',
controller: 'AuthCtrl',
resolve: {
user: function(Auth){
return Auth.resolveUser();
}
}
})
.state('login', {
url: '/login',
templateUrl: 'templates/login.html',
controller: 'AuthCtrl',
resolve: {
user: function(Auth){
return Auth.resolveUser();
}
}
})
//----------- Main states--------------------
.state('posts', {
url: '/posts',
views: {
'posts': {
templateUrl: 'templates/tab-posts.html',
controller: 'PostsCtrl'
}
}
})
.state('newpost', {
url: '/newpost',
views: {
'posts': {
templateUrl: 'templates/tab-newpost.html',
controller: 'NavCtrl'
}
}
})
.state('posts.view', {
url: '/posts/:postId',
views: {
'posts#': {
templateUrl: 'templates/tab-showpost.html',
controller: 'PostViewCtrl'
}
}
})
.state('profile', {
url: '/users/:userId',
views: {
'posts': {
templateUrl: 'templates/tab-profile.html',
controller: 'ProfileCtrl',
}
}
});
Updated for Levi
app.factory('Auth', function($firebase, $firebaseAuth, FIREBASE_URL, $rootScope) {
var ref = new Firebase(FIREBASE_URL);
var auth = $firebaseAuth(ref);
var Auth = {
register: function (user) {
return auth.$createUser(user.email, user.password);
},
login: function (user) {
return auth.$authWithPassword(user);
},
logout: function() {
auth.$unauth();
},
resolveUser: function() {
return auth.$waitForAuth();
},
signedIn: function() {
return !!Auth.user.provider;
},
createProfile: function (user) {
var profile = {
username: user.username,
md5_hash: user.md5_hash
};
var profileRef = $firebase(ref.child('profile'));
return profileRef.$set(user.uid, profile);
},
user: {}
};
auth.$onAuth(function (user){
if(user) {
angular.copy(user, Auth.user);
Auth.user.profile = $firebase(ref.child('profile').child(Auth.user.uid)).$asObject();
console.log(Auth.user);
} else {
console.log('logged out');
if (Auth.user && Auth.user.profile) {
Auth.user.profile.$destroy();
}
angular.copy({}, Auth.user);
}
});
return Auth;
});
Image for error trace
Remove you resolver from your login state.
.state('login', {
url: '/login',
templateUrl: 'templates/login.html',
controller: 'AuthCtrl',
})
If a someone want to go to login, you can't force him to be logged in.

Angular UI Router - Access Custom Data in Children's Resolve {}

How come this Inherited Custom Data data is not accessible in the child state main.loadbalancer.vips in the resolve: {} function hello?
angular.module("main.loadbalancer", ["ui.bootstrap", "ui.router"]).config(function($stateProvider) {
return $stateProvider.state("main.loadbalancer", {
data: { readonly : false },
url: "device/:id",
views: {
"content#": {
templateUrl: "loadbalancer/loadbalancer.html",
controller: "LoadBalancerCtrl"
}
}
}).state("main.loadbalancer.vips", {
url: "/vips",
templateUrl: "loadbalancer/vip-table.html",
resolve: {
hello: function(data) {
console.log(data);
}
},
controller: "VipListCtrl"
})
That data should be accessible in the $state object if you inject it ($state):
$state.$current.data.readonly
I had to use this.data...
}).state("main.loadbalancer.vips", {
url: "/vips",
templateUrl: "loadbalancer/vip-table.html",
resolve: {
hello: function() {
console.log(this.data);
}
}

Resources