I've found a weird behavior in AngularJS when clicking links. My goal would be to prevent the page to refresh when the path is the same, and only the query string changes.
The strange thing is that this happens already... but only sometimes. At least in my particular scenario, some links trigger the page refresh, and some others simply not, even when they look the same (except minor changes like ones having a title attribute and others not).
<a class="btn btn-primary" ng-href="https://.../search?_target=event&...>Edit</a>
Besides this odd thing, which perhaps is the result of me doing something wrong, I would like to ask for the common way of avoiding page refresh on link clicks, and if possible when someone manually changes the URL, but only the query string. It's annoying to have to wait for the whole app to load just because you wanted to activate some particular pop-up, for instance.
Note that I have the HTML5 mode enabled.
Thanks.
It looks like you're using absolute links in your <a> tags.
You should use your router's links (if you're using ui-router it's ui-sref to navigate state).
[EDIT]
The problem seems to be a lot different, so here's another wording:
"I need to display a popup based on my state params in all of my states, whenever my state changes".
So here's how to do it:
The logic says that since you have to display this in all of your state changes, you should hook a $stateChangeSuccess function (docs).
That way, you can implement your logic there and display pop-ups and everything. I suggest you put this into your app.js file or if the app is relatively large in some events.js file or whatever you prefer
angular.module('your_app_name').run(function($rootScope){
$rootScope.$on('$stateChangeSuccess',
function(event, toState, toParams, fromState, fromParams){
// you have your toParams, your toState and everything here, so use your logic to open your popup window.
})
});
Related
In my angular app, I have this issue. When user quickly double-clicks link to state (ui-sref link), the target state begins loading twice. This would be bearable, if the state window didn't freeze and stop responding to other state changes. When clicking another ui-sref links, URL changes accordingly, http calls on background are made, but the view is frozen.
I need to know, how can I prevent any transition, when there is another transition already trying to resolve promise. I know I can somehow work magic with $stateChangeStart and event.preventDefault(). What I don't know is how to allow my transition to continue after resolving it's resolve block and how to counterpart event.preventDefault().
Thanks for your time. Any advice will be greatly appreciated.
Angular UI Router's $state object has a property on it, 'transition', which will be present if it is in the middle of an active transition. One option is to remove the ui-sref attribute and use a ng-click attribute instead. Inside your ng-click function, you can do a manual check for the presence of the transition object before invoking $state.go().
Before
HTML:
<a ui-sref="Root.State1">
After
HTML:
<a href="" ng-click="goToStateOne()">
JS:
scope.goToStateOne = function() {
if (!$state.transition) $state.go('Root.State1');
}
In my Angular app, some routes have reloadOnSearch set to false so that Bootstrap tabs work ok.
The problem comes when a link in one of those views links to another of those views. Links just don't work, because the controller does not reload the view.
So I have to use ng-click on those links.
$scope.goToThisPage = function () {
$location.path(newPage);
$route.reload();
};
However, that does not work and always takes me to the default routing. Same happens if I replace the last line of the function with $scope.$apply().
What is the best way to move between routes that have reloadOnSearch set to false?
Do you have a separate controller for each of those tabs?
As far as I know, reloadOnSearch: false will only prevent the controller from reloading if a query parameter or hash in the url changes. So, moving between /route/page?param=1 and /route/page?param=2 will not reload the controller, but moving to /route/anotherpage definitely should.
I don't understand entirely how you're getting this issue, but for what it's worth, this is how I've solved reloadOnSearch issues when I having a single controller. Even though the controller and view don't reload when a search parameter changes, $location still does, so I would just listen to $locationChangeSuccess in the controller and make any changes to bound scope variables in the callback.
Edit
Looking at the documentation for tabs, wouldn't it be possible for you to just not use links to switch the tabs, and instead call the .tab("show") method using ng-click?
I'm trying to build an Android action bar-like navbar in Ember. I would like the action bar to show the route (friendly) name and have context dependant button's on the right side. I came a long way, this jsFiddle will explain things more clearly:
jsFiddle
However, the activate event isn't I am using to figure out when a route has been changed, is only firing when one first visits the route (traversing back up the route tree won't trigger it), thus my context isn't loaded consistently.
What would be the best way to solve this problem? I know the serialize, renderTemplate and setupController fire on every route change, but none of these methods are intended to be used this way. Is there perhaps a way to add a custom event to my routes, that fires on every route change?
On a side note, I am completely new to ember so I may be going about this completely the wrong way, in that case, I am eager to hear a generally better solution, than mine.
UPDATE:
Thanks to kingpin2k's tip I was able to clean up my code a bit, for future reference here's the updated fiddle:
jsFiddle
didTransition/willTransition were created for this reason. In your case didTransition will make the most sense.
actions: {
didTransition: function(){
console.log('level two transition');
},
}
http://jsfiddle.net/FZ29Q/
I am working on an ember.js (version 1.2) based mobile application and I am trying to find the most idiomatic way of implementing the global menu toggle/back button pattern that is common in many mobile apps. Specifically, its a button that sits on the left side of a fixed-top toolbar, which toggles a hidden drawer main menu when the user is at the app's home/index view, however upon moving into a sub route, the button displays a back arrow, and when clicked, it takes the user back to the previously viewed route (or back to the index route if there is no previous history states, i.e. if the user came into a sub route directly upon loading the app).
Fyi, currently I have my app structured with the fixed-top toolbar and menu toggle/back button in the root application template. Ideally this functionality would work no matter how a routes are being transitioned to, whether via transitionTo(), or {{#link-to}} helpers, ect.
So essentially I want to know if Ember internally maintains any sort of accessible history/log of what routes were transitioned to over the course of the app's lifetime, and also what would be the best way to conditionally change the action that the toggle/back button performs and its display (aka its icon) depending on the current route. And/or is there a way to listen to ember's route change events so I could implement that history myself if need be?
I hate to be the bearer of bad news, but I also hate to leave you hanging.
Ember doesn't keep track of the history, there isn't a general use case for it (especially since the browser keeps track of it for you).
Fortunately you can monitor route changes in the application controller, something like this should get you started (Note I didn't spend time working out an awesome solution that works perfectly, just showed you the basics you need for it, I'll let you figure out the workflow that works well for you)
http://emberjs.jsbin.com/IZAZemEP/1/edit
App.ApplicationController = Em.Controller.extend({
history: [],
hasHistory: function(){
return this.get('history.length')>1;
}.property('history.length'),
watchHistory: function(){
this.get('history').pushObject(this.get('currentPath'));
}.observes('currentPath'),
actions: {
goBack: function(){
// implement your own history popping that actually works ;)
if(this.get('hasHistory')){
this.get('history').popObject();
window.history.back();
this.get('history').popObject(); // get rid of route change here, don't need it
}
}
}
});
In a single page application, is there a way of switching back and forth to an AngularJS route and to display it back in the same state as it was shown before?
Usually this would be implemented by binding data in a parent scope. While this is easy to set up for lightweight view, it can be cumbersome when doing it for views holding lots of graphical elements.
Here is an example, where having the previous route state remembered could enhance user experience: on the following page, imagine that
you stand on Item 1 and select Tab 2
then move to Item 2
finally switch back to Item 1: Tab 2 is not selected anymore :-(
http://angular-route-segment.com/src/example/#/section1/1
It seems the views are destroyed/constructed when switching back and forth between routes.
A solution would be about storing the state of the user interface in a parent scope but it has the following pitfalls:
creating an object storing all the little details of the user interface
creating complex logic about -saving and- resetting the UI in the same state as before
storing UI state in a data model does not sound that MVC-ish
Using show/hide of div storing the views saves the state but then no route is used and the switching business must be implemented by hand. I like using routes because 1. of the browser history navigation (hash in the url) and 2. it is easy to set up.
Having the UI state not remembered is like having Chrome to reload pages when switching back and forth between tabs: not very user friendly.
Is there an Angular-way?
Your $routeSegment approach is very interesting. The $routeSegment service could plug into the $routeChangeStart event in order to
Somehow keep a "sub path history" on all paths seen so far, maybe only for those explicitly configured to keep their UI state. In your example for the path "/section1/1" the stored sub path would be "/Y" if tab 2 was selected. Things get interesting, as also dynamic paths with $routeParams might need to be covered.
Use this history for redirecting by using $location.path in the event handler. So a $routeChangeStart event with next.originalPath being "/section1/1" might be redirected to "/section/1/Y"