AngularJS, How about multiple routes with different templates but the same controller? - javascript

i'm investigating if i can have what the title says.
Here's my thought.
Let's assume that i've got this routes:
.when('/', {
templateUrl : 'partials/homepage.html',
})
.when('/test', {
templateUrl : 'partials/test.html',
})
.when('/page/:pageID', {
templateUrl : 'partials/page.html',
})
.when('/page/single/:pageID', {
templateUrl : 'partials/page-single.html',
})
Until now i had the opportunity to add the templateUrl as also the controller details in the route and everything was working just fine.
Now the app is changed and there is only one controller with all the information needed and must remain one controller. And the routes will be something like that:
.when('/:templateName/:pageID', {
controller: 'myCtrl'
})
Can i set from the controller the template id by getting the templateName parameter? And if so how about the last route example /page/single/:pageID? How can i know that there is a second option in route?
I can take the templateName parameter and see it changing with the $routeChangeSuccess method but i cannot find any way to set the template on the fly.
Any ideas?

One solution could be the following one:
angular.module('myapp', []).
config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/:templateName/:pageId', {
templateUrl: function(urlattr){
return '/pages/' + urlattr.templateName + '.html';
},
controller: 'YourCtrl'
});
}
]);
From the AngularJs 1.3 Documentation:
templateUrl – {string|function()} – path or function that returns a path to an html template that should be used by ngView.
If templateUrl is a function, it will be called with the following parameters:
Array.<Object> - route parameters extracted from the current $location.path() by applying the current route

I would move your singleton logic from your controller to a service. Since you didn't provide much code below is an example to give you an idea how it could work.
app.config(function($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'partials/homepage.html',
controller: 'SingleController'
})
.when('/test', {
templateUrl: 'partials/test.html',
controller: 'SingleController'
})
.when('/page/:pageId', {
templateUrl: 'partials/page.html',
controller: 'SingleController'
});
});
app.provider('appState', function() {
this.$get = [function() {
return {
data: {}
};
}];
});
app.controller('SingleController', function ($scope, appState) {
$scope.data = appState.data;
});
But if it must be a singleton controller you actually could use the ng-controller directive before your ng-view directive so it becomes a $rootScope like scope for all your views. After that just add empty function wrappers in your $routeProvider for the controllers.

Related

Getting access to parent scope variables using ui router

I am currently using ui router as below: -
$stateProvider
.state('login', {
url: '/login'
, resolve: loadSequence(
'base')
, templateUrl: 'app/shared/main/login-main.html'
, controller: 'mainController'
, abstract: true
})
.state('login.signin', {
url: '/signin'
, resolve: loadSequence(
'login-items'
, 'spin'
, 'ladda'
, 'angular-ladda'
, '_loginController'
)
, templateUrl: "app/components/login/login_login.html"
, controller: 'loginController'
});
Now in loginController I want to be able to access a function in the mainController.
Is that possible with my current implementation:-
angular.module('app').controller('mainController', function($scope, $state) {
$scope.showWarning= function(){
//show warning
}
});
angular.module('app').controller('loginController', function($scope, $state) {
// I want to access $scope.showWarninghere;
});
Extract the getData() method out into a service and then you can inject it into both controllers:
angular.module('app').factory('dataService', function () {
return {
getData: function() { ... }
}
});
angular.module('app').controller('mainController', function($scope, $state, dataService) {
// You probably don't need to put this into your scope, but if you do:
$scope.getData = dataService.getData.bind(dataService);
});
angular.module('app').controller('loginController', function($scope, $state, dataService) {
dataService.getData();
});
It is useful to remember that scopes and controllers are created and destroyed as you navigate between states, so anything that actually wants to exist in more than one state really does want to be stored in a service.
As said by Duncan and Sanjay, it might indeed be a better idea to use a service to get the data, but I thought I'd answer the original question so you know :
As stated in the docs, for prototypal inheritance to be active the views must be nested, not only the states.
So in order for loginController to have access to the scope of mainController, the login-main.html template must use the uiView directive (e.g <div ui-view></div>) which will be the placeholder for the login_login.html template of the login.signin state.
you can use angular service for this.
I found a Plunker code to resolve your problem

Saving an object into an array in a controller in AngularJS

I've been creating a contact list website and have just begun trying to implement an add contact function. So far I have created the page using a form and input elements and then use ng-click to call a function which theoretically would add an object containing these input values into an already-existing array in the controller. For some reason this doesn't work and nothing is added.
In particular, I'm having trouble with the js/app.js file and the $scope.saveContact = function() in relation to the partial/edit.html webpage. Clicking the "Confirm button" when trying to add a contact calls the saveContact function, but the results are not stored properly. Any help is appreciated.
In my HTML I have this code (which calls the saveContact() function in my controller.
<a href="#/"><div class="confirm col-xs-6" ng-click="saveContact()">
<h3>Confirm</h3>
</div></a>
In my app.js file I have a declaration of an empty object and an array containing objects that already have values (used to display the contacts that are already created). I'm trying to add to these contacts using .push() but it for some reason it doesn't work.
$scope.contact = { ... } //empty object that gets inputs from HTML
$scope.contacts = [ { ... }, ... ];
$scope.saveContact = function(){
$scope.contacts.push($scope.contact);
};
This bottom function fails to push the contact object to the contacts array and I don't understand why.
This is happening as you have assigned same controller to all your routes. Your saveContact function is working fine, its pushing the object to the array. As soon as the route changes, a new instance of the controller is created and hence the added object is lost. You should create a service(singleton) to store the object and inject the service as a dependency to the controller. In this way the array will persist until the page load.
app.service("storeContact", function(){
var contacts = [];
this.setContact = function(cnt){
contacts.push(cnt)
};
this.getContact = function(){
return contacts;
}
});
And inject it in the controller and use the setContact and getContact methods to update the contact array and retrieve the contact array.
Ideally, you should have separate controllers for your route.
The issue is in your app.config code. You are using the same controller for all your templates.
This is not required since you have already mentioned the same in ng-controller attached with body
<body ng-controller="AppController">
<div ng-view></div>
<script src="js/app.js"></script>
</body>
Using same controller for all your routes is essentially (re)instantiating the controllers when the route is changed and thats the reason why $scope.contacts.push($scope.contact); is ineffective for the route / when called from /add.
contactListApp.config(['$routeProvider', '$locationProvider',
function($routeProvider, $locationProvider) {
$routeProvider
.when('/', {
controller: 'AppController',
controllerAs: 'list',
templateUrl: 'partials/list.html'
})
.when('/add', {
controller: 'AppController',
controllerAs: 'add',
templateUrl: 'partials/edit.html'
})
.when('/edit/:id', {
controller: 'AppController',
controllerAs: 'edit',
templateUrl: 'partials/edit.html'
})
.otherwise({
redirectTo: '/'
});
}]);
Workaround:
Either use separate controllers for separate routes and use a service to store the object
OR
Simply remove the controller and controller as from your route config and you are good to go.
Updated config:
contactListApp.config(['$routeProvider', '$locationProvider',
function($routeProvider, $locationProvider) {
$routeProvider
.when('/', {
templateUrl: 'partials/list.html'
})
.when('/add', {
templateUrl: 'partials/edit.html'
})
.when('/edit/:id', {
templateUrl: 'partials/edit.html'
})
.otherwise({
redirectTo: '/'
});
}]);

How to select different template depending on different angular js route value

I have a route like this:
$routeProvider.when('/test/item/:item', {
templateUrl: '/test/test.html'
, controller: 'TestController'
});
Now I want to load different templateUrl depending on different :item value, How do I do it in angularJS?
for example:
$routeProvider.when('/test/item/:1', {
templateUrl: '/test/test1.html'
, controller: 'TestController'
});
$routeProvider.when('/test/item/:2', {
templateUrl: '/test/test2.html'
, controller: 'TestController'
});
Thanks in advance.
templateUrl can be a function as well and you get the first argument will be route params:
So you can do something like this:-
$routeProvider.when('/test/item/:item', {
templateUrl: function(param){
return '/test/test' + param.name + '.html'
/*if(param.name === 'somevalue'){
return someurl;
}
return someotherurl;*/
}
, controller: 'TestController'
});
templateUrl – {string=|function()=} – path or function that returns a path to an html template that should be used by ngView.
If templateUrl is a function, it will be called with the following parameters:
{Array.} - route parameters extracted from the current $location.path() by applying the current route

AngularJS. Initialize controller with different data

I'm using $routeProvider for routing in my Angular app. And for 2 routes I'm using same HTML template and same Controller.
when('/products, {
templateUrl: 'views/products.html',
controller: 'ProductListCtrl'
}).
when('/myProducts', {
templateUrl: 'views/products.html',
controller: 'ProductListCtrl'
}).
Only difference in data that I want to show. I.e. for path products I want AJAX request to myserver:8080/products and for for path myProducts I want to load data from AJAX request to myserver:8080/products/my.
For now I i'm using $location service to distinguish the current page (products or myProducts) and load apropriate data.
Is there some more elegant way to do it? For example using resolve method of $routeProvider?
The best way to reuse controller name in today scenario is to use resolve with $routeparams.
You can modify your code as below
when('/products, {
templateUrl: 'views/products.html',
controller: 'ProductListCtrl',
resolve: {
product: function($http) {
return $http.get('/products')
},
needToShowFilter:function($q){
var showfilter = $q.defer();
showfilter.resolve(false);
return showfilter.promise
}
}
}).
when('/myProducts', {
templateUrl: 'views/products.html',
controller: 'ProductListCtrl',
resolve: {
product: function($http) {
return $http.get('/products/my')
},
needToShowFilter:function($q){
var showfilter = $q.defer();
showfilter.resolve(true);
return showfilter.promise
}
}
}).
And then in your controller you can inject the product into the controller code.
try to add $route in your controller, and log
$route.current
to see what you have inside, i think thats the way to get the information

controller not found through routeProvider

$routeProvider
.when('/default', {
templateUrl: 'HTML/login.html',
controller : 'funct2'
}).when('/adminMenu/:username', {
templateUrl: 'HTML/adminMenu.html',
controller : 'admin'
}).otherwise({
redirectTo : '/default'
});
When i try to use the controller adminMenu i get a no adminMenu defined even though its defined with in the js files linked to adminMenu.html.
When going to the individual adminMenu.html page it loads, however when specifying the controller in routeProvider it never loads. Any ideas?
if you defined your controller like this:
function MyCtrl($scope) {
}
You will have to specify your controller like this (without the quotes):
.when('/default', {
templateUrl: 'myCtrl.html',
controller : MyCtrl
})

Categories

Resources