I'm wondering weather I can join two routes into one - add and edit.
Here are my states:
.state('app.topics.add', {
url: 'add/',
views: {
'page#app': {
templateUrl: 'app/sites/topics/add.html',
controller: 'topicsaddCtrl'
}
}
})
.state('app.topics.details', {
url: '{topic_id:[0-9]+}/',
views: {
'page#app': {
templateUrl: 'app/sites/topics/details.html',
controller: 'topicsdetailsCtrl'
}
}
})
.state('app.topics.details.edit', {
url: 'edit/',
views: {
'page#app': {
templateUrl: 'app/sites/topics/add.html',
controller: 'topicsaddCtrl',
}
}
})
topic/add/ - adding topic
topic/2/ - details of topic
topic/2/edit/ - editing topic
But state for add and edit are using the same templates and controllers. Can I simplyfy states?
You can use stateParams https://github.com/angular-ui/ui-router/wiki/URL-Routing
.state('app.topics.add', {
url: ':method/:id',
views: {
'page#app': {
templateUrl: 'app/sites/topics/add.html',
controller: 'topicsaddCtrl',
}
},
resolve: {
formData: ['$stateParams', 'topicSvc', function ($stateParams, topicSvc) {
if ($stateParams.method === 'add') {
return {}; //return empty object if you creating topic
} else if ($stateParams.method === 'edit' && $stateParams.id) {
return topicSvc.getDetail($stateParams.id); //get topic data from topicSvc service
}
}]
}
})
Also you can inject $stateParams to your controller and access its 'method' and 'id' property.
Related
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;
});
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}}
Working on angular single page application.
I am trying this...
.state('one-category-product-list', {
url: '/products/:category/:category_id',
views: {
'': {
templateUrl: './view/single-category-product.html',
controller: 'ProductsController'
},
nav:{
templateUrl: function() {
if (authenticate() == 'customer') {
return './view/template/nav-login.html';
}
return './view/template/nav.html';
}
},
footer:{
templateUrl: './view/template/footer.html'
}
}
})
the issue with me if a user will not pass the category_id there or directly enters the URL without last parameter like www.example.com/product/category/ then it takes parameters category_id: "". How to restrict this.
Try this out:
.state('one-category-product-list', {
url: '/products/:category/:category_id',
views: {
'': {
templateUrl: './view/single-category-product.html',
controller: 'ProductsController'
},
nav: {
templateUrl: function () {
if (authenticate() == 'customer') {
return './view/template/nav-login.html';
}
return './view/template/nav.html';
}
},
footer: {
templateUrl: './view/template/footer.html'
}
},
resolve: {
data:($stateParams,$state, $q) => {
if(!$stateParams.category_id) {
$state.go('my-otherwise-state');
return $q.reject('No state params');
}
}
}
})
My angular app is routed as following:
$stateProvider
// setup an abstract state for the tabs directive
.state('tab', {
url: "/tab",
abstract: true,
templateUrl: "templates/tabs.html"
})
// Each tab has its own nav history stack:
.state('tab.dotnet', {
url: '/dotnet',
views: {
'tab-dotnet': {
templateUrl: 'templates/tab-dotnet.html',
controller: 'QuestionsCtrl'
}
}
})
.state('tab.sql', {
url: '/sql',
views: {
'tab-sql': {
templateUrl: 'templates/tab-sql.html',
controller: 'QuestionsCtrl'
}
}
})
The above two routes use the same controller but different html pages.
Since both the pages are same, I want to have a single html page in my application instead of two different tab-sql and tab-dotnet pages.
But I will need a differentiation variable to be injected to the controller when selecting the tabs.
Basically I need something like this:
.state('tab.dotnet', {
url: '/dotnet',
views: {
'tab-dotnet': {
templateUrl: 'templates/tab.html',
controller: 'QuestionsCtrl',
type: 'dotnet' // so that i get this type in my Controller
}
}
})
.state('tab.sql', {
url: '/sql',
views: {
'tab-sql': {
templateUrl: 'templates/tab.html',
controller: 'QuestionsCtrl',
type: 'sql'
}
}
})
How to achieve this?
You can pass data to controllers in a state using resolve.
.state('tab.dotnet', {
url: '/dotnet',
views: {
'tab-dotnet': {
templateUrl: 'templates/tab.html',
controller: 'QuestionsCtrl',
resolve: {
type: 'dotnet';
}
}
}
})
.state('tab.sql', {
url: '/sql',
views: {
'tab-sql': {
templateUrl: 'templates/tab.html',
controller: 'QuestionsCtrl',
resolve: {
type: 'sql';
}
}
}
})
https://github.com/angular-ui/ui-router/wiki#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);
}
}