Angular UI Router - How to preserve views while switching views - angularjs

I am I new to Angular and UI Router.
Plunk http://plnkr.co/edit/1wfyrGryfGG5RtXozPFY?p=preview
Setup I have three top level application nav buttons Home, Projects, Help. They load different views home.html, projects.html and help.html using the Angular UI Router ui-view directive. This works good.
The Projects.html view has a tab bar with each tab corresponding to a project: D1, D2 D3 etc., I show the corresponding project tab using url router attributes.
Every time I click the Projects button it is reloading the tab bar completely. I loswe the current tab and hopefully if any nested views inside it. Basically the page contents of Project.html, invoking the controller as well.
I read through the wiki documents and couldnt figure out how to implement my required functionality. I am sure I am missing something. Will it always reload the view?
Question: How to avoid reloading the projects view contents so that I can retain the selected tab and all the contents as-is before switching to Home. Because I would have a lot of nested views and models on each project.

I wanted similar functionality too, but ui-router doesn't yet support it. I forked ui-router to support "parallel states" and submitted it to the project for comment. The gist of the conversation is that ui-router will eventually support some form of parallel states but not yet. In the meantime, you can try my fork of 0.2.10 which provides the parallel states that you want.
Read the conversation here: https://github.com/angular-ui/ui-router/issues/894
View the sample parallel tabs plunk here: http://plnkr.co/edit/YhQyPV?p=preview
Here is the fork; build it with grunt: https://github.com/christopherthielen/ui-router

One option would be to implement a service that can be used to maintain the previous state. Services persist over controller changes, thus they can be used to maintain the previous page state and updated when the route changes. something similar to this would work.
app.factory('persitDataService', [function(currentStateData){
var stateService = {
state:{
//your object data set to passed in data
}
//other functions here
};
return stateService
});
then in the controllers just inject the service and assign to a scope value. When the route changes just reset the data in service to new state and inject into new controller
This should work for the previous page state. If you are wanting to save the states of all previous pages then this becomes a larger problem but should be accomplished in much the same way only with a more complicated service setup.
This could also be combined with local and session storage

Related

How to cache state (page) during history back in Angular JS like IONIC

IONIC has a very good feature to "cache" the state by using ion-nav-view, when user access the state in history, it will not reload the page -- Controller won't be called, and we could enable the cache globally or by page.
While working on a web site, I tend to use Angular JS directly instead of IONIC since IONIC is mainly for the mobile hybrid APP development. However, I really like the way IONIC handle the "history" and page reload. I know that we could leverage Angular Service to keep page data and achieve the similar function. But I feel it's not convenient to code and we have to put everything into service instead of controller.
Take an example here, we have a pagination search on Page A, by clicking each item to navigate to page B for the detailed item information, if we go back to Page A, we do not want to re-execute the pagination search again. I feel this is a very common requirement for most web site, IONIC's ion-nav-view could achieve this function easily without moving data to service, I wonder is there any angular JS plugins or directive which could help to achieve this function, it's something very similar as what IONIC's ion-nav-view does?
I am looking for the answer too, no lucky.
One answer is
http://www.tivix.com/blog/dont-forget-the-back-button-in-your-single-page-ap
the author mentioned ngRouter's [reloadOnSearch] option, but i doubt this answer.
From ui-router v0.2.5, there's reloadOnSearch option too, but it's not for our purpose.
another answer is
http://www.bennadel.com/blog/2801-revisiting-routing-nested-views-and-caching-with-ngroute-in-angularjs-1-x.htm
I think there's no simple way now, you have to keep controller's status, and restore controller's status on popstate event, and reproduce all controller's actions.
The other way is cache rendered-html, but how can angular touch the restored-html still?
you can use $window.history.back()
History is a consequence of navigation. So I think you are actually asking about AngularJS routing which is responsible for navigation and history management features. Angularjs has built-in router but ui-router seems to be more main stream because of its additional capabilities.
I also need the same feature and I found this lib:
http://christopherthielen.github.io/ui-router-extras/#/sticky
I think It can solve the problem but it make a problem on performance
because every opened state still working in background and use memory and cpu. (as I think)
Edit
ui-router added stiky feature please see this link:
ui-router/sticky-states
Here how you can use it
1) Add Plugin
import {StickyStatesPlugin} from "ui-router-sticky-states";
angular.module('myapp', ['ui.router']).config(function($uiRouterProvider) {
$uiRouterProvider.plugin(StickyStatesPlugin);
});
2) Mark a state as sticky
let adminModule = {
name: 'admin',
sticky: true,
views: {
admin: { component: AdminComponent }
}
}

Use Angular Ui-router without any views or templates

I've used UI router in the past in single page applications and found it prefect for loading new views and syncing them with the URL. However, I now have a normal multi-page ecommerce site which uses Angular a lot on various pages. Including te search results page.
I need to use ui-router only on this page to do ajax paging. Basically the content is already loaded onto the page and I have an ng-repeat for the results. It's a very simple set up.
What I want to do is change the state/url when the user hits the next/previous buttons and watch the stateParams to look for the new page number, then manually reload the new results and re-bind the ng-repeat to show the new results. Obviously I could load new search results without using ui-router at all but I want the back button to work so that you can go back through the pages.
Now, as far as I can see none of this requires any ui-view tags, or templates or controllers. I simply want to update the URL when a button is clicked and watch for changes. Is this possible with UI-router and if it is then what routes (if any) do I put into $stateProvider config?
Any help would be greatly appreciated.

Loading controllers when navigating through screens

I'm currently using directives in my ionic app, there directives are normally bind to a angular controller. So my problem is, when I navigate through the app, my controllers are not loading (loads for the first time) and hence I cannot setup some initial values.
Following is an example
I navigate to users screen/page
users controller loads (When I check with Chrome dev tools)
I navigate to home screen
I navigate back to users screen
At this point I expect users controller to load again, to setup my initial values, but it's not happening
I'm not sure if this is the default behavior, or am I missing something?
if you are using nested states, parent.child1, parent.child2, parent only loads 1 for the entire hierarchy, changing from child1 to child 2 will not reload the parent controller, thats one of the pros of using ui-router.
also note that with ionic latest version they introduced view caching so, the controller is only instanciated once for each view, to prevent that you need to use
cache-view="false"
in your ion-view
http://ionicframework.com/docs/api/directive/ionNavView/

General approach of left side menu that loads different content in a center of the page

I've started to learn AngularJS but I need some application design hints. Of course I'm not asking about the layout but ... how to design my application and it's controllers in a proper way. I have left sidebar with a menu that is loaded from the web using JSON. That needs a controller. That's fine. It works for me. There's a content box as well in a center of my page that loads some data dynamically. In my opinion it requires another controller.
And now comes my solution, that somehow doesn't look good IMHO. When I click a menu item in my sidebar I'm loading a content. Then I'm passing this data into a Service which emits an Event afterwards to the Second controller (which is responsible for controlling my content in a center of my page). When it receives this event it simply gets previously loaded data from the Service and displays it. It generally works.... but ... I'm pretty sure that's not the proper way of doing this.
I would be grateful for any hints. AngularJS has a really poor documentation and tutorial :(
cheers
EDIT:
OK. That's my basic application using JQuery:
http://greatanubis-motoscore.rhcloud.com/index
And that's the same application I'm converting into AngularJS:
http://greatanubis-motoscore.rhcloud.com/angular/index
No worries, some text is in Polish but... I think it really doesn't matter ;)
Note for the AngularJS version: At the moment the content is a HTML but finally it will load JSON data as the other controllers.
I would go about doing this with angular ui-router. With ui-router you can achieve this in a couple of ways. You can use nested routing to have a base state (Your sidebar menu, header etc.) which will act as your shell page, this can have its own controller as well. You could then define each of those other views as child states of the base state. These child states can also have their own controller/views as well, but they will be sitting inside the base state (both visually, and also inherit $scope properties of the base state) optionally they can have separated URLs themselves, but they don't have to, you can just change states without changing the url, by leaving the URL bit empty when you define different states in your $stateProvider configs. Another way would be to use the multiple named views feature.

How to preserve state of hidden views?

I'm an Angular newbie working on a Phonegap application with a few views: a map, a list, and search.
As the user interacts, each view accumulates some UI state: the map is dragged, the list gets a scroll position, a detail view is opened for a list item, a search is performed, etc. I'd like for the user to be able to navigate among views without losing this state.
When I put my views in partials in ng-view, and my nav links use href="#/path", or ng-click to trigger location.path(path), the controller is run and state is obliterated. Makes sense.
One option would be to ng-include all partials in index.html and ng-show based on the user's nav actions. However, I've found that this kind of complexity in the DOM will lead to poor Phonegap performance. It also feels that by eschewing routing, I'm losing one of the main benefits of using Angular.
Another thought: nav clicks cause traversal of browser history. Seems tricky to maintain the state of all views in parallel, however.
My question: is there a good pattern for this?
FWIW currently using Phonegap 3.0 and Angular 1.1.5. Thanks for your time.
If you want to preserve the state of the DOM in parallel views, there's an extension to ui-router called ui-router-extras. It has a a nice demo with state transitions and full DOM preservation when switching among tabs.
you can keep all the data that needs to persist between controller reloads in services
a simple example here
Preserve state with Angular UI-Router
a more complex example here that includes restoring state if the user leaves the page and then presses the back button
Maintain model of scope when changing between views in AngularJS

Resources