Auto-update deep-linked url when model changes in Angular - javascript

So. I've been messing around in AngularJS (which continues to amaze me every minute I work with it) and I was wondering, when using $routeProvider and $routeParams, is there any way to force the current url/location/deep-link in the location bar in the browser to automatically update when certain models change on the page?
Here is the app that I'm messing around with.
Its the app from the tutorial on angular's site except I've screwed around with it and added in some features like pagination. If you notice, upon visiting this link you're redirected to #/phones//age/5/0. The first segment is the controller, while the last 4 describe filters, respectively, a text query, the "column" to sort by, number of items per page, and page number.
The controller for this takes these in through $routeParams and updates the models/views like normal but how can I force the url to change automatically when the user changes the models/views? So if you were to type xoom in the query box on the page when you first visit, the url in the location bar would change to http://brandonep.org/angular-test-phonecat/#/phones/xoom/age/5/0 as soon as you type it.
Thanks in advance! And sorry if I'm unclear but I tried my best :P

I would use parameters on your url (/?a=1&b=2), and then inject $routeParams into your controller to interpret the parameters on controller load.
Then you can use $watch to watch your model, and each time it changes set window.location.url. Here's an example: http://jsfiddle.net/andytjoslin/eYJmR/

Related

Ionic-1 Navigation

I am working on an Ionic-1 App. I am terrible confused in managing the back history of my app. Consider this scenario:
Start from home page then
Does a 3 step user registration process
After the end of user registration redirect to records page
Now clicking back button (hard or soft back) I want to navigate back to home instead of cycling through user registration process. There are other scenarios like this where back behavior needs to be modified. Are there any references around to implement back behavior systematically? Should I manually define view hierarchy tree structure and somehow figure out where in tree current view is and then go to parent?
As per my suggestion you should pass parameter say 'extraparams' in your url and set it value to 'home'.And on record page controller then make a function on back button say 'goBack()' where you can check if value of 'extraparams' is 'home' and then use $state.go() to navigate to home view.
If you can keep and maintain each and every section using state approach then you can redirect to home page or what ever the page you prefer to redirect to.In that way you have to implement back button like this way, $state.go('homeSate');
or if you can keep 3 steps(registration) as sub states and have try by injecting $rootScope to your controller in which allows you to access your parent(home).

JS main app which uses routing to show dialogs and such?

I'm wondering if I can have a JavaScript-based application which has a main "template" as a background/main app of some sorts mixed with some URL routing to show dialogs and such? say, here's a short example:
Main app displays google map and whatnot. URL: /#
User clicks some menu item and it displays an options dialog. URL: /#options
User goes to a sub-options menu. URL: /#options/advanced
User closes the main option dialog, back to main app. URL: /#
User puts some coordinates in URL and the map locates it. URL:/#coords/100/100
The main idea here is to keep the map visible (and other stuff that I want to show in that template, too) in the background while using the URL to either display dialogs, forms or even to control the google map itself - BUT that if the user goes to, for example, /#options on first load, the app should load everything and then show the options dialog, okay?
Basically, I'd like to have a "main state" page which contains the most important part of my app, but I'd like to use url-routing for displaying dialogs and executing actions, that users can bookmark in the future and share and so on. I dunno how is this idea/concept called, so that's why I'm asking.
Also, what can I use to archieve something like this? I know this is kind of an open question, but I'm aiming for a JavaScript-based app/framework (TypeScript works too). I don't know if Angular2 + ui-router can do this, or even how should I google this?...
If Angular2+ui-router can do it, then great! but how?. If there are any other frameworks or combinations please provide an example! I've read about vue.js, react.js and so on, but vue.js seemed too simple and react.js still makes me feel uneasy mixing HTML inside the JS files, it just feels unnatural. Thanks in advance for any pointers you can provide! :)
Angular 2 can accomplish this. One way would be to have just one component. This component shows your map.
Your logic can watch for changes to the URI parameters and show/hide options accordingly. Since these parameters are not always present, you would use optional parameters.
While your app is running, you can add event listeners to buttons and links that should change the view state. When the user clicks a Select City button, the event listener could direct him to a URI with the appropriate parameter: ;view=dialog;target=city (Angular 2 uses matrix uri notation by default)
The component would be listening for changes in the parameters and react accordingly.
ngOnInit() {
this.route.params.forEach((params: Params) => {
// this is executed every time new URI parameters arrive
this.viewType = params['view'];
this.target = params['target'];
//todo: update the model to match new parameters
});
}

How to restore previous state of angular controllers

I need to keep controllers' state in angular ,for improving some user experiences, during user is visiting different pages.
For instance I have a list, which is created via a directive, and it has a pagination section, so imagine when a user go to page 20 and choose an item, they'll be redirected to the detail page, but when they click back button and return to the previous page they see the first page of the list which is not convenient and they expect to be on page 20 again.
I've come up with several options:
Using a dialog to display second page (item detail), so they can close that modal and return to the previous form without any change.
Redirecting users to the second page with a parameter in URL and then return them with that parameter to understand what page number they have been before.
Keeping some crucial variable globally to store controller state and using them when user comes back.
But I think there should be better ideas like keeping controllers' state during redirection.
Any idea would be appreciated.
Redirecting users to the second page with a parameter in URL and then return them with that parameter to understand what page number they have been before.
I prefer this because you get the added benefit of staying on page 20 when you do a page refresh. Options 1 and 3 do not give you this added benefit. Path params are also bookmark friendly.
Another alternative for you to look into that is almost as good is localstorage
or cookies. I dont think these options are better than your 2 though.

Keep all states when going back

I have multiple pages in my Angular app that the user can change quite a bit, i.e. open tabs and pills, modals, etc. Let's say, for example, they open a modal and then click a link in that modal which leads them to another page. On that other page, when they go back in their browser history, I'd want them to see the first page the way they left it, i.e. with the modal open, not how it looks when you reload it.
I am using ui-router with Angular 1.4.3.
So far I have looked into the following links:
https://github.com/angular-ui/ui-router/issues/63
https://github.com/angular-ui/ui-router/issues/562
...but they don't seem to be quite what I need. And I'm not even sure how to google this.
Another example for this is when a user enters something in a search bar, then clicks on a result which leads to a new page. When they go back, they would have to enter the search again, which is not the greatest experience.
Use a service to store page state
Rather than storing page state and user input on the $scope, store it on a persistent service that is injected into the page controller along with the $scope.
Store a reference to the service on the $scope:
myApp.service('MyPageStateService', function() {
this.someProperty = 'some initial state';
});
myApp.controller('MyPageController', function($scope, MyPageStateService) {
$scope.state = MyPageStateService;
});
and from the page template access data stored on the persistent state service:
<div ng-controller="MyPageController">
<p>My page state is {{state.someProperty}}</p>
</div>
When navigating back to this page within the app, the controller will get a new $scope but the same instance of MyPageStateService.
You may take a look at sticky states. They are not limited to forward/back navigation, this gives some consistency to them.
If this behaviour is not desirable anywhere but forward/back, I guess it can be done by doing $stickyState.reset('...') on $stateChangeStart for everything except the adjacent state.

Complex routing with Backbone & Backbone.Marionette

I'm working on a google maps app for some time now. The app is using Backbone & Backbone.Marionette. A screenshot of what it looks like can be found here:
https://www.facebook.com/photo.php?fbid=566101353505241&set=a.516037321844978.1073741832.145077908940923&type=3&theater
For the last couple of hours I've trying to find advanced examples of using Backbone Router to keep the app state, but I couldn't find anything more advanced than examples with single route parameters: #about #notes etc...
Here is what I'm trying to do.
When the user moves around on the map, I change the url to reflect this:
/:lat/:lng/:zoom
When the user selects any marker from the list on the right, then I change the url to:
/:lat/:lng/:zoom/hotspot/:id
The list on the right is using Backbone.Paginator. So when the user clicks on any page the url will change to:
/:lat/:lng/:zoom/page/:id
now if the user clicks on a hotspot I want to change the url to:
/:lat/:lng/:zoom/page/:id/hotspot/:id
If for example the user used the directions functionality in the app I want the url to reflect this:
/:lat/:lng/:zoom/direction/:start/:end
If he uses the list with hotspots before or after he used the directions app I want to change the url to:
/:lat/:lng/:zoom/direction/:start/:end/page/:id/hotspot/:id
You get the idea. I want to make it possible for the user to use any part of the app and share the link with anyone after that.
As I said I'm using Backbone.Marionette - so my application has a lot of sub apps responsible for the map view, list view, directions view etc.
My problems are as follow:
How to use backbone.navigate properly? When the user moves around on the map - I can easily change the /:lat/:lng/:zoom . But now if the user clicks on any hotspot and I just pass backbone.navigate('hotspot/200') -> the url will change to just #hotspot/200 and the part with the lat/lng/zoom will be lost. Same goes for any other url I listed above. If I just pass the part that needs to be added to the url, backbone will clear the whole hash and add my new part. How do you deal with that? Do you have a global function that keeps track of all possible url combinations and just adds or replace depending on the current situation?
If we take this url for example:
/:lat/:lng/:zoom/direction/:start/:end/page/:id/hotspot/:id
/:lat/:lng/:zoom - this part is needed by the map app
direction/:start/:end - this part is needed by the directions app
page/:id - this part is needed by the hotspots app
hotspot/:id - this part is needed by the hotspot app
How do you manage such urls? I would basically need to call the above apps one after the other in order to recreate the app state.
Is there any way to do all this without going mad? Any examples of advanced Backbone Router (or even just HTML5-history) usage or tips are welcome!
I'd create a navigate(newState) type function which checks the current state of the app (ie. the URL). Using the current URL you can generate the next URL as per all of your conditions by simply adding the new state to the current state or by replacing parts of the current state where appropriate. Once that's done, call Backbone.navigate with your new URL.

Categories