If I have a route as such:
$routeProvider.when('/event/:id', { templateUrl: 'view/event-details.html', controller: 'EventDetailCtrl'});
Is there a way to check if the user is on the /event/:id route
Is using if ($location.path().indexOf('/event/') !== -1) a safe way to check if the user is on this route?
Of course there is. Either you can use a console.log in controller or another way you can use an ng-init in the template URL to call any function. So if the template is loaded then it will call the function and hence you get to know that the user is on that route :)
I'm not sure to fully understand what you want to achieve. Your $routeProvider relays your incoming request to a particular controller. It is inside the controller you can fully access the tokens parsed by your $routeProvider.
Declare $routeParams in your controller to access the tokens of your matched route.
$routeProvider
.when('/event/:id', { templateUrl: 'view/event-details.html', controller: 'EventDetailCtrl'});
In your controller:
.controller('EventDetailCtrl', function($scope, $routeParams) {
$scope.id = $routeParams.id;
})
Related
I trying to create a search application using angularJS.I am facing the issue in binding $scope values to view when router Url changes.
I have a search field in /main.When I write the query and click on search button, the function does the data fetch and assign to a scope variable.The router URL will change to '/Result' and the respective view is displayed.But the view doesn't have the scope values bound. /main and /Result uses the same controller.
router code in main module :
$routeProvider.
when('/main', {
templateUrl: '/views/search.html',
controller: 'searchCtrl'
}).when('/Result',{
templateUrl:'/views/Result.html',
controller: 'searchCtrl' ,
reloadOnSearch: false
}).otherwise({
redirectTo: '/main'
});
Controller :
On button click from /main
$scope.fetchResult=function(searchWord){
shService.fetchResultDocumentsList(searchWord).data.then(function(response){
//service call here-data fetch is successfull.
$scope.docResultList=response[0];
$scope.docResultList=response[0];
$scope.documents = $scope.docResultList.data.documentEntities;
$location.path('/Result');
}
When the respective view is changing, the binding is not done.But when i replace the $scope.documents with $rootScope.documents binding is successful.
I have read the use of $scope is encouraged over $rootScope.
The controller and $scope gets re initialized when you move from one page to another page. if you want to use $scope , you should consider using service to share the data across controllers.
Create a service, that will hold your variable.
angular.service("dataService", function() {
this.value1 = ""
});
reference that service in your controllers,
angular.controller("myCntrl1", function($scope, dataService) {
$scope.val= dataService.value1 ;
});
angular.controller("myCntrl2", function($scope, dataService) {
$scope.val= dataService.value1 ;
});
As Sajeetharan said, $scope get reinitialized when you update location.
Using angularJs, you don't need to change location. You simply update $scope in the same view you used for searching.
But if you really need to use another view, and assuming your search returns only strings, you could try to pass data through url, and grab it from your controller.
Something like this (not tested):
Solution 1 (Angular way)
Controller
$scope.documents = ""; // init your results to empty/null, as you need
$scope.fetchResult=function(searchWord){
shService.fetchResultDocumentsList(searchWord).data.then(function(response){
//service call here-data fetch is successfull.
$scope.docResultList=response[0];
$scope.docResultList=response[0];
$scope.documents = $scope.docResultList.data.documentEntities;
$location.path('/Result');
}
View
<!-- search div is over here -->
<!-- results goes here -->
<div ng-if="$scope.documents">
{{$scope.documents}}
</div>
Solution 2 (your way)
Router
$routeProvider.
when('/main', {
templateUrl: '/views/search.html',
controller: 'searchCtrl'})
.when('/Result/{data:[a-z]{1,}}',{ //here we specify that data expected format is only lowercase letters
templateUrl:'/views/Result.html',
controller: 'searchCtrl' ,
reloadOnSearch: false
})
.otherwise({
redirectTo: '/main'
});
Controller
// dont forget to inject $stateParams service in your controller
if( !$stateParams.data){
$scope.data = $stateParams.data;
}
I have a route defines as follows:
$routeProvider.
when('/projects/', {
controller: 'ProjectCtrl',
controllerAs: 'project_ctrl',
templateUrl: '/static/app/partials/project.html'
}).
After the login finishes I need the user to land on this link, hence in my controller I am using this:
vm.login = function(form) {
if (form.$valid) {
loginService.login(vm.loginFormData.username, vm.loginFormData.password);
loginService.setUpUser()
$location.url("/projects");
}
}
But unfortunately the controller associated with this view is not triggered, that is ProjectCtrl is not triggered. However when I click on the navigation link which uses in the dom, it works fine. Can someone please guide me here, may I am missing something conceptual.
Hence the larger question is how do I redirect a user in the controller using some APIs which also complies with ngRoute based controllers.
Try removing the last / in url so it matches $location.url("/projects");
$routeProvider.
when('/projects', {
When user lost password, an email is sent to his account with an URL. I want the page that controls a reset password only loads if the url has a parameter. Im using Angular.
For example:
if user goes to http://example.com/reset_password/A232Ddade
loads the reset_password/reset_password.html page normally
but
if user goes to http://example.com/reset_password/
redirect to http://example.com/index.html
Another thing to consider is that before rendering the page, I will use the parameter to find the user that will change the password.
To make this happens I have to use some initialize function, read the parameter and if it is present use it or if it is not present redirect to index page? like
//At the top of the controller
var init = function () {
//check if there is query in url
//and redirect if not
};
//and fire it after definition
init();
Or Can I use the ui-router module?
Thanks.
It's look like standard usage of $routeProvider
app.config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/reset_password/:param', {templateUrl: 'pageToReset.html', controller: ResetLogicCtrl}).
when('/reset_password/', {templateUrl: 'index.html', controller: IndexCtrl}).
otherwise({redirectTo: '/'});
}]);
You can do that with Resolve, on your route. Take the param and get the user with it, if there is no user, or if param is falsy value, redirect to wherever you want. That way your controller gets the needed data or it redirects.
Using Angular I have a dozen or so routes setup similar to the following example code.
Is there a way to override which template and controller is loaded based on some other criteria while keeping the URL in tact? My goal is to display a login page when... lets say $scope.isLoggedIn = false. I don't want to change the URL to /login.
SomeApp.config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/place', {
templateUrl: 'routes/place.html',
controller: 'PlaceCtrl'
})
.when('/test', {
templateUrl: 'routes/test.html',
controller: 'TestCtrl'
});
}]);
ngRoute is a very simple library that can basically only maps urls to controller/views. If you want more flexibility, try ui-router which has the ability to route based on state.
This isn't really doable with ngRoute, but with ui-router you can dynamically provide different templates based on just about anything you want.
$stateProvider.state('root',
url: '/'
controller: 'HomePageController'
templateProvider: [
'$rootScope'
'$templateCache'
'$http'
($rootScope, $templateCache, $http) ->
templateId = if $rootScope.isLoggedIn then "home-page-logged-in" else "home-page-not-logged-in"
templateId = "/templates/#{templateId}.html"
return $http.get(templateId, cache: $templateCache)
]
)
The catch is, as far as I know, you can't change the controller, only the template. Which kinda stinks.
I have an Angular JS application with a defaultController which controls the header of the app. Then I have some other controllers one for each view. The views are loaded in the <main>. I load the views using the $routeProvider with this code:
myapp.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/login', {
templateUrl: 'templates/login.html',
controller: 'loginController'
}).
when('/dashboard', {
templateUrl: 'templates/dashboard.html',
controller: 'dashboardController'
}).
...
I am trying to display a LOGOUT button inside the header when the loaded view is the dashboard and hide it if the loaded view is the login view. In order to do that I have on the defaultController the $location object and I properly add and remove classes from the LOGOUT button with ng-class.
There is only one problem: $location gives me the correct path the first time I load the page, but after I change the view (changed by the $routeProvider) that variable is not updated anymore, so when I am actually on /#/dashboard , the $location.url is still on /login. Here the controller code:
controllers.controller('defaultController', ['$scope', 'ipCookie', '$location', function($scope, ipCookie, $location) {
$scope.url = $location.url();
...
I also tried with $window.location.hash with the same result.
Any idea?
EDIT: after the accepted answer this is what I ve added on the defaultController in order to make it work
$scope.$on("$locationChangeSuccess", function() {
$scope.url = $location.url();
});
The location is probably updated in the service after your default controller is loaded.
You can either inject the $location service into the scope and make decisions in your template based on it (then it will automatically be watched and re-evaluated) or you could listen for the $locationChangeSuccess event.
When injecting, you can simply $scope.location = $location and then use something like <a ng-hide="location.path() != '/something'">.
$location broadcasts the $locationChangeSuccess on the root scope, so you should be able to listen for it on whichever scope you have available: $scope.$on( "$locationChangeSuccess", function() { /* do something */ } );