I have a list. What I want is when I click on one of the item of List a new page should open where the data related to only that listItem is displayed. Right now I am using anchor tag and .config to pass data like this:
<ion-item ng-repeat="field in fields">
<a href="#detail/{{field.firstName}}/{{field.personNo}}/{{field.street}}/{{field.city}}/{{field.postcode}}" id="a-item"> <div style="width:100%;height:100%" >
{{field.firstName}}<br>
{{field.personNo}} </div></a>
</ion-item>
And
.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/', {
templateUrl: 'templates/mainpage.html'
}).
when('/detail/:name/:no/:street/:city/:postcode', {
templateUrl: 'templates/details.html',
controller: 'detailctrl'
})
}])
I don't think this is an effective way to pass data. Although I know about .service but I can't figure out a way to pass data specific to the item clicked. Please suggest a better way. Thanks
What you're looking at is the classic master detail pattern that you indeed would want to use a service (or factory) for.
First change I'll make to your code is giving the main route a controller, as well as for the details route only passing in the personNo.
.config(['$routeProvider',function($routeProvider) {
$routeProvider.
when('/', {
templateUrl: 'templates/mainpage.html',
controller: 'mainctrl'
}).
when('/detail/:no', {
templateUrl: 'templates/details.html',
controller: 'detailctrl'
})
}])
Next, let's set up a "PeopleService" via a factory with two methods. One, is the GetPeople method which gets all the people in an array and resolves a promise via $http before storing it in a private variable. The GetPerson method looks up a person by personNo in that private variable.
.factory('PeopleService',['$http',function($http){
var people = [];
return {
GetPeople: function(){
$http.get("path/to/resource").then(function(response){
people = response;
return response;
});
},
GetPerson: function(personNo){
for(i=0;i<people.length;i++){
if(people[i].personNo == personNo){
return people[i];
}
}
}
}
}]);
Next, in our mainctrl we will want to call that GetPeople function.
.controller("mainctrl",['PeopleService',function(PeopleService){
PeopleService.GetPeople().then(function(people){
$scope.people = people;
});
}]);
Finally, in our detailsctrl, we will get the personNo from the $routeParams and use it to call the GetPerson method from our service.
.controller("detailctrl",['$routeParams','PeopleService',function($routeParams,PeopleService){
var personNo = $routeParams.no;
$scope.person = PeopleService.GetPerson(personNo);
}]);
Related
I need to setup a controller with some data passed from the routeProvider.
I would like the value topic to be passed to my controller VideoCtrl and then assigned to a value such as video.topic
$routeProvider
.when('/video/:topic', {
templateUrl: 'pages/video/video-page.tmpl.html',
controller: 'VideoCtrl',
controllerAs: 'video'
});
It seems like I should just need to call $routeProvider in my controller function:
app.controller('VideoCtrl', function($routeProvider) {
var video = this;
video.topic = $routeProvider.topic; // What do I need to add here?
...
});
But I can't seem to figure out how to inject $routeProvider into the controller.
I think, you need to pass the $routeParams as controller parameter and then you will able to get the passed route value.
app.controller('VideoCtrl', function($routeParams) {
var video = this;
video.topic = $routeParams.topic;
...
});
'use strict'
var hsbc = angular.module('hsbc',['ngResource','ngRoute']);
hsbc.config(['$routeProvider','$locationProvider', function ($routeProvider, $locationProvider){
//console.log('config part working');
$routeProvider
.when('/login', {
controller: 'hsbccontroller',
templateUrl: 'modules/authentication/views/login.html',
hideMenus: true
})
.when('/gloabltranfer', {
controller: 'hsbccontroller',
templateUrl: 'modules/home/views/gloabltranfer.html'
})
.when('/tranferReq', {
controller: 'hsbccontroller',
templateUrl: 'modules/home/views/TransferRquest.html'
})
.when('/reviewdetail', {
controller: 'hsbccontroller',
templateUrl: 'modules/home/views/Reviewdetails.html'
})
.when('/confirmdetail', {
controller: 'hsbccontroller',
templateUrl: 'modules/home/views/confirmdetails.html'
})
.when('/', {
templateUrl: 'modules/authentication/views/login.html'
})
.otherwise({ redirectTo: '/login' });
}]).controller('hsbccontroller', ['$scope','$http','$resource','$location', function($scope,$http,$resource,$location, transfer){
var gformcountry, gtocountry, userID, formData;
$scope.hsbcaccts = [];
$scope.countries = [];
$scope.login = function(){
var username = $scope.username;
var pass = $scope.password;
if(username =='test' && pass =='test'){
username = 1234;
$location.path('/gloabltranfer');
}
else if(username =='test2' && pass =='test2'){
username = 2222;
$location.path('/gloabltranfer');
}
else{
$location.path('/login');
}
}
$http.get('http://localhost/api/Accounts').success(function(data) {
$scope.hsbcaccts = data.body;
}).error(function(){
alert('Sorry server down at moment. please some time later');
});
$http.get('http://localhost/api/Country').success(function(data) {
$scope.countries = data.body;
}).error(function(){
alert('Sorry server down at moment. please some time later');
});
/*$http.get('json/currency.json').success(function(data) {
$scope.countries = data;
});*/
$scope.countryFromTo = function(){
$scope.fromData ={ 'fromcountry':$scope.fromcountry,'tocountry':$scope.tocountry};
$location.path('/tranferReq');
}
$scope.tranferForm = function(){
$scope.tranferForm ={ 'fromaccount':$scope.fromaccount,'toaccount':$scope.toaccount, };
return $scope.tranferForm;
$location.path('/reviewdetail');
}
$scope.reviewdetails = function(){
//alert($scope.tranferForm);
$location.path('/confirmdetail');
}
$http.get('http://localhost/api/Accounts').success(function(data){
//alert(data.id);
$scope.hsbcaccts = data;
});
}]);
Here getting data from ng-click tranferForm function without submitting data try binding to next page $scope tranferForm function collecting data and display in the page reviewdetail page.
and then my controller twice at a time.
First thing first, using same controllers in different pages means two different instances, completely independent of each other.
Now to share the variables between controllers,there are two ways to do this:
Store data in factories and fetch from the factories in other page.
But a parent controller at body level, or above the view node, and store the values in $scope variables of parent controller. Usually this is on the same html element as the ng-app and is supposed to be the parent of all the controllers.
Plus I think you should be using different controllers.
Putting same controller defeats the purpose of modular programming.
I don't know your case but if possible, create different controllers with different names and put only functions used per page in those controllers.
If there are some functions which are needed in all the places,create a generic function and put it in a service.
I just started with angularJS and I have a question:
How can I access a variable defined with $rootScope in a templateUrl function?
Here is my code:
myApp.config(['$routeProvider',
function($routeProvider, $rootScope) {
$routeProvider.
when( '/', {
templateUrl: 'partials/login.html',
controller: 'loginCtrl'
}).
when( '/home', {
templateUrl: function($rootScope){
console.log($rootScope.utilisateur.user.role_id);
if ($rootScope.utilisateur.user.role_id==2){
return 'partials/home.html';
}
else return 'partials/login.html';
},
controller: 'homeCtrl'
}).
otherwise({redirectTo:'/'});
}]);
It tells me that utilisateur is undefined.
I defined it in the index controller:
$rootScope.utilisateur = null;
$rootScope.rapports = null;
And then in the LoginCtrl:
var user = Authentification.login(email,password);
user.success(function(response){
$rootScope.utilisateur = response;
console.log($rootScope.utilisateur);
$location.path('/home');
});
You cannot use the $rootScope inside of the config block, as the config block runs before the $rootScope is created. Constants and providers may be used inside of the config block instead. If constants are not an option for you, you may want to redirect to the correct url inside of your homeCtrl.
[EDIT] Added possible solution from comment below:
Option 1: Have 2 different routes
/admin/home
/home
Option 2: Switch templates according to permission inside of controller/view
home.html
<div ng-switch="utilisateur.user.role_id">
<div ng-switch-when="2">
<!-- is admin -->
</div>
<div ng-switch-default>
<!-- not admin -->
</div>
</div>
Not the ideal solution, but it'd work for what you are trying to do, based on your comments below
Your problem seems like you have two different views, and on condition base you have to redirect views.
Pass the parameters in url like from your views (Create/Edit link etc.) As i have set the cookie on login and accessed here as a parameters or you can use different way to access the parameters.
''
And your config in $routeProvider use like this:
$routeProvider.when("/editTest/:ID/:flagTab",
{
templateUrl: function (params) {
var flag = params.flagTab;
if (flag == 'tabPanelView') {
return '/apps/templates/editTest.html';
}
else {
return '/apps/templates/editTestPageView.html';
}
},
controller: 'EditTestController'
});.
Refere a link swtiching views in routeProvider based on condition
Instead of describing different ways to achieve what you would like to, the code snippet below answers the actual question that was asked:
How can I access a variable defined with $rootScope in a templateUrl function?
The answers above and here imply there is no way to reference $rootScope within the config/$routeProvider. While that may strictly be true, there is a simple way to access the $rootScope through $routeProvider. Below is how to do this:
Sample HTML:
<div ng-app="myApp">
<div ng-controller="masterController">
<script type="text/ng-template" id="home.html">{{something}}</script>
Page
<div ng-view></div>
</div>
</div>
Sample javascript:
var myApp = angular.module('myApp',[],function($routeProvider) {
$routeProvider
.when('/home',{templateUrl:'home.html'})
.when('/page',
{
template:'<p>{{something}}</p>',
controller:'masterCtrlWrapper'
})
.otherwise({redirectTo:'/home'});
});
myApp.controller('masterCtrlWrapper', function($rootScope)
{ $rootScope.changeVariable(); });
myApp.controller('masterController', function($rootScope)
{
$rootScope.something = 'This is the $rootScope talking.'
$rootScope.pressCount = 0;
$rootScope.changeVariable = function()
{ $rootScope.something = "This function was run " + $rootScope.pressCount++ + " times."; };
});
Like others have said, $rootScope doesn't exist yet, but unlike their answers, it doesn't at all mean you can't use it at all, you just have to code-in the wait.
Here is your example working but just printing since we dont have the templates.
myApp
.provide('home', function() {
var $rootScope = null;
this.templateUrl = function() {
var check =
$rootScope.utilisateur &&
$rootScope.utilisateur.user.role_id
;
console.log(check);
return (check) ? 'partials/home.html' : 'partials/login.html';
};
this.controller = 'homeCtrl';
this.resolve = {load:['$rootScope', function(fetched) { $rootScope = fetched; }]};
this.$get = function() { };
})
.config(['$routeProvider', 'homeProvider', function($routeProvider, homeProvider) {
$routeProvider
.when('/', {
templateUrl : 'partials/login.html',
controller : 'loginCtrl'
})
.when('/home', homeProvider)
.otherwise({redirectTo:'/'})
;
}])
;
I need to build a User that can be the resut of different REST API call (each way comes from a specific route).
Let's say for this example that we can visit:
http://myapp/#user/:pseudo
http://myapp/#user/:user_id
angular.module('Test').config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/user/:pseudo', {
templateUrl: 'views/user.html',
controller: 'userFromPseudoCtrl'
}).
when('/user/:user_id', {
templateUrl: 'views/user.html',
controller: 'userFromIdCtrl'
}).
otherwise({
redirectTo: '/'
});
}
]);
then, i have 3 different controllers:
userFromPseudoCtrl
userFromIdCtrl
userCtrl (To control the view)
angular.module('Test').controller('userFromPseudoCtrl', function($User, $http) {
$http.get('/getUserFromPseudo/test')
.success(function(User) {
$User.set(User);
});
});
angular.module('Test').controller('userFromIdCtrl', function($User, $http) {
$http.get('/getUserFromId/test')
.success(function(User) {
$User.set(User);
});
});
angular.module('Test').controller('userCtrl', function($scope, $User) {
$scope.User = $User;
});
This way is not good because the userCtrl is called before the $http callback (from the router's controllers), so the User is actually empty into the page (i was hopping it will be automatically updated).
Before i try to manage with it (using $rootScope.$apply()), i am wondering what is the more optimize way to do this kind of process (loading datas from router's controller then display it).
Do you use as many controllers as i do ? Do you process these REST APIs calls in the same controller that "bind" your view ? I am interesting to know !
When you define your routes you can define an additional value named resolve which is an object where each field is a promise that when resolved will be injected into your controller:
Route Definition:
when('/user/:pseudo', {
templateUrl: 'views/user.html',
controller: 'userFromPseudoCtrl'
resolve: {dataNeeded: userPseudoService.getUserData()});
Service (new):
angular.module('Test').service('userPseudoService', function($http){
return $http.get('/getUserFromPseudo/test');
});
Controller:
angular.module('Test').controller('userFromPseudoCtrl', function(dataNeeded){});
The route will not change until the promise is resolved.
Is it possible to pass your own variables in a defined route in AngularJS?
The reason why I'm doing this is because I have to data representations of the same page (one is a filtered view in terms of the JSON data) and all I need to do is give a boolean flag to the $params array to let the controller function know that this page is either filtered or non-filtered.
Something like this:
var Ctrl = function($scope, $params) {
if($params.filtered) {
//make sure that the ID is there and use a different URL for the JSON data
}
else {
//use the URL for JSON data that fetches all the data
}
};
Ctrl.$inject = ['$scope', '$routeParams'];
angular.modlule('App', []).config(['$routeProvider', function($routes) {
$routes.when('/full/page',{
templateURL : 'page.html',
controller : Ctrl
});
$routes.when('/full/page/with/:id',{
templateURL : 'page.html',
controller : Ctrl,
params : {
filtered : true
}
});
}]);
According to $routeProvider documentation, the route parameter of $routeProvider.when() has property resolve:
An optional map of dependencies which should be injected into the controller.
Something like this should work:
function Ctrl($scope, isFiltered) {
if(isFiltered) {
//make sure that the ID is there and use a different URL for the JSON data
}
else {
//use the URL for JSON data that fetches all the data
}
}
Ctrl.$inject = ['$scope', 'isFiltered'];
angular.modlule('App', []).config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/full/page',{
templateURL: 'page.html',
controller: Ctrl
});
$routeProvider.when('/full/page/with/:id',{
templateURL: 'page.html',
controller: Ctrl,
resolve: {
isFiltered: function() { return true; }
}
});
}]);
AFAIK it is not currently possible to specify additional parameters for a route. Having said this your use case could be easily covered by testing if :id is defined as part of $routeParams.
The thing is that AngularJS will match your routes either on '/full/page' or '/full/page/with/:id' so just by testing $routeParams for id presence in your controller:
if ($routeParams.id)
you would know in which case your are.
The alternative is to use different controllers for different routes.
mething like this must be work for filter:
function caseFilterCtrl($scope, $routeParams, $http) {
$http.get('./data/myDatas.json').success( function(data){
var arr = new Array();
for(var i=0; i < data.length; i++){
if(data[i].filter == $routeParams.id){
arr.push(data[i]); }
}
$scope.filtered= arr;
});
}
caseFilterCtrl.$inject = ['$scope', '$routeParams', '$http']; //for minified bug issue
and the routage :
angular.module('myFilterApp', []).
config(['$routeProvider', function($routeProvider){
$routeProvider.when('/filter/:id', {templateUrl: './view/partial/filter.html', controller: caseFilterCtrl});
$routeProvider.otherwise({redirectTo: '/filter/01'});
}
]);
You can get sneak params directly through $route.current.$$route.
function Ctrl($scope, $route) {
var filtered = $route.current.$$route.params.filtered;
}
angular.modlule('App', []).config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/full/page/with/:id',{
templateURL: 'page.html',
controller: Ctrl,
params : {
filtered : true
}
});
}]);
Although it work, I'd still prefer a resolve solution. params (or any name of your choice) could be overwritten by angularjs in future releases.