$location.path() is navigating to some other page - angularjs

I have below states defined-
.state('HomePage', {
url: '/HomePage',
templateUrl: 'home.html',
controller: 'HomeCtrl'
})
.state('RegistrationHome', {
url: '/RegisterHome',
templateUrl: 'RegistrationHome.html',
controller: 'RegistrationHomeCtrl'
})
.state('RegisterAdditionalInfo', {
url: '/RegisterAdditional',
templateUrl: 'RegistrationAdditional.html',
controller: 'RegistrationAddCtrl'
})
From home page when I click on register button, I will be navigating to registration home page using $location.path('/RegisterHome');
Now on registration home page I provide my email Id and username and click on continue button. After clicking on continue button it provides additional fields (Age and Gender) to be filled on the same page. On click of continue $location.path('/RegisterHome/RegisterAdditionalInfo') is loading the RegistrationAdditional.html. Age and Gender are present in RegistrationAdditional.html.
Now there is one 'Cancel' button. If I click on 'Cancel' button I want to go to HomePage. On click of cancel I am calling one function in the controller and in this function I am writing
$location.path('/HomePage'); for navigation. But it's not navigating to HomePage. On click of cancel it's navigating to 'RegistrationHome'.
In url function ($location.url()) I tried to print the url. On click of 'cancel' , url is 'HomePage' but again url function is being called automatically and url value is getting changed to 'RegistrationHome'. I tried all possible ways like writing $scope.$apply() after $location.path('/HomePage'), using $state.go('HomePage') instead of $location.path('/HomePage'); but nothing worked. Could someone plz help me on this.

Related

Navigate back to state without reloading template

I have done some research but couldn't find a definitive answer. I have main application area where I load different screens. From one screen I want to open a page that would cover the whole screen. So, navigating to 'viewreport' does exactly that. And when I click on Browser's Back button or have my own Back button on the whole screen page I want to get back to the previous state without reloading its template and controller. Another words, I want to see all selections I have done prior opening the whole screen page. Here is my state configuration:
$stateProvider
.state('body', {
url: '/',
abstract: true,
template: '<div ui-view />'
})
.state('viewreport', {
url: 'viewreport',
templateUrl: 'wholescreen.html',
controller: 'wholescreenController'
});
I am loading different modules into the main 'body' state which might look like this:
function ($stateProvider) {
$stateProvider.state('body.htmlreports', {
templateUrl: function ($stateParams) {
return 'htmlReports.html';
},
controller: 'htmlReportsController',
url: 'htmlreports',
}).state('body.htmlreports.reportarea', {
templateUrl: 'htmlReportParams.html',
controller: 'htmlReportParamsController',
});
I am navigating to viewreport state from htmlReportParamsController controler. The new page then opens into the whole screen. That part works fine. But navigating back to htmlreports when clicking on the Browser's Back button will reload 'body.htmlreports' state. Is there a way of getting back to it without reloading its template?
Update. Why I think it's not a duplicate.
I tried what's suggested in it before posting. This: $state.transitionTo('yourState', params, {notify: false});
still reloads 'yourState'. Also the use case in the provided link is not exactly as mine. Because the OP uses edit mode for already loaded view while I am loading a new view over the the whole screen.
Thanks
Use
$window.history.back();
Add $window in dependency injections of your controller. This will refresh your page and wont reload data we selected.
Please maintain states like this
function ($stateProvider) {
$stateProvider.state('body.htmlreports', {
templateUrl: function ($stateParams) {
return 'htmlReports.html';
},
controller: 'htmlReportsController',
url: 'htmlreports',
}).state('body.htmlreports.reportarea', {
templateUrl: 'htmlReportParams.html',
controller: 'htmlReportParamsController',
}).state('body.htmlreports.reportarea.viewreport', {
url: 'viewreport'
});

Redirecting to parent state on tab click

I have an Ionic application that has 4 tabs menu and one of tabs is actual menu page that has some links of it's own, so quick snippet:
.state('menu', {
url: '/menu',
params: {user: null},
views: {
'tab-menu': {
templateUrl: 'menu.html',
controller: 'menuCtrl'
}
}
})
.state('user-profile', {
url: '/menu/profile',
params: {user: null},
views: {
'tab-menu': {
templateUrl: 'user-profile.html',
controller: 'menuCtrl'
}
}
})
So when user taps "Menu" Ionic tab, and then taps on profile page, everything works fine. Then user clicks "Home" tab and that also works fine. But after that, when user taps on "Menu" tab again it will go to profile page, and not to actual Menu page.
How do I make it go to menu page?
Solution to this problem as follows:
Tabs have ui-sref property:
ui-sref="main.live.tabs.ranking"
And this is causing the problem with redirection. Instead, just create controller with method
$scope.goToState = function () {
$state.go('state');
}
And modify tab by removing ui-sref and replacing it with
ng-click="goToState()"

Use href to redirect to tab in angularjs

I'm currently trying ionic with the tab template. I got to the stage where I have a second-level tab in one of my main tabs.
.state('tab.leaderboard', {
url: "/leaderboard",
abstract:true,
views: {
'tab-leaderboard': {
templateUrl: "templates/tab-leaderboard.html",
controller: 'LeaderboardCtrl'
}
}
})
.state('tab.leaderboard.players', {
url: "/players",
views: {
'leaderboard-page': {
templateUrl: "templates/players-leaderboard.html",
controller: 'PlayersCtrl'
}
}
})
.state('tab.leaderboard.teams', {
url: "/teams",
views: {
'leaderboard-page': {
templateUrl: "templates/teams-leaderboard.html",
controller: 'TeamsCtrl'
}
}
})
If I use a direct link to my tab tab.leaderboard.teams, the url on the address bar changes, the bar title changes but the content is not loading and the current page from where I made the call stays opened.
However if I click on a link to tab.leaderboard.teams, it works perfectly.
Also if I switch the tabs on my html and make the teams tab first then it works for teams and not for players.
Note that if I go manually to the tabs then everything is fine. The problems happens only when I use href to open it.
Any help would be appreciated.
EDIT
I also used ng-click='func()' and then on my controller used $state.go('tab.leaderboard.teams') it didn't work. Same for ui-sref on my html. The url changes but not the content.
angular-ui-router is based on states. If you want to go from one state to another then you have to use "ui-sref" or "$state.go()"
for example :
<a ui-sref="stateName">to go page</a>

Angularjs UI bootstrap temporarily change URL on open and revert to original URL on close

I want to temporarily change the browser url when the ui bootstrap modal is opened ( The page behind should remain as is, only the url changes ). When the modal is closed the url should be reverted back to the original one.
Steps :
User loads the page
url : xyz.com/home
User clicks a link opens a modal
url : xyz.com/detail/123
possible solution : changing url with html5 push state
problem : Angular ui-router tries to run its routes as per the changed url, eventually changing the background page.
User closes the modal
url : xyz.com/home
possible solution : html5 pop state
problem : Reloads the background page, which kills the purpose
Example implementation : Pinterest pins and their pin details popup.
You can use ui-router-extras sticky state to solve your problem. There is simple example with modal by the link. You should create two named views, one for main content (background) and one for modal.
<div ui-view="app"></div>
<div ui-view="modal"></div>
Mark the state, from what you want to access to modal as sticky: true in route definition.
.state('main', {
abstract: true,
url: '/',
templateUrl: '_layout.html'
})
.state('main.index', {
url: '',
sticky: true,
views: {
'app': {
templateUrl: 'index.html'
}
}
})
.state('main.login', {
url: 'login/',
views: {
'modal': {
templateUrl: 'login.html'
}
}
})
Also add an event for stateChangeSuccess:
$rootScope.$on('$stateChangeSuccess', function (ev, to, toParams, from, fromParams) {
if ((from.views && !from.views.modal) || !from.views) {
$rootScope.from = from;
$rootScope.fromParams = fromParams;
}
});
so, when you need to close modal, you can just
$state.go($rootScope.from, $rootScope.fromParams);
There is small problem for that solution. If you reload page on the modal state, then the app ui-view will be empty.
This can be achieved by having a nested state and triggering the modal using onEnter callback:
$stateProvider
.state('contacts', {
url: '/home',
templateUrl: 'home.html',
controller: function($scope, MyService){
$scope.contacts = MyService.getContacts();
}
})
.state('contacts.details', {
url: "^/details/:id", // using the absolute url to not have the "/home" prepended
onEnter: function($state, $uibModal) {
var modal = $uibModal.open({
templateUrl: 'details.html',
controller: function($scope, $stateParams, MyService) {
// get data from service by url parameter
$scope.contact = MyService.getContact($stateParams.id);
}
});
modal.result.finally(function() {
$state.go('^'); // activate the parent state when modal is closed or dismissed
});
}
});
This technique is described in the ui-router's FAQ.
Here the plunk. In this example the modal's scope is created as a child of the $rootScope - the default $uibModal's behavior when no scope is passed to it. In this case we should use the service in the modal's controller to obtain the data by url parameter.
To have master and details URLs look like these - xyz.com/home and xyz.com/detail/123 - we should use the absolute URL (^/details/:id) in the child state.
Using this solution you can open the detail URLs directly and still have both, master and detail states, activated properly, so sharing the detail URL is possible.
I think you can achive that with ngSilent module
https://github.com/garakh/ngSilent
using $ngSilentLocation.silent('/new/path/');
(once you open modal and again after closing it)
Managed to implement this using https://github.com/christopherthielen/ui-router-extras/tree/gh-pages/example/stickymodal

$location.path(...) adds an ID to url

If the user has become logged out, I want to send the user to the login page, but it fails. I have this configuration:
webShopApp.config(function($routeProvider) {
$routeProvider.when('/login', {
templateUrl: 'partials/login.html',
controller: 'LoginController'
});
$routeProvider.when('/:id?/?products', {
templateUrl: 'partials/products.html',
controller: 'MenuController'
});
});
Note the "/:id?/?" inte the code for products. Let's say the url is 'index.html#/45/products'. If the controller discovers that the user is logged out, it calls
$location.path('/login');
If I console.log the $location.path(), it says '/login' as expected, but the url in the browser is 'index.html#/45/login'. Why is the '45' (the id) still there, and how do I get rid of it, ie, redirect to 'index.html#/login' without the id from the previous path?
I guess you should use window.location = 'yourUrl'; instead of $location.path('/login'); in this case. But in this case, the page is reloaded.
see if you need to workout in pure angularjs, so please avoid javascript terms and jquery terms i.e. windows.location and $location.path; Better option is always to route the user to login page whenever the user gets logout from the App.
for this you can specify it at the routing level i.e.
$routeProvider.otherwise({redirectTo: "/login"});
or you can say a logout link on clicking of which user will be redirected to login page
$routeProvider.when('/logout', {
templateUrl: 'partials/login.html',
controller: 'LoginController'
});
I hope this may help.

Resources