Combining multiple ng-apps into a single app - javascript

The Problem: We have multiple angular apps running on the same page. One for the footer. One for the header and one for a login modal. Each with it's own state and each user ui.router.
The challange: We would like to combine them into a single ng-app in the least invasive manner. The main issue here is that when we try to combine them, switching states causes some areas to disappear,
Our first "naive" approach is to do something like:
angular
.module('bigApp', ['smallApp1', 'smallApp2'])
.run(['$state', function($state) {
console.log("Big app running!");
}]);
This seems to result in selective rendering. For example. When I click a link to go to a state defined in smallApp1 the view for smallApp2 disappears.
Am I correct in my assumption that a new common parent state will have to be created? The parent state will need to have subviews to render the small apps that need to stay in place? and not disappear when state changes?

You will need to map out your new states and components. You can use hierarchical states, so for example the
"menu" state - contains navigation, status bar (always present)
"menu.home" - contains the central home page
"menu.people" - contains your list of people
"menu.people.individual" - contains details of an individual (a sub view of "menu.people")
Once you have mapped out your structure, you can work out which parts will use ui-view, and which will use components. Each component can have its own controller under one app.

Related

Change route when React.js component changes

I'm not quite sure what would be the best way to handle a particular scenario.
With 2 components rendered on the same page, links in one component will control the data displayed in the other component.
I am using the Flux pattern, so I typically would propagate this through, but my goals are:
reflect the change in the url /path
no actually navigate away or cause transition
One of my constraints is: the component with the links is a 3rd-party library that renders the links. But I have control ove the URL's.
I am not sure if it is possible to both:
use the Flux pattern for this scenario
And (with react-router) reflect the selection in the URL
e.g.
/some/url/1
[comp1] -> link clicked -> [comp2] -> displayed data changed
path becomes -> /some/url/2
Any suggestions?

AngularJS Routing: Keep view loaded, but invisible (save scroll location and prevent reload of data)

So I'm trying to make a single page web application that makes use of AngularJS's routing mechanism and so far it's working brilliantly, but I noticed that when the route changes, the view seems to be completely deleted and replaced with the new one.
Is there any way to keep the old view around so that it doesn't have to re-download all of its data when the user goes back to it? Also it would be nice so that their scroll position would be retained.
Any ideas?
Using UI-Router I solved this problem with the angular ui router extras. Here you will find the sticky states that will perhaps do what you want. Quote from the website:
Sticky States allows a tree of states to be long-lived, running
concurrently alongside one or more other state trees. This is also
sometimes referred to as Parallel States. The basis for this
functionality is to implement a "tabs" use case. Using UI-Router
Extras Sticky States, a single page angular app can implement
independent tab state trees, which operate in parallel to each other.
Does that help?

Angular-ui Router get two states active in parallel

I need to use two states in parallel, one for my page and an other for a modal with several sub states.
Right now calling the modal state will wipe out my page since the page state changed.
Create a child state child of my page wouldn't be a solution since the modal will be used on several pages.
Example:
$stateProvider
.state('user', {}) // page
.state('bookshelf', {}) // page
.state('books', {}) // modal
.state('books.read', {}) // sub state of modal
So if I'm on user and open my modal then the state would change to books, my modal would then have the content but the page content will be wiped out.
How do I fix it?
I believe the way you're looking to do this is not possible with UI.Router currently. What you're describing is a modal component (which would ideally be written as a directive), which tracks it's state independently from the main state.
The way to think about it, is that UI.Router works by creating a state tree. At any given time you can only be looking at one branch of the tree. You can go deeper down a branch (ie: book, book.open, book.open.checked), but you can't be in two places at once.
Another issue with the problem above is how do you serialize the state of the two different trees into one url? It's not to say it can't be done, it's just a hard problem to solve.
Checkout these issues:
https://github.com/angular-ui/ui-router/issues/119
https://github.com/angular-ui/ui-router/issues/384
https://github.com/angular-ui/ui-router/issues/475
Also checkout these repos, they might be further along the lines of solving the problem.
https://github.com/afterglowtech/angular-detour
https://github.com/stu-salsbury/angular-couch-potato
As far as solving your immediate problem, I think the 'easiest' way would be to ditch controlling the state of the modal inside your state config.
Instead, I would add some sort of root or abstract state, and then track whether the modal is open there. Then, you can communicate between controllers using events as shown here. Note: There are performance implications with listening to $rootScope, so be sure to research those. However (someone feel free to correct me), the implementation here doesn't have those problems, because the AppCtrl is never destroyed.
Jan 15, 2015 Edit
Turns out this is a pretty popular use case, and one of the core contributors to UI Router maintains a plugin/addition called UI Router Extras
It also includes utilities for lazy loading, called "Future States" which are very helpful.
That being said, one feature I'm hoping to get time to work on is maintaining all state within the URL (or perhaps, local storage) and allowing for reusable state "components". The latter is in the UI Router roadmap as well.

AngularJS: remembering state/setup of complex views with routes

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"

Using a State Machine to keep my UI Simple and Flexible? Good Idea? How do I do it in Knockout JS?

Iā€™m new to Knockout JS. Should I use sammy.js to help me with the below?
I am building a Knockout JS App (single page) where as I move from state to state, exactly what sub panels are visible and what they do changes. For example:
pre-login, I have one big panel that invites the user to login.
Right after login, I have a bunch of tabs, a main area for searching and an advertisement at the bottom.
If the user does a search, then I end up in a state where we see tabs, a search area and a search results area.
I imagine doing this via having a state machine that moves from state to state as the user clicks, sort of the way a parser would move from state to state.
I imagine delegating to the current state, an object hanging off of the ViewModel (perhaps) so that my 20 or so different states are almost like 20 very simple different UIs each one separate from the others and simple and clean and easy to understand.
1 - How would I do this, have the UI delegate a sub UI to a sub object hanging off the ViewModel?
2 ā€“ Is there a better way to keep my UI simple even though it has lots of states and different states often look very different from one another in terms of what elements (sub panels) are visible?
3 ā€“ Does anyone have an example were the code repeatedly delegates to a sub user interface?
Am I making sense?
A framework that would probably fit very well is machina.js - should be just what you are looking for.
Here is a presentation on it from jQuery UK - stateful machines
I'm using a scheme where I simply have two separate state observables - one for the total application state and one for the current "page" (tab, or whatever a "page means to you). In coffeescript, as an example:
#currentState('logged-in')
#currentPage('page-foo')
#applicationState = ko.computed => "#{#currentState()}:#{#currentPage()}"
then in your knockout visible bindings, you can match on a specific state or substate:
<div data-bind='visible: applicationState() == "logged-in:page-foo">
or you can do partial matchs:
<div data-bind='visible: applicationState().endsWith("page-foo")'>

Categories