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
});
}
Related
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!
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...)
I'm using the Polymer core-animated-pages to switch between my websites main pages.
I select which page needs to be shown by the id of that <section>. You can see a sample in action here. Now, the issue I'm having is that at loading of the page, the page that should be selected gets loaded from the url, eg www.example.com/home shows the home page, www.example.com/activities shows the activities page (code left out of example since not really relevant).
But what should I do when the id provided in the link doesn't exist? Is there an option to show a default core-animated-pages-page with a 404 message? Or do I have to check every link if it's in an array of all my pages, if so load the error page manually and else show the correct page?
Again, here's the example: jsbin.
Edit: To show the way my page handles linking, here's an update example: jsbin. Linking is essentially www.example.com/#home, etcetera
Something I'm missing from reviewing your example is how you're handling routing. In a typical site, if a user navigates to example.com/foo or example.com/#foo my expectation would be (using your current setup) that that would take you to the corresponding core-animated-pages page with the ID foo or a section which corresponds to that route.
Using routing (maybe the Polymer flatiron-director element), a basic solution might query the DOM in your element to see if a section of ID notsupportedURL can be found. If not, default to taking the user to your core-animated-pages 404 page, which doesn't have to be any more complex than what you have in place now.
There are a couple of things you could do here.
In the simplest case, you could just validate the value in the pageChanged handler. If the page doesn't exist, update it:
pageChanged: function(){
var foundPage = this.$.pages.querySelector('#' + this.page);
if (! foundPage) {
this.page = 'error'
}
...
See: http://jsbin.com/xequvone/14/edit
If you don't bind the core-menu directly to the core-animated-pages, you can add whatever logic you want. The following version does exactly the same thing as the previous one, but uses a separate variable for the selected page:
http://jsbin.com/xequvone/12/edit
I think you'd want a router if your URL scheme was more complex. For example, if the hash includes multiple levels and parameters, such as #people, #/people/search or #/people/edit/12343.
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.
I've a dashboard page which shows data relevant to a particular user which is shown in the drop-down at the right hand top corner.
When i select a different user the dashboard should be reloaded/refresh with data relevant to that user.
Router does not work since I navigate to the same page it does not reload the page.Another trick would be to create a dummy page & redirect from there back to dashboard,but i'm looking for a cleaner approach.
My Bad.
Durandal is leveraging KO heavily so i only needed to update the ViewModel & GUI would get autorefreshed. But the dropdown is not a durandal module.So was trying to figure out a way to notify the Durandal module with the change event.
I realized i was also using http://www.jstorage.info/ & it had a callback for pub/sub as well as listener :) , Issue resolved :)