Complex routing with Backbone & Backbone.Marionette - javascript

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.

Related

Create multi page design with single URL

My goal is to create multi screens in one single page.Depending upon the action the user will be able to navigate from one screen to another screen.I have shared the images below
When the user clicks on any of the categories ,it will navigate to a second screen.
While clicking back it will again comeback to the first screen without change in URL.I have tried creating a full page modal and could not achieve this kind of functionality.I am not sure whether it should be done as a modal with multiple screens.
Please suggest me any method I can achieve this.
What you are likely referring to is creating an SPA or Single Page Application. This can be done through 'Vanilla' JavaScript at great effort or via one of many JavaScript Libraries or Frameworks.
Reactjs, Angular and Vuejs are probably the most common.
IF you were to use Reactjs then you could use what's called React Router. React Router would do what you want to do very easily. Doing it in Vanilla JavaScript would require a great deal of work or it would be very ugly.
However you did ask, so one way of doing would be to use JavaScript to load an iFrame or to make a top level parent element display: none and another to then display:...
Also if you are thinking of something less hacky, but not something as sophisticated as React or it's peers, then check this link out for a relevant article. Perhaps it's a path forward that you would prefer.
https://dev.to/rishavs/making-a-single-page-app-in-ye-good-olde-js-es6-3eng
To help rookies like me, you can make a single page app or SPA, or a dynamic page that updates based on user actions with a single URL, in vanilla Javascript. You don't have to use a framework.
There are 3 concepts you need to understand:
The server doesn't see past the # in the URL
You need to tell your code what screen you want to display. Normally you would have URL.com/page-you-are-on and click a link to go to URL.com/page-you-want
However, in a single page app, you don't go to different URLs. So how does it work? You use a fragment identifier or a pound symbol. #
The # in the URL doesn't get recognized by the server. So URL.com/page#page1 and URL.com/page#page2 to the server is the exact same URL.com/page.
So you can use the URL to indicate to the server what page you want, in your single page app.
A Router can decide what to show based on the # URL fragment
So your page loads at URL.com/page#page-you-want. You need to inspect the URL and get the piece past the #. You inspect the URL, and split it on the #. That means you get page-you-want. Your code then uses that to decide what content to display. The function or file that does this is commonly called a router because it routes to the file or function you want displayed.
Once you know what to show, dynamically update the DOM
This is where the magic happens. Your website looks at the URL, gets everything past the #, sends it to function that decides what to display. You now need to display it.
The DOM has lots of functions and methods that help it update and create various things. It could be as simple as this:
function displayPageAbout() {
// the router calls this if the URL is URL.com/page#about
let pageSection = document.getElementById('pageSection') //this is where the page will be displayed
//create the div and give it content
let page = document.createElement('div');
page.textContent = 'This is the About Page'
//add the div to the spot on the page where the content should go
pageSection.appendChild(page);
}
That is basically it.
If found these two examples and tutorials useful in understanding what it is, and how it could work.
https://blog.jeremylikness.com/blog/build-a-spa-site-with-vanillajs/
https://dev.to/rishavs/making-a-single-page-app-in-ye-good-olde-js-es6-3eng
Good luck!

how to get Previous Route in Angular 4 app

I have 2 routes defined as homepage and page1. I am going to page1 from homepage by this.router.navigation(with some queryparams).Now once i go to page1, i have some filters,which i can add to get particular data from api.Once i add those filter i change the page1 url by this.router.navigation(with some queryparams).After adding/deleting multiple filter , my url changes many times..Now i have a back button which upon click should navigate me to Homepage.
1.I have tried using history.back/location.back.But i have to click multiple times.(i see that navigationstart gets called multiple times)
2.i have tried a solution using rxjs pairwise
But i am not able to get the previous page(homepage).
3.This is just a situation.Basically i have to get the route of the preious page.I can't hard code the path in backFunc,Because this has to be generic for all of my other similar types of pages.I can come to page1 from any other page, and should be able to go back to the respective page.
Am i missing something very obvious , does Angular 4 provides any way to tackle this?
I'm slightly confused by the question but it should be as simple as just navigating to the homepage by using router.navigate. Failing that, try using https://angular.io/api/common/Location service's back function.
router.navigate has extra parameters like "replaceUrl".
If you set it to true (when you change query params), the browser will consider you don't change page. So an history.back will works.
Have a look at https://angular.io/api/router/NavigationExtras.
this.router.navigate(['/page1'], {replaceUrl: true, queryParams:{...}});

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
});
}

backbone routes, creating a faux route?

I not sure if I have used the technical term, or so I will describe what I am wanting to do with my backbone routes. In my application a user logs into a dashboard and they can see all the activity that is related to them, clicking on an activity link create modal for them to edit that activity.
On landing in the dashboard the URL is http://app.dev/#dashboard on clicking a link I want the modal to overlay the dashboard, but for the URL to change to http://app.dev/#activity/edit/:id without losing the activity view that should site behind model, currently the app navigations to edit route and re-renders everything, is there another way to preserve a view but change the URL?
You need to create a subview which will render the edit view (or just create an overlay popup).
Either way, you cannot do this using a <a href> tag, but you will need to do this via javascript.
Backbone.js has a way for you to easily navigate through routes using:
router.navigate(fragment, options) - see Backbone Navigate
Using {trigger:true} you can call the router function (which is basically what happens now) and that will re-render the view using the router function (as if the user landed on that page). By default, and if you pass {trigger:false}, Backbone will only change your url, but will not trigger the router function, so it will be transparent to the user, besides the fact that will see the url change, and he can see the change in his history (if you used Backbone.history.start())
Bottom line: To just change the url, without going through router, call router.navigate(requestedUrl, { trigger: false}) and don't forget to actually show him the new view (popup, overlay, nested view, etc...)

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

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/

Categories