Angular, problems with ngRoute code sequence - angularjs

I am using ngRoute for reading the url parameters. The problem I have is that I can't get the ID while the code is running. However if try to call it as function I get values from url.
.controller('PageCtrl', function ($scope, $routeParams, Survey) {
$scope.survey = Survey.get({surveyId: $routeParams.id}); //doesn't work
this.add = function (pageId, pageIndex) {
console.log($routeParams.id); //works
};
$scope.Page = this;
}
Do you think there is the way of getting the url parameter while I am making the Survey.get() request ?

One way you could solve this would be to wait till the $routeChangeSuccess broadcast had been fired and then to initialise your $scope.survey.
i.e something like this
.controller('PageCtrl', function ($scope,$rootScope, $routeParams) {
$rootScope.$on('$routeChangeSuccess',function(){
$scope.survey = Survey.get({surveyId: $routeParams.id}); //doesn't work
});
this.add = function (pageId, pageIndex) {
console.log($routeParams.id); //works
};
$scope.Page = this;
}

Most likely your controller is called only once on the application startup. That's why your routeconfig isn't set yet and returns undefined. Are you sure you're specifying a controller to your view in your routeconfig?
app.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/home', {
templateUrl: 'partials/home.html',
controller: 'HomeCtrl'
}).
otherwise({
redirectTo: '/home'
});
}]);

Related

setup 404 page using $routeProvider in angular js

Working on single page application everything is working fine but getting stuck when want to set 404 page when :username not found or any unexpected url will load in browser please check my code below
controller.js
var myApp = angular.module('assignment', ['ngRoute']);
myApp.service('userData', ['$http', function($http){
return{
userslist : function(){
return $http({'url' : 'js/data.json', 'method' : 'GET'}).then(function(response){
return response.data;
}, function(data){
console.log('some error')
})
}
}
}]);
myApp.config(function($routeProvider) {
$routeProvider.
when('/', {
templateUrl: 'user-list.html',
controller: 'users'
}).
when('/:username', {
templateUrl: 'detail.html',
controller: 'userdetail'
}).
otherwise({
redirectTo: '/404.html' /*>>>>>>Here is the problem<<<<<<*/
});
});
myApp.controller('userdetail', ['$scope', '$routeParams', 'userData', function($scope, $routeParams, userData){
var selectedUser = $routeParams.username;
selectedUser = selectedUser.replace(/-/g, ' ');
userData.userslist().then(function(data){
$scope.items = [];
angular.forEach(data.data.bst_users, function(item){
if(item.name == selectedUser) {
$scope.user = item;
};
})
})
}])
myApp.controller('userdetail', ['$scope', '$routeParams', 'userData', function($scope, $routeParams, userData){
console.log($routeParams.username);
userData.find($routeParams.username, function(found){
$scope.user = found;
})
console.log(scope.user)
}])
/*******Filters*******/
myApp.filter('removeSpace',function() {
return function(input) {
if (input) {
return input.replace(/\s+/g, '-');
}
}
});
Since you declared /:username as a route, it can match anything after the /, meaning the 404 route isn't really doing anything and the username route in a sense is acting as your catch-all route. This is kind of a weird case, since you can't really define a regular 404 route. But what you could do is have a /404 route, then if /:username doesn't resolve to a user, redirect them to /404. That is the most efficient method I can come up with, but I guarantee there's a better way to do it.
#Jordan points out a definite issue.
I would recommend updating your user detail path to something like the following:
when('/user/:username', {
templateUrl: 'detail.html',
controller: 'userdetail'
})
Just so there is no confusion between /random_username and /unmatched_path.

Using angularjs route how can I get a scope value into another controller?

I have project which is a single page application.So that I am using angular js route.
In the first controller I have a $scope value.The same value i have to use in the other controller
here is my controller.js file
var module = angular.module("sampleApp", ['ngRoute']);
module.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/route1', {
templateUrl: 'http://localhost/MyfirstApp/welcome',
controller: 'RouteController1'
}).
when('/route2', {
templateUrl: 'http://localhost/MyfirstApp/result',
controller: 'RouteController2'
}).
otherwise({
redirectTo: '/'
});
}]);
module.controller("RouteController1", function($scope)
{
$scope.value="Athira"
})
module.controller("RouteController2", function($scope) {
$scope.text=$scope.value + "Sandeep"
})
In the result page it should show as 'Athira Sandeep'
thank you for any kind of help
Use a service to share data among controllers .
Another option could be event emitters which i personally am not a fan because it populates the rootScope (in this case) with a lot of events.
What you could do it
angular.module('app',[])
.factory('SharedScope',function(){
var fac = this;
var scope = "";
var sharedScope = {
getScope : function(){
return fac.scope;
},
setScope: function(scope){
fac.scope = scope
}
};
return sharedScope;
})
.controller('Ctrl1',function('SharedScope'){
SharedScope.setScope("Angular");
})
.controller('Ctrl2',function('SharedScope'){
var data = SharedScope.getScope();
$scope.text = data + " is awesome"; //would get Angular is awesome
});
Hope this helps.

Angular route not firing at all

I triggered the %a{"ng-click"=>"get_destinations(city)"}
However, it should redirect me to "destinations" controller, but it didn't
and there is no error in webconsole, what's going on ?
welcome.js.erb
var App = angular.module('App', ['ngRoute']);
App.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/depart_from/:id',
{
templateUrl: "<%= asset_path('promotion_destinations.html') %> ",
controller: 'destinations'
}
)
.otherwise({ redirectTo: '/depart_from/:id' });
}]);
App.controller("departure_cities", function($scope, $location, $http) {
$http.get("/promotion.json")
.success(function (response) {
$scope.departure_cities = response;
});
$scope.get_destinations = function(id) {
return $location.url("/depart_from/" + id);
};
});
App.controller("destinations", function($scope, $location, $http) {
$http.get("/another_city.json")
.success(function (response) {
$scope.destinations = response;
});
});
Your default controller is destinations in the $scope of destinations controller no any method like get_destinations .
Put your method in side destinations controller it will work if every thing is fine.
Well if you can link the html generated (the one that see the browser, not the server template) that would help.
However i still see an error for me in the HTML (or it's a naming problem)
get_destinations(city)
And in the javascript :
$scope.get_destinations = function(id)
Maybe you wanted to do this ?
get_destinations(city.id)

Using resolve in $routeProvider causes 'Unknown provider ...'

I am trying to do an asynchronous http request to load some data before my app loads and so I am using a resolve in $routeProvider which is an http request in my MainController. For some reason, I keep getting Error: [$injector:unpr] Unknown provider: appDataProvider <- appData where appData is where I do my http request. I am using AngularJS v 1.2.5.
Here is the code and two methods that I tried that both give the same error:
Method #1
MainController.js
var MainController = ['$scope','$location','appData',
function($scope, $location, appData){
console.log(appData.data);
}
];
MainController.loadData = {
appData: function($http, $location, MainFactory){
var aid = MainFactory.extractAid($location);
return $http({method: 'GET', url: URL_CONST + aid});
}
};
app.js
var app = angular.module('HAY', ['ngRoute']);
app.config(function($routeProvider) {
$routeProvider
.when('/', {
redirectTo: '/pages/alerts'
})
.when('/pages/:pageName', {
templateUrl: function(params) {
return 'views/pages/' + params.pageName + '.html';
},
controller: MainController,
resolve: MainController.loadData
})
.otherwise({
redirectTo: '/pages/alerts'
});
});
I tried changing the name in case it was a conflicting system reserved keyword but with no luck. For some reason, appData is never recognized
Method #2
I also tried changing it around like so:
app.js
var app = angular.module('HEY', ['ngRoute']);
app.config(function($routeProvider) {
$routeProvider
.when('/', {
redirectTo: '/pages/alerts'
})
.when('/pages/:pageName', {
templateUrl: function(params) {
return 'views/pages/' + params.pageName + '.html';
},
controller: MainController,
resolve: {
appData: ['$http', '$location','MainFactory', function($http, $location, MainFactory) {
var aid = MainFactory.extractAid($location);
return $http({method: 'GET', url: URL_CONST + aid});
}]
}
})
.otherwise({
redirectTo: '/pages/alerts'
});
});
MainController.js
var MainController = ['$scope','$location','appData',
function($scope, $location, appData){
console.log(resolvedData);
}
];
However, the result was exactly the same. Does this have something to do with angular 1.2.5 ?
Here is a working version from someone else
http://mhevery.github.io/angular-phonecat/app/#/phones
And here is the code:
function PhoneListCtrl($scope, phones) {
$scope.phones = phones;
$scope.orderProp = 'age';
}
PhoneListCtrl.resolve = {
phones: function(Phone) {
return Phone.query();
},
delay: function($q, $defer) {
var delay = $q.defer();
$defer(delay.resolve, 1000);
return delay.promise;
}
}
angular.module('phonecat', ['phonecatFilters', 'phonecatServices', 'phonecatDirectives']).
config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/phones', {templateUrl: 'partials/phone-list.html', controller: PhoneListCtrl, resolve: PhoneListCtrl.resolve}).
otherwise({redirectTo: '/phones'});
}]);
Here's an example of the code I've used in the application I'm working on, not sure it will help much because its not much different than how you have it already.
Routing
.when('/view/proposal/:id',{
controller : 'viewProposalCtrl',
templateURL : 'tmpls/get/proposal/view',
resolve : viewProposalCtrl.resolveViewProposal
})
Controller
var viewProposalCtrl = angular.module('proposal.controllers')
.controller('viewProposalCtrl',['$scope','contacts','details','rationale',
function($scope,contacts,details,rationale){
$scope.contacts = contacts;
$scope.details = details;
$scope.rationale = rationale;
// [ REST OF CONTROLLER CODE ]
});
// proposalSrv is a factory service
viewProposalCtrl.resolveViewProposal = {
contacts : ['$route','proposalSrv',function($route,proposalSrv){
return proposalSrv.get('Contacts',$route.current.params.id)
.then(function(data){
return data.data.contacts;
},function(){
return [];
});
}],
details : ['$route','proposalSrv',function($route,proposalSrv){
return proposalSrv.get('Details',$route.current.params.id)
.then(function(data){
return data.data.details;
},function(){
return {};
});
}],
rationale : ['$route','proposalSrv',function($route,proposalSrv){
return proposalSrv.get('Rationale',$route.current.params.id)
.then(function(data){
return data.data.rationale;
},function(){
return {};
]
}]
};
Now that I think about it, when I was developing my application I did have a problem and not sure why when I named my resolve function "resolve." This gave me a problem:
.when('/path',{
// stuff here
resolve : myCtrlr.resolve
})
but this did not:
.when('/path',{
//stuff here
resolve : myCtrlr.myResolveFn
})
Another Possibility
The only other thing I can think of, is that you're returning the promise from the $http call and then trying to use appData.data Try using the .then function or one of the other functions (.success,.error) to retrieve the information from the promise.
The problem was NOT due to previously using different version of AngularJS.
Here are the fixes using the code that I have above.
In app.js, you need to declare the controller as controller: 'MainController' and NOT as controller: MainController even though you have var MainController = app.controller('MainController', ....).
Second and biggest thing was that in my index.html I declared my controller already like so:
index.html
body ng-app="HEY" controller="MainController" /body
This was causing the whole Unknown provider error Apparently angular wont tell you that you have already declared the controller that you are using to do the resolve it and that that will cause a weird error that have nothing to do with the resolve.
I hope this helps someone who may have the same problem.
One thing I noticed in angular 1x docs is that YOU DO NOT SPECIFY THE RESOLVED PARAMETER AS AN ANNOTATED DEPENDENCY
So this:
.when('/somewhere', {
template: '<some-component></some-component>',
resolve: {
resolvedFromRouter: () => someService.fetch()
}
})
export default [
'$scope',
'someService',
'resolvedFromRouter'
Controller
]
function Controller($scope, someService, resolvedFromRouter) {
// <= unknown provider "resolvedFromRouter"
}
is wrong. You don't specify the resolved parameter as a dependency, in the docs:
For easier access to the resolved dependencies from the template, the resolve map will be available on the scope of the route, under $resolve (by default) or a custom name specified by the resolveAs property (see below). This can be particularly useful, when working with components as route templates.
So just do this instead:
.when('/somewhere', {
template: '<some-component></some-component>',
resolve: {
resolvedFromRouter: () => someService.fetch()
}
})
export default [
'$scope',
'someService',
Controller
]
function Controller($scope, someService) {
$scope.$resolve.resolvedFromRouter; // <= injected here
}

AngularJS show dialog from routeProvider

Is it possible to [execute a function] e.g. open a modal dialog window from the routeProvider when a certain route is requested?
myApp.config(function($routeProvider) {
$routeProvider
.when('/home',
{
controller: 'HomeCtrl',
templateUrl: 'Home/HomeView.html'
}
).when('/profile/:userId/changepwd',
function(){
$dialog.messageBox(title, msg, btns)
.open()
.then(function(result){
alert('dialog closed with result: ' + result);
});
}
).otherwise({ redirectTo: '/home' });
});
PS: I want to cancel a route and instead open a dialog box. Opening the dialog box is not the only issue. Cancelling the route is the major issue.
You can pass your function as dependency in resolve and it will wait until dependency is resolved and when your dialog ends then change the route and modify history as you wish using $location
var app = angular.module('myApp', [])
.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/view1', {
template: '&nbsp',
controller: //empty function,
resolve: {
data1 : function($dialog, $location) {
var promise = $dialog.messageBox(title, msg, btns)
.open()
.then(function(result){
alert('dialog closed with result: ' + result);
//Use [$location][1] to change the browser history
});
return promise;
}
}
});
}]);
Building on Rishabh's answer, and using sergey's location.skipReload from this Angular Issue you can use the following to create a dialog on route-change, defer the url-change indefinitely (in effect 'cancelling' the route change), and rewrite the URL bar back to '/' without causing another reload:
//Override normal $location with this version that allows location.skipReload().path(...)
// Be aware that url bar can now get out of sync with what's being displayed, so take care when using skipReload to avoid this.
// From https://github.com/angular/angular.js/issues/1699#issuecomment-22511464
app.factory('location', [
'$location',
'$route',
'$rootScope',
function ($location, $route, $rootScope) {
$location.skipReload = function () {
var lastRoute = $route.current;
var un = $rootScope.$on('$locationChangeSuccess', function () {
$route.current = lastRoute;
un();
});
return $location;
};
return $location;
}
]);
app
.config(['$routeProvider', function ($routeProvider) {
$routeProvider
.when('/home', {
controller: 'HomeCtrl',
templateUrl: 'Home/HomeView.html'
})
.when('/profile/:userId/changepwd', {
template: ' ',
controller: '',
resolve: {
data1: function($dialog, location, $q){
$dialog.messageBox(title, msg, btns)
.open()
.then(function(result){
//fires on modal close: rewrite url bar back to '/home'
location.skipReload().path('/home');
//Could also rewrite browser history here using location?
});
return $q.defer().promise; //Never resolves, so template '&nbsp' and empty controller never actually get used.
}
}
})
.otherwise({
redirectTo: '/'
});
This feels like it leaks unresolved promises, and there may be a neater solution, but this worked for my purposes.
You can redirect the route to the same partial. You can do this by watching for a change in route using the following code. You can also show a dialog from here.
$rootScope.$on( '$routeChangeStart', function(event, next, current) {
if ( next.templateUrl == "xyz.html" ) {
//other validation logic, if it fails redirect user to the same page
$location.path( "/home" );
}
});

Resources