I've run into this on a few apps now, so I wonder if I'm doing something wrong with Backbone history. Here's the situation...
I have two pages, let's say:
index.html
app.html
The index page is just a normal, flat HTML page with a link to app.html. On the App page, Backbone.history.start() is called to fire up hash state management, which is used to toggle between two views on the App page, say:
app.html#search
app.html#results
So, navigating back and forth between the #search and #results pages works great. No problems there. The issue occurs when you try to use the back button to step all the way back to index.html. The path back to the index page involves a stop at app.html (no hash state), at which the Backbone router dutifully fills in missing hash state, putting you back at app.html#search. Again, clicking the back button will go to app.html, which fills in the missing hash state again... basically, you're now stuck in a loop and can't go back from the page. This same behavior occurs when using push state.
This seems like a potentially common problem with apps that automatically fire up their own routing system on top of a default page URL. Does anyone know of a good way to avoid this?
The problem is that app.html isn't doing anything on it's own; and so, may somehow break the app if navigated.
In this case, what you could do is instead of redirecting the root route to another, just use it as the default page:
routes: {
"": "search",
"results": "results"
}
Related
I am new to Vue. I am using Vue-router and I have some animations and videos on my index page.
I would like to prevent the index page from refreshing if I navigate away to the about page for example, so that the user, when they click back to the index page won't have to start the videos and animations again.
Which lifecycle hooks would I need to make use of and is their a simple way to implement it?
After #Yom S pointed me in the direction I did some research and discovered that wrapping the router-view HTML elements in keep-alive tags we can achieve the outcome I desired. By explicitly naming the components one can make use of "includes" "excludes" keywords within the keep-alive element to include or exclude certain router views from re rendering
here is a link to an informative conversation on the vuejs forum regarding this very problem
https://forum.vuejs.org/t/conditional-keep-alive-with-vue-router-not-working/4319
I'm working on a project using react with flux architecture.
I have several views and a store called ContextStore in which I save the current view in the state, so that when an action to change the view is triggered this store change his state and the Main view listen and change it.
But the problem is that always when I refresh the page with F5 it always goes to the initial Views.
What is more, if I press the back button the View has no change.
I think that my problem is because when I refresh the Main view loads again the initial state. How could I solve it?
Thanks!
You might want to look into using a router to manage your views. Here's the one I use: https://github.com/rackt/react-router. When you transition to different views (routes) it adds to the history stack so you can use the back button. However, I don't have the use case where you need to stay on the current view when you refresh, so you might need to use cookies or session storage in those instances in any case.
You are right, when hitting F5 you are completely reseting all javascript, ergo the store looses its state. You need to use some kind of storage for saving the state. Classical ways are cookies, or you could use IndexedDB which is included into HTML5
Should Backbone routers be used for nested views also, as it it is used for navigating in between more complete page views and some other sorts? When to use a router and when to use inner views?
For example a home view page has tabs and each tab for showing another view with its model and collection. This home view is similar to Twitter or Facebook. How should this complete page be rendered:
By navigating via router to subviews on tab clicks and rendering by subviews render function and placing them in home view page by homeview render, or routers is not and not good for this purpose. Advantage: a.bookmark-able subviews, b. ?more maintainable code. Disadvantage: on page refresh homeview part not rendered, only subview does.
Instead, on tab clicks subviews should be created in homeview and
rendered in themselves and placed in the home view page by homeview
render(). Advantage: no disadvantage above. Disadvantage: no advantage a, ?b above.
UPDATE:
A hybrid solution to refresh problem in 1. To have each subview to render homeview parts, tabs etc., by depending on a seperte single little template for that or from their templates having written those parts code to have those homeview parts. Disadvantage here is like separation of modules decreases a bit by subviews requiring (as dependancy) or including (in their template) something that is not sub at all but something like sup, main, belongs to an upper level module.
Or is there another, better, way?
Ultimately it's subjective; there is no rule for when you should start a new page View triggered by a Backbone.Router route and when you should just re-render a sub-view for a part of the DOM without involving a route. Really, it's just a matter of whether you want the user to feel like they've gone to a new page or not. Ask yourself:
do you want them to be able to click back/forward in their browser?
do you want them to be able to bookmark the "page"?
is most of the DOM changing or just a small part?
To put it another way, when a user goes to a Backbone.Router page it indicates that a significant change in state has occurred on your site. Really all the bookmarking/history entry/significant DOM changes are just reflections of that. So if you feel that a significant change, whatever that means to you and your site, is happening, make a route for it. Otherwise just re-render a View.
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"