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' ...
Related
I have 3 level routing, in url it looks like site.com/Jonny/2. But now I need this looks site.com/2/Jonny or site.com/10/Kelly. But index.name.page it's next page, after index.name, so I can't understand how to swap 3rd and 2nd state. Is it possible?
$stateProvider
.state('index', {
url: '',
controller: 'MainCtrl'
})
.state('index.name', {
url: '#:name',
views: {
'#': {
templateUrl: 'app/names/name.html',
controller: 'NameCtrl'
}
}
})
.state('index.name.page', {
url: '/:number',
templateUrl: 'app/pages/page.html',
controller: 'PageCtrl'
})
inject $state service to your controller, then in your controller...
CONTROLLER
$scope.changeState = function () {
$state.go('where.ever.you.want.to.go', {stateParamKey: exampleParam});
};
and add ng-click to your button
HTML
<button ng-click="changeState()">Change State</button>
Following works perfect.
In my application file app.js, i have states like
.state('nna.home',
{
url: '/home',
views: {
templateUrl: 'views/home.html'
}
})
//home.html is like
<script src="../controllers/home.js"></script>
<div class="container cf" ng-controller="home">
// my home.js is included correctly in all cases have code like
alert(2); // works
app.controller('home', function ($scope) {
alert(2); // works
});
But as soon as I try to use named views like following. It stops routing
.state('nna.home', {
url: '/home',
views: {
'v1' : {
templateUrl: 'home.html',
controller: 'home',
resolve: {
deps: function ($ocLazyLoad) {
return $ocLazyLoad.load('homecontroller.js');
}
}
},
}
// my home.js is included correctly in all cases have code like
alert(2); // works
app.controller('home', function ($scope) {
alert(2); // Does not work
});
Plunker
I can use them fine as long as i load all controller files in index but i want to load controllers only with views not all the way in index
Probably the issue is with my understanding about named views, but i am stuck to know the reason that why the home is undefined even when i can show with alert that file had been successfully added
Try this:
.state('nna.home',
{
url: '/home',
views: {
'v1': {
templateUrl: 'views/home.html',
controller: 'home'
}
}
})
There is a working plunker
These could be the states:
.state('nna', {
template: '<div ui-view="v1"></div>',
})
.state('nna.home', {
url: '/home',
views: {
'v1' : {
templateUrl: 'views/home.html',
controller: 'home',
},
}
});
And these links are working now:
<a href="#/home">
<a ui-sref="nna.home">
Check it in action here
Say i am on a page http://localhost/#/edit/10/step2 and i want to have a link (anchor tag) that takes me to http://localhost/#/edit/10/step1.
What shall one put in ng-href="" and could this be achieved without specifying id (10) in the link?
<a ng-href="step1">Previous</a>
edit (routing):
.config(["$stateProvider", "$urlRouterProvider", "$httpProvider", ($stateProvider: ng.ui.IStateProvider, $urlRouterProvider: ng.ui.IUrlRouterProvider, $httpProvider: ng.IHttpProvider) => {
$urlRouterProvider.otherwise("/home");
$stateProvider
.state("MyModule", {
template: "<div ui-view></div>"
})
.state("home", {
url: "/home",
templateUrl: "App/home.html",
controller: "homeController as ctrl"
});
$httpProvider.interceptors.push("busyHttpInterceptor");
}]);
state (edit):
.state("edit", {
url: "/edit/:id",
templateUrl: "App/edit.html",
controller: "editController",
controllerAs: "ctrl",
resolve: {
}
})
I think you can do the redirection by a ng-click function :
//for the 'state', you can add a new one or edit the existing one depending on your requirement and restirctions
//Add a new one:
.state("edit.action", {
url: "/edit/:id/:action",
templateUrl: "App/edit.html",
controller: "editController",
controllerAs: "ctrl",
resolve: {
}
})
//in the html
<a ng-click=goToAction("step1")>Previous</a>
//in the controller 'editController', inject the service '$stateParams' and '$state'
$scope.goToAction = function(action) {
//get the ':id' from the url
var currentId = $stateParams['id'];
$state.go('edit.action', {
id: currentId,
action: action
});
}
If you want you can also apply regex to the parameter part of the url:
url: "/edit/{id:[a-zA-Z0-9]*}/:action
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
I have code like this
<a ui-sref="nested.something">something</a>
<div ui-view="nested.something"></div>
how to load ui-view without click ui-sref ?
EXTEND - related to this plunker provided by OP in the comments above
The state definition is:
.state('store', {
views: {
'store': {
templateUrl: 'store.html'
}
}
})
.state('store.detail', {
views: {
'store_detail': {
templateUrl: 'store_detail.html'
}
}
})
Then in this updated plunker we can see that this would do the job
//$urlRouterProvider.otherwise('/store');
$urlRouterProvider.otherwise(function($injector, $location){
var state = $injector.get('$state');
state.go('store.detail');
return $location.path();
});
Reason? states do not have defined url. Which is a bit weird. So, I would honestly rather suggested to do it like this (the link to such plunker):
$urlRouterProvider.otherwise('/store/detail');
//$urlRouterProvider.otherwise(function($injector, $location){
// var state = $injector.get('$state');
// state.go('store.detail');
// return $location.path();
//});
$stateProvider
.state('store', {
url: '/store',
views: {
'store': {
templateUrl: 'store.html'
}
}
})
.state('store.detail', {
url: '/detail',
views: {
'store_detail': {
templateUrl: 'store_detail.html'
}
}
})
There is a working plunker
ORIGINAL
We can use the .otherwise(rule) of $urlRouterProvider, documented here
$urlRouterProvider.otherwise('/parent/child');
As the doc says:
otherwise(rule)
Defines a path that is used when an invalid route is requested.
So, this could be used for some default - start up "redirection"
The .otherwise() could be even a function, like shown here:
How not to change url when show 404 error page with ui-router
which takes '$injector', '$location' and can do even much more magic (on invalid or startup path)
$urlRouterProvider.otherwise(function($injector, $location){
var state = $injector.get('$state');
state.go('404');
return $location.path();
});
ALSO, if we want to fill in some more details into some nested viesw, we can do it by defining multi-named views:
.state('parent.child', {
url: "/child",
views: {
'' : {
templateUrl: 'tpl.child.html',
controller: 'ChildCtrl',
},
'nested.something#parent.child' : {
templateUrl: 'tpl.something.html',
},
}
})
So, if the tpl.child.html will have this anchor/target:
<i>place for nested something:</i>
<div ui-view="nested.something"></div>
it will be filled with the tpl.something.html content
Check it in action here