angular: state change looses URL at second click - angularjs

I have 4 states, each representing a different visualization. The first visualization is a map, the second to fourth are pie charts.
The default is the map visualization. I have three icons showing always the other 3 possible visualizations.
Each of the state is actually a nested state. The first state is "root.map", then we have "root.vis1", "root.vis2", and "root.vis3".
When I initially load the default "root.map" visualization, all is fine first. Then I click on an icon, and all works fine, the visualization changes. The URL in the browser becomes "localhost:3000/#/root/vis2" for example. But when I click again, although the visualization correctly changes to the chosen one, I loose the path in the browser, and it becomes "localhost:3000/#".
What could be causing this? I'd like the URL in the browser to always reflect the current URL (so it can be bookmarked or shared).
The state provider config:
$stateProvider
.state('home', {
url: "/home",
templateUrl: "views/home.html",
})
.state('root', {
abstract: true,
url: "/root",
cache: false,
templateUrl: "views/root.html"
})
.state('root.map', {
url: "/map",
cache: false,
templateUrl: "views/map.html",
resolve: {
//some resolve code
}
})
.state('root.vis1', {
url: "/vis1",
cache: false,
templateUrl: "views/vis.html"
})
.state('root.vis2', {
url: "/vis2",
cache: false,
templateUrl: "views/vis.html"
})
.state('root.vis3', {
url: "/vis3",
cache: false,
templateUrl: "views/vis.html"
});
}
The icons:
<a class="inline vis-icons" href="#" ng-click="set_visualization('vis2');"><i class="fa fa-map-marker"></i></a>
The set_visualization function in the controller:
$scope.set_visualization = function(visualization) {
$scope.current_vis = visualization;
$state.transitionTo('root.' + visualization);
return false;
}

Change it to:
<a class="inline vis-icons" href="" ng-click="set_visualization('vis2');">
Or
<a class="inline vis-icons" ng-click="set_visualization('vis2');">
See:
href overrides ng-click in Angular.js

Related

Ionic back button with parent and child state

I have an ionic app with the following ui-router setup, where locations state is the parent of 2 states map and favourites. The updates state is a sort of details page that can be access from any state.
.state('locations', {
abstract: false,
cache: true,
url: '/locations',
templateUrl: 'templates/locations.html',
controller: 'LocationsCtrl'
})
.state('locations.favourites', {
cache: true,
url: '/favourites',
templateUrl: 'templates/locations.favourites.html',
controller: 'LocationsFavouritesCtrl'
})
.state('locations.map', {
cache: true,
url: '/map',
templateUrl: 'templates/locations.map.html',
controller: 'LocationsMapCtrl'
})
.state('updates', {
cache: true,
url: '/updates/:place_id',
templateUrl: 'templates/updates.html',
controller: 'UpdatesCtrl',
params: {'place_id': 'undefined'}
})
// if none of the above states are matched, use this as the fallback
$urlRouterProvider.otherwise('/locations/map');
This is the HTML
<body ng-app="app" animation="slide-left-right-ios7">
<div>
<div>
<ion-nav-bar class="bar-turq">
<ion-nav-back-button class="button-icon icon ion-ios-arrow-back light"></ion-nav-back-button>
</ion-nav-bar>
<ion-nav-view></ion-nav-view>
</div>
</div>
This works perfectly except that the back button on the "updates" state always goes back go locations.map rather than remembering the previous state, ie I might have come from locations.favourites. Is there something fundamentally wrong with my setup?
**
UPDATE:
**
Okay so inside UpdatesCtrl I added this code to check the view history, and no matter where I access the /updates view from, the back view is locations.map
$scope.$on('$ionicView.enter', function() {
console.log($ionicHistory.viewHistory());
}
Remove this params: {'place_id': 'undefined'} or make sure that you pass thru the place_id in $stateparams.place_id
I think that you are ending in an none unknown state (unresolved) and goes to your default state.
You haven't posted your default location route. But I'm assuming that it has this config: $urelRouterProvider.ohterwise('/location.map');

angular ui-router state child view not updating after edit

When I make changes to the template from an sub state and I go to the view again the first loaded (so before the template was updated) view is given.
I have tested it with google chrome. internet explorer, microsoft edge all the same problem.
my state
$stateProvider
.state('games', {
abstract: true,
url: "/?username&token",
templateUrl: "games/views/Games.html",
controller: 'GamesController'
})
.state('games.open', {
url: '',
templateUrl: "games/views/GamesOpen.html"
})
.state('games.active', {
url: "/active",
templateUrl: "games/views/GamesActive.html"
})
HTML
<a ui-sref=".open"><button>open games</button></a>
<a ui-sref=".active"><button>active games</button></a>
<div ui-view></div>
The problem seems to be that the views are cached, the transitions work perfectly only I can't view the updated template and always see the first loaded template that was loaded and never the updated version..
A similair question fixes it by adding ?'+ new Date() at the end of the url but this looks like a hack.
you don't have any url in your game.open state: please check that.i guess that is an issue.
When i was creating an app
i used this code :
(well in my case in my certain app )
app.config(function($stateProvider,$urlRouterProvider){
$stateProvider.state('list',{
url:'/list',
templateUrl:'templates/list.html'
});
$stateProvider.state('edit',{
url: '/edit/:noteId',
templateUrl: 'templates/edit.html',
controller:'EditCtrl'
});
$stateProvider.state('add',{
url: '/add',
templateUrl: 'templates/edit.html',
controller:'AddCtrl'
});
$urlRouterProvider.otherwise('/list');
});
and use
a button like this:
New Note

UI-Router considering url as state

I have my routing defined as below
$stateProvider
('MasterPage', {
url: '/',
templateUrl: 'views/master.html',
})
.state('MasterPage.dashboard', {
url: 'dashboard',
templateUrl: 'views/dash.html',
})
.state('MasterPage.test', {
url: 'test/:id',
templateUrl: 'views/test.html',
})
$urlRouterProvider.otherwise('/');
I have links that allows me to navigate from mainpage to dashboard and then to the test page which works fine. When I navigate to the test page with an id:1234, which makes my url as <HOST>/#/test/1234, and try to refresh it fails. It gives me an error saying:
Cannot resolve state 'MasterPage.test/1234' from 'MasterPage.test'
Why is UI-Router considering the url segment as a state?
Update
I dont have any ui-sref. I am going to the test page by using $state.go('MasterPage.test', {id:1234}).
There is working plunker
This issue is usually related to wrong ui-sref setting
<a ui-sref="MasterPage.test/1234">
we need to split and pass 1) the state name, and 2) state params like this:
<a ui-sref="MasterPage.test({id:1234})">
In case, we want to use href, we just have to concatenate parent and child url definitions (parent '/', child 'test/:id') :
<a href="/test/1234">
EXTEND
So, these states (almost unchanged):
.state('MasterPage', {
url: '/',
templateUrl: 'views/master.html',
})
.state('MasterPage.dashboard', {
url: 'dashboard',
templateUrl: 'views/dash.html',
})
.state('MasterPage.test', {
url: 'test/:id',
templateUrl: 'views/test.html',
})
will work with these links
<a href="#/">
<a href="#/dashboard">
<a href="#/test/1234">
<a href="#/test/9875">
<a ui-sref="MasterPage">
<a ui-sref="MasterPage.dashboard">
<a ui-sref="MasterPage.test({id:2222})">
<a ui-sref="MasterPage.test({id:4444})">
There is working plunker

Ionic nav views with side menus lose history when swtiching tab

I'm trying to migrate a native app to Ionic but I'm experiencing one major issue which is almost certainly a blocker if I can't at least work around it.
Basically, I have an application with multiple tabs and each of them has a split view. I attached a plunker to demonstrate what a simplified app version would look like. My problem is that when switching tab, ion nav views do not keep their history. To be more specific about my example: after selecting a playlist from the side menu and switching tab to "Search" and then back to "Playlists", the navigation history on that tab is not preserved and gets reset to its "root" state.
I think this happens when the ion-nav-view element is not a direct child of the ion-tab element (as in my case, since it's inside a ion-side-menu-content), but I'm not quite sure.
Overall, I feel the app states in the example might need some love as well. What am I doing anything wrong? Is it a known Ionic limitation?
State provider configuration follows, below is the link for the full plunker example:
$stateProvider
.state('tabs', {
url: '/app',
abstract: true,
templateUrl: 'tabs.html',
controller: 'AppCtrl'
})
.state('tabs.search', {
url: '/search',
views: {
'search': {
templateUrl: 'search.html'
}
}
})
.state('tabs.playlists', {
url: '/playlists',
views: {
'menu': {
templateUrl: 'playlists.html',
controller: 'PlaylistsCtrl'
},
'menuContent': {
templateUrl: 'empty.html'
}
}
})
.state('tabs.playlist', {
url: '/playlists/:playlistId',
views: {
'menu': {
templateUrl: 'playlists.html',
controller: 'PlaylistsCtrl'
},
'menuContent': {
templateUrl: 'playlist.html',
controller: 'PlaylistCtrl'
}
}
});
Here's a plunker with the app: http://plnkr.co/edit/UZp3EE3l6X5IIdvpu477
Thank you!
According to This other question, every time you navigate through a tab, it creates a new history, so there's no back. You would need to handle this with your own code. They propose to use the goBack() directly. Something like:
$ionicHistory.viewHistory().backView
Also, you would need to handle the case when there's no backView because you just logged in into the app.

AngularJs UI router - one state with multiple URLs

I have a request to add in another URL parameter that directs to a state that I already have set up. For efficiency purposes, I'm trying to see if I can add multiple URLs to point to the same state, or should I just use the $UrlRouterProvider.when() method to re-direct to that state in this new case.
Ex. this is what already exists
.state('site.link1',
{
url: '/link1',
templateUrl: '/views/link1.html',
controller: 'link1Ctrl'
})
and the request is to add www.site.com/newlink that points to the link1 page. Is there something like this;
.state('site.link1',
{
url: '/link1, /newlink',
...
Try using the Regex and a parameter in the url. It is not optimal but works.
.state('site.link1',
{
url: '/{path:link1|newlink}',
templateUrl: '/views/link1.html',
controller: 'link1Ctrl'
})
More information on regex in Urls.
To generate links with ui-sref pass the same parameter with the state name as a function
<a ui-sref="site.link1({path:'link1'})" >site link 1</a>
<a ui-sref="site.link1({path:'newlink'})">site new link</a>
You use params:
https://github.com/angular-ui/ui-router/wiki/URL-Routing
.state('site.link',
{
url: '/{link}'
..
}
so when you use the same state like this
$state.go('site.link', {link: 'link1'})
$state.go('site.link', {link: 'link2'})
you can used when() function
.state('site.link1',
{
url: '/link1',
templateUrl: '/views/link1.html',
controller: 'link1Ctrl'
})
then on root config
angular.module('myApp', [...])
.config(function ($urlRouterProvider) {
$urlRouterProvider.when(/newlink/, ['$state','$match', function ($state, $match) {
$state.go('site.link1');
}]);
});
I found this approach to be quite simple and clean: create two equal states, just changing the url property
//Both root and login are the same, but with different url's.
var rootConfig = {
url: '/',
templateUrl:'html/authentication/login.html',
controller: 'authCtrl',
data: {
requireLogin: false
}
}
var loginConfig = Object.create(rootConfig)
loginConfig.url = '/login'
$stateProvider
.state('root', rootConfig)
.state('login', loginConfig)
I had almost the same problem, only with another constraint - I didn't want to use a redirect, since I wanted the url in the browser to stay the same, but display the same state.
This was because I wanted the chrome saved passwords to work for users that already saved the previous url.
In my case I wanted these two urls :
/gilly and
/new/gilly
to both point to the same state.
I solved this by having one state defined for /gilly, and for the second url, I defined an abstract state called /new.
This should be set up like this :
$stateProvider.state('new', {
abstract: true,
url: '/new'
template: '',
controller: function() { }
}).state('gilly', {
url: '/gilly',
template: 'gilly.html',
controller: 'GillyController'
}).state('new.gilly', {
url: '/gilly', // don't add the '/new' prefix here!
template: 'gilly.html',
controller: 'GillyController'
});

Resources