angular state get param child - angularjs

How can I get a param from child?
This is what I do:
$state.go('demo.content', {proces: '10'})
And then in controller 'Main' I need the value of param proces.
.state('demo', {
url: '/',
abstract: true,
views: {
'main': {
templateUrl: './App/main.html',
controller: 'Main'
}
})
.state('demo.content', {
url: '/monitoring',
views: {
'chart': {
templateUrl: './App/chart.html',
controller: 'Chart'
},
'grid': {
templateUrl: './App/grid.html',
controller: 'Grid'
},
params: {proces: '4'}
})

The point here is, that any call to 'demo.content' with different param process should re-call/re-init the controller of such state view.
Other words, only controllers which are part of this state, could consume the process as a part of injected params.
So, if there is really any part in main controller, which needs handle (changing) process id, it should be moved to the demo.content state, as another view
If this is the true, the best we can do is to move that view from parent into state:
.state('demo.content', {
url: '/monitoring',
views: {
'chart': {
templateUrl: './App/chart.html',
controller: 'Chart'
},
'grid': {
templateUrl: './App/grid.html',
controller: 'Grid'
},
// this would do the stuff fro main controller
// based on changing params
'mainProcessor': {
templateUrl: './App/mainProcessor.html',
controller: 'mainProcessor'
}
This, and only this way, you can be sure, that different param value will trigger the "mainProcessor" controller and allow him to do the job

Related

ui.router nested States, nested Views: $rootScope.$on $rootScope.$broadcast doesnt connect

i use $rootScope to send data to a controller from a nested state and view
It works between 'items' and rootSelector,
It does not work between 'detail' and rootSelector
something blocks my rootScope events.
var listState = {
name: 'playlist.list',
parent: 'playlist',
url: '/list?',
resolve: {
playlistsDb: resolvePlaylistsFromDb,
},
views: {
// target the unnamed view in the playlist state
'#playlist': {
templateUrl: 'app/playlists/list/list.html',
controller: 'PlaylistListController',
controllerAs: 'list'
},
// target the content view in the playlist.list state
'content#playlist.list': {
templateUrl: 'app/playlists/list/items/items.html',
controller: 'PlaylistItemsController',
controllerAs: 'items'
},
// target the rootSelector view in the playlist state
'rootSelector#playlist.list': {
templateUrl: 'app/selector/rootSelector.html',
controller: 'rootSelectorController',
controllerAs: 'rootSelector',
resolve: {
selectedPlaylistId: resolveSelectedPlaylistId,
}
}
}
};
I can send and receive events via $rootScope.broadcast and $scope.$on
from PlaylistItemsController "items" to rootSelector
but i can't receive them if they come from the nested "detailState"
var detailState = {
name: 'playlist.list.detail',
parent: 'playlist.list',
url: '/detail/:id',
views: {
'detail#playlist.list': {
templateUrl: 'app/playlists/list/detail/detail.html',
controller: 'PlaylistDetailController',
controllerAs: 'detail',
resolve: {
playlistDb: resolvePlaylistDb,
}
}
}
};
Ok, events didnt go through cause
$scope.$on('removeTrackFromPlaylist'), function (event, args) { }
was no code error in VS2015

controller doesn't work in ui-router

I have this home state in my router config,
.state('home', {
url: '',
controller: 'addMovieCtrl',
views: {
"frontpage": {
templateUrl: '../assets/angular-app/templates/_frontpage.html',
// controller: 'addMovieCtrl'
},
"movieoverview": {
templateUrl: '../assets/angular-app/templates/_movieTemplate.html',
// controller: 'addMovieCtrl'
}
}
})
I want both my views to work with the addMovieCtrl controller, but if I assign the controller in the state (like in the example above) the controller doesn't get called.
When I assign the controller in the view (which I now have commented out) it does get called, but I'm pretty sure I should be able to asign a controller to a state and that adds the controller to all the views. Right?
No, you need to assign a controller to each view. So, your commented out code is the right way to do it.
views: {
"frontpage": {
templateUrl: '../assets/angular-app/templates/_frontpage.html',
controller: 'addMovieCtrl'
},
"movieoverview": {
templateUrl: '../assets/angular-app/templates/_movieTemplate.html',
controller: 'addMovieCtrl'
}
}

Access scope variable from the other controller within the nested state

How to access other state scope variable from another state ctrl?
If in 'session.index.detail' state, I want to access leftPanel scope variable from rightPanel Ctrl is it possible? What I want to do is I have a form in rightPanel, when I click save, I want to add the new data object back to leftPanel list and refresh it after it is successfully added to the database.
.state('session', {
abstract: true,
templateUrl: '/schedule/_session.html'
})
.state('session.index', {
url: '/sessionmang',
views: {
'leftPanel#session': {
controller: 'SessionCtrl',
controllerAs: 'vm',
templateUrl: '/schedule/_sessionPanel.html'
},
'rightPanel#session': {
templateUrl: '/schedule/_sessionDetailPanel.html'
}
}
})
.state('session.index.detail', {
params: {
sessionObj: null,
sessionTypeObj: null
},
views: {
'rightPanel#session': {
controller: 'SessionDetailCtrl',
controllerAs: 'vm',
templateUrl: '/schedule/_sessionDetailPanel.html',
resolve: {
sessionObj: ['$stateParams', function ($stateParams) {
return $stateParams.sessionObj;
}],
sessionTypeObj: ['$stateParams', function ($stateParams) {
return $stateParams.sessionTypeObj;
}]
}
}
}
});
I think the best way is to create a service that holds the data you want to share.
And share it between the controllers.
Or use broadcasting to talk between the controllers and pass data over that way
the simplest way is, you could use events like this.
when you click save, you will do
$scope.$broadcast('myevent', data);
from the rightCtrl and from the leftCtrl you could do
$scope.$on('myevent', function(event,data) {
//do your updates here
})

Nested sates and views in Angular UI Route

Sorry if similar questions have been asked before but I have been strugling to get a certain setup working for a while. I took a working plunker from from an existing question and am trying to tweak it just a little to my needs.
Orginal Plunker: http://plnkr.co/edit/uY1Sl3f0KCTukPGHDRdW
My (slightly) edited fork: http://plnkr.co/edit/hlw4Et00UeGjzxD4Mszi
What I am trying to achieve is a base layout containing a header, footer and unnamed view for the page content. I can do this fine with the original plunker. But when I try to get more fancy and have a structure more like this:
$urlRouterProvider.otherwise('/home/list');
$stateProvider
.state('root', {
abstract: true,
views: {
'#': {
controller: 'RootCtrl',
controllerAs: 'rootCtrl'
},
'header#': {
templateUrl: 'header.html',
controller: 'HeaderCtrl',
controllerAs: 'headerCtrl'
},
'footer#': {
templateUrl: 'footer.html',
controller: 'FooterCtrl',
controllerAs: 'footerCtrl'
}
}
})
And here is the adjusted state definition:
.state('root.home', {
parent: 'root',
url: '/home',
views: {
'#': {
template: '<ui-view></ui-view>',
controller: 'HomeController',
controllerAs: 'homeCtrl'
},
'list#root.home': {
url: '/list',
template: 'homeList.html',
controller: 'HomeController',
controllerAs: 'homeCtrl'
}
},
});
What I am trying to do here is make it so that 'root.home' state is just a base state for prepending the URL 'home' or whatever the url is in my real application. I have tried ready though the ui-route sample app but it's a lot to take in and am going in circles. I'm sure this is simple...
There is a working updated plunker. There is one state definition adjustment.
This was original piece of code:
.state('root.home', {
parent: 'root',
url: '/home',
views: {
'#': {
template: '<ui-view></ui-view>',
controller: 'HomeController',
controllerAs: 'homeCtrl'
},
'list#root.home': {
url: '/list',
template: 'homeList.html',
controller: 'HomeController',
controllerAs: 'homeCtrl'
}
},
});
What was wrong there? Firstly a note - we do not need to define parent: 'root', because our parent is in our name 'root.home'. So, to make it more clear, I decided to keep parent setting, while change the state name into 'home'.
Secondly, we have two views in play for our state, but the second one, is ordered to be injected into the first one.
// this line is instructing UI-Router: inject this into
// the other view definition of the current state
// search for ui-view="list"
'list#root.home'
but there was no ui-view="list" defined.
Finally, we cannot declare url for views. Url belongs just to states:
// this is wrong. The view cannot have url
// url is for state
'list#root.home': {
url: '/list',
So, we should introduce the child of our state... 'home.list'
This is the adjusted state(s) definition (from the new working plunker):
.state('home', {
parent: 'root',
url: '/home',
views: {
'#': {
template: '<div ui-view="list"></div>',
controller: 'HomeController',
controllerAs: 'homeCtrl'
}
},
})
.state('home.list', {
url: '/list',
views: {
'list': {
templateUrl: 'homeList.html',
controller: 'HomeController',
controllerAs: 'homeCtrl'
}
},
});

Angular UI Router: How to stop reloading based on query parameters change?

Here is my ui-router configuration:
$stateProvider
.state('search.filter.results', {
url: '/results?profileId&keywords',
views: {
'profiles#': {
templateUrl: 'profile-list/profile-list.html',
controller: 'ProfileListCtrl'
},
'profile-summary#search.filter.results': {
templateUrl: 'profile-list/profile-summary/profile-summary.html'
},
'profile-details#search.filter.results': {
templateUrl: 'profile-list/profile-details/profile-details.html',
controller: 'ProfileDetailsCtrl'
}
}
})
ProfileListCtrl has the following method:
$scope.showProfileDetails = function(profileId) {
$state.go('search.filter.results', { profileId: profileId });
};
The problem is, when this method is executed, ProfileListCtrl is instantiated and the view is reloaded.
I would like the reload to happen only if the keywords query parameter changes, but not when the profileId parameter changes.
What would be the best way to achieve this?
I would suggest: split this state into 2 states.
The "parent" keeping the profileId,
the "child" working with keywords.
Until the profileId is not changed, the parent controller won't be re-instantiated.
I created this example with this simplified states definition:
.state('profile', {
url: '/results/:profileId',
views: {
'profiles#': {
//templateUrl: 'profile-list/profile-list.html',
template: '<div>'
...
'<div ui-view=""></div></div>',
controller: 'ProfileCtrl'
},
}
})
.state('profile.results', {
url: '/?keywords',
views: {
'': {
//templateUrl: 'profile-list/profile-list.html',
template: ...
controller: 'ProfileListCtrl'
},
}
})
NOTE: state defintion here is simplified, to just show the split. Not all the details. Also, the child state target parents unnamed view ui-view="", because these should be nested. Finally, parent could even be abstract
This approach also will require some small adjustments of the url. It is not working well if the child url defintion would start with ? like: url: '?keywords'. So I used different pattern:
/results/profileId-value/?kewords=abc

Resources