I have the state brand. On the template of this state, I have some breadcrumbs. When I go to the nested state brand.collections for example, I need to update the breadcrumbs in the brand state.
How can I accomplish this?
.state('brand', {
url: '/brands/:brandId/:brandName',
templateUrl: 'js/modules/brands/partials/brand.html',
controller: 'BrandController',
})
.state('brand.home', {
url: '/home',
templateUrl: 'js/modules/brands/partials/brand.home.html',
controller: 'BrandController'
})
.state('brand.collections', {
url: '/collections',
template: 'Some collections',
controller: 'CollectionsController'
})
inside CollectionsController
$scope.$emit('changeParentVar',<newVal>);
inside BrandController
$scope.$on('changeParentVar',function(event,newVal){
event.stopPropagation();
variable = newVal;
});
Reference http://docs.angularjs.org/api/ng.$rootScope.Scope#methods_$on
Related
I an trying to develop an angular app using ui router, however I am stuck trying to get the controllerAs syntax working correctly.
my stateProvider looks like this
$stateProvider
.state('microsite', {
url: "/",
templateUrl: "microsite.tmpl.html",
abstract: true
})
.state('microsite.home', {
url: "",
templateUrl: "home.tmpl.html",
controller: 'MicrositeController as vm',
data: {
page_name: 'Introduction'
}
})
.state('microsite.features', {
url: "/features",
templateUrl: "features.tmpl.html",
controller: 'MicrositeController as vm',
data: {
page_name: 'Features'
}
})
.state('microsite.about', {
url: "/about",
templateUrl: "about.tmpl.html",
controller: 'MicrositeController as vm',
data: {
page_name: 'About'
}
});
As you can see I setup an abstract default view, and three pages.
I have also assigned a data object with a page_name for each page. This feeds into my controller
myapp.controller('MicrositeController', ['$state', function($state) {
var vm = this;
vm.page_name = $state.current.data.page_name;
vm.sidenav_locked_open = false;
vm.toggleSideNav = function() {
if ($mdMedia('gt-sm')) {
vm.sidenav_locked_open = !vm.sidenav_locked_open;
} else {
$mdSidenav('left').toggle();
}
}
}]);
and then delivers the name to the page via the vm.page_name variable.
However this is not happening. The variable never makes it to the page.
Also I have a vm.toggleSideNav function that is suppose to open and close the sidenav, but that never gets called.
the toolbar with the sidenav button is this
<md-toolbar layout="row" class="md-whiteframe-glow-z1 site-content-toolbar">
<div class="md-toolbar-tools docs-toolbar-tools" tabIndex="-1">
<md-button class="md-icon-button" ng-click="vm.toggleSideNav()" aria-label="Toggle Menu">
XXX
</md-button>
<h1>{{vm.page_name}}</h1>
</div>
</md-toolbar>
here is a plnkr example http://plnkr.co/edit/Na5zkF?p=preview
I am looking for someone to help me figure out the last piece on how to get the toggleSideNav function to get called when I click on the xxx button, and how to get the title to display in the toolbar.
From the Docs:
controller
(optional)
string
function
Controller fn that should be associated with newly related scope or the name of a registered controller if passed as a string. Optionally, the ControllerAs may be declared here.
controller: "MyRegisteredController"
controller:
"MyRegisteredController as fooCtrl"
controller: function($scope, MyService) {
$scope.data = MyService.getData(); }
— UI Router $stateProvider API Reference.
According to the Docs, your controller declaration is correct.
controller: 'MicrositeController as vm'
You need to look for your problem elsewhere.
UPDATE
Put the controller in the root state:
$stateProvider
.state('microsite', {
url: "/",
templateUrl: "microsite.tmpl.html",
//IMPORTANT == Put controller on root state
controller: 'MicrositeController as vm',
abstract: true
})
.state('microsite.home', {
url: "",
templateUrl: "home.tmpl.html",
̶c̶o̶n̶t̶r̶o̶l̶l̶e̶r̶:̶ ̶'̶M̶i̶c̶r̶o̶s̶i̶t̶e̶C̶o̶n̶t̶r̶o̶l̶l̶e̶r̶ ̶a̶s̶ ̶v̶m̶'̶,̶
data: {
page_name: 'Introduction'
}
})
.state('microsite.features', {
url: "/features",
templateUrl: "features.tmpl.html",
̶c̶o̶n̶t̶r̶o̶l̶l̶e̶r̶:̶ ̶'̶M̶i̶c̶r̶o̶s̶i̶t̶e̶C̶o̶n̶t̶r̶o̶l̶l̶e̶r̶ ̶a̶s̶ ̶v̶m̶'̶,̶
data: {
page_name: 'Features'
}
})
.state('microsite.about', {
url: "/about",
templateUrl: "about.tmpl.html",
̶c̶o̶n̶t̶r̶o̶l̶l̶e̶r̶:̶ ̶'̶M̶i̶c̶r̶o̶s̶i̶t̶e̶C̶o̶n̶t̶r̶o̶l̶l̶e̶r̶ ̶a̶s̶ ̶v̶m̶'̶,̶
data: {
page_name: 'About'
}
});
})
The DEMO on PLNKR
Try adding the option controllerAs: 'vm' to the state params instead defining the controller as in the controller option.
Try adding the option controllerAs: 'vm' to the state params instead defining the controller as in the controller option.
or, if I'm not mistaken, you can add
myapp.controller('MicrositeController as vm' ...
I've linked my plnkr here
http://plnkr.co/edit/kuyw1shiKwz9wzVmoo5K?p=preview
On the addProducts tab, I want to load the nested states in the ui-view.
.state("productEdit", {
abstract: true,
url: "/products/edit/:productId",
templateUrl: "productEditView.html",
controller: "ProductEditCtrl as vm",
resolve: {
productResource: "productResource",
product: function(productResource, $stateParams){
var productId = $stateParams.productId;
return productResource.get({productId: productId}).$promise;
}
}
})
.state("productEdit.info",{
url:"/info",
templateURL: "productEditInfoView.html"
})
.state("productEdit.price",{
url:"/price",
templateURL: "productEditPriceView.html"
})
ProductEditInfoView.html has a form with some controls, which I expect to load in the ProductEditView page, but they are not visible
What am I missing here?
Things are case sensitive. Change templateURL to templateUrl and you should be good to go.
I'm using the UI router for Angular. I have two nested states using the same controller. When I go from state1 to state2 via ui-sref click, the controller is called and resetting all my variables. I want the controller to be called only once.
.state('GN.state1', {
url: '/createGNForm',
templateUrl: 'app/createGNForm/createGNForm.html',
controller: 'GNCtrl'
})
.state('GN.state2', {
url: '/newChapter/{chapterID}',
templateUrl: 'app/createGNForm/createNewChapter.html',
controller: 'GNCtrl'
})
Expanding on teleaziz's answer:
.state('GN', {
url: '/GN',
abstract: true,
template: '<div ui-view></div>',
controller: 'GNCtrl'
})
.state('GN.state1', {
url: '/createGNForm',
templateUrl: 'app/createGNForm/createGNForm.html',
})
.state('GN.state2', {
url: '/newChapter/{chapterID}',
templateUrl: 'app/createGNForm/createNewChapter.html'
})
Have an abstract parent state and nest all the states you want to use the same controller under it.
This is my plunker http://plnkr.co/edit/GMfMcXgHguYjFYoxWEaM
1.) click the above live demo link
2.) click the "create" button which should activate the projects.create state
3.) an alert() should pop up now but it does not.
Why are those onExit and onEnter callbacks in the projects state definition not called?
The projects state onExit should be triggered when this state is left and we activate the projects.create state.
app.js
.config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/projects');
$stateProvider
.state('projects', {
url: '/projects',
views: {
'menu#""': {
template: 'Start your projects!'
},
'content#': {
templateUrl: "projects.html",
controller: 'ProjectsController',
onEnter: function(){
alert('hello onEnter');
},
onExit: function(){
alert('hello onExit');
}
}
}
})
.state('projects.create', {
url: '/create',
views: {
'outer#': {
templateUrl: 'projects.create.html',
controller: 'ProjectWizardController'
}
}
})
.state('projects.selected', {
url: '/:projectId'
})
});
Okay, I got it now. The first problem is that, if you are using nested views then you can't use onEnter & onExit callbacks there (at view level). You can only use them at state level configuration.
For reference documentation: https://github.com/angular-ui/ui-router/wiki/Multiple-Named-Views#views-override-states-template-properties
If you define a views object, your state's templateUrl, template and
templateProvider will be ignored. So in the case that you need a
parent layout of these views, you can define an abstract state that
contains a template, and a child state under the layout state that
contains the 'views' object.
Now since, you can't use them at view level, you have to add it to your state config for create page like this:
.state('projects', {
url: '/projects',
views: {
'menu#""': {
template: 'Start your projects!'
},
'content#': {
templateUrl: "projects.html",
controller: 'ProjectsController'
}
}
})
.state('projects.create', {
url: '/create',
views: {
'outer#': {
templateUrl: 'projects.create.html',
controller: 'ProjectWizardController'
}
},
onEnter: function(){
alert('hello onEnter');
},
onExit: function(){
alert('hello onExit');
}
})
Hope this helps!
Hello when i have this states defined:
.state('locations', {
url: '/locations',
templateUrl: '/templates/locations/index.html',
controller: 'LocationsCtrl'
})
.state('locations.show', {
url: '/{location_id}',
templateUrl: '/templates/locations/show.html'
});
How can i have /templates/locations/index.html to show for example a list of all locations,
but templates/locations/show.html to show a view of the location, but not nested inside the view of index.html. Basically i want the routes nested, but not the views.
I just worked on an example similar to yours
.state('overview', {
url: '/all',
templateUrl: '_/partial/overview/all.html',
controller: 'homeCtrl'
})
.state('places', {
url: '/:id/place',
templateUrl: '_/partial/details/detail-place.html',
controller: function($scope, $stateParams) {
$scope.path = $scope.paths[$stateParams.id];
}
})
In your case
.state('locations', {
url: '/locations',
templateUrl: '/templates/locations/index.html',
controller: 'LocationsCtrl'
})
.state('show', {
url: '/{location_id}',
templateUrl: '/templates/locations/show.html'
});
That means the show state shouldn't be nested under locations.