How to use angular to handle page navigation in single-page application? - javascript

I have a single-page app that updates divs on the page by calling the server via ajax. I am using angular as the framework.
I am trying to handle page navigation through angular but I'm struggling a bit to understand it.
I've been looking at the $route functionality, and in the examples I've seen, you specify a template to be loaded. But I don't want to do that. What I would like to happen is this:
when the location url changes, eg from /#page1 to /#page2, a function in my controller gets called that can make the ajax call and update the appropriate div.
I would also like this to happen if the user manually changes the url in the browser address bar, and I would also like the app to load the correct page if a user comes straight to /#page1 or /#page2 eg from an outside link.
Is that the kind of thing I could use angular routes to do and is it the best tool for the job?
Many thanks for your help!

Related

How to store data when navigating between multiple pages in Angular?

I have the following problem in Angular. If I have two pages A and B each containing a table. Then I make changes to Page A in the table, and then navigate to Page B. Now I expect that when I navigate back to Page A, the changes are still there. I don't want to send the changes to the database until I click a save button. What is the best way to solve this in angular?
If you are only wanting to preserve the data for this one instance, then definitely look to using a Service and writing your data to localstorage for it to persist across page refreshes.
If you are developing a SPA, then I'm not sure why you need it to persist across a page refresh since moving between components does not actually send a new HTTP request. You state should be preserved in your Service.
If you find yourself needing to manage state across your entire application and want to do it reactively, I recommend checking out NGRX.
https://ngrx.io/
Another alternative that maybe has a little less boilerplate is NGXS, which does the same thing as NGRX.
https://www.ngxs.io/
I don't recommend to use localStorage for your task if you develop SPA application, because localStorage/sessionStorage is limited and it is designed for another purposes - like authentication etc. But of course if you need to preserve your data - like cookie/JWT token etc. even after refreshing the page you can use localStorage.
I recommend to use Angular services for this: please see examples at docs Services/DI docs. Once you registered service as a singleton Singleton services, you can inject it via built-in DI(Dependency Injection) in component which renders your table at page A. But of course, you are not limited in injection only in component which located at page A, you can inject it even in page B etc.

Mean Stack Application: Page does not rerender on refresh, but returns only JSON

I'm currently designing a MEAN.js web application, and for some reason, whenever I refresh the page on a route or window.reload, it does not rerender the page, but only returns the JSON file found at that current route.
For example, when I'm at localhost:8080/people:
If I click here from the main page, I get
But if I hit refresh or reload the page for whatever reason I get
Does anyone have any idea why this is happening and how to fix it?
Presumably you are using what Angular call's html5Mode routing.
This uses pushState and friends. These are browser features designed to allow you to build a web app which has what appear to be separate pages with unique, real URLs but when you change the page you actually modify the DOM of the current page (to State B) instead of loading a new one from scratch.
The design intention for pushState and friends is that if you request the unique, real URL that maps onto State B then the server will provide the browser with the HTML for State B directly.
This means that:
if you arrive on the site without going to the homepage first, then you
load the content you are trying to load directly (which is faster than loading the homepage and then modifying it with JavaScript).
if you arrive on the site without JavaScript working (which could be for many reasons, then everything still works. See also Progressive Enhancement and Unobtrusive JavaScript.
What you've done wrong is that your URLs are mapping onto your JSON based API instead of server side processes that generate the pages.
You need to write the server side processes. You could consider using the Accept header to allow them to share URLs with the API (so the server returns either JSON or HTML depending on what the client says it accepts).

Advantage and Implementation of Angular Universal?

Ancient website:
User navigates to url via bar or href, server call is made for that particular page
The page is returned (either static html or html rendered on server by ASP.NET
MVC, etc
EVERY page reloads everything, slow, reason to go to SPA
Angular 2 SPA:
User navigates to url via bar or router
A server call is made for the component's html/javascript
ONLY the stuff within the router outlet is loaded, not the navbar, etc (main advantage of SPAs)
HOWEVER, html is not actually received from server as is, Angular 2 code/markup is - then this markup is processed on the CLIENT before it can be displayed as plain HTML, which the browser can understand - SLOW? Enter Angular Universal?
Angular Universal:
First time users of your application will instantly see a server rendered view which greatly improves perceived performance and the overall user experience.
So, in short:
User navigates to url via search bar or router
Instead of returning Angular components, Angular Universal actually turns those components into html AND then sends them to the client. This is the ONLY advantage.
TLDR:
Is my understanding of what Angular Universal does correct? (last bullet point above).
And most importantly, assuming I understand what it does, how does it achieve this? My understanding is that IIS or whatever just returns requested resources, so how does Angular Universal pre-process them (edit: I would basically running something akin to an API that returns processed html)?
This HAS to mean that the server makes all the initial API calls needed to display the initial view, for example from route resolves...correct?
Edit: Let's focus on this approach to narrow down the question:
The second approach is to dynamically re-render your application on a web server for each request. There are still several caching options available with this approach to improve scalability and performance, but you would be running your application code within the context of Angular Universal for each request.
The approach here:
The first option is to pre-render your application which means that you would use one of the Universal build tools (i.e. gulp, grunt, broccoli, webpack, etc.) to generate static HTML for all your routes at build time. Then you could deploy that static HTML to a CDN.
is beyond me. Seeing how there is a bunch of dynamic content there, yet we preload static html.

Making views work with templates generated on the server with AngularJS & Laravel

I am looking to create an application with AngularJS that also has pages rendered on the server side with PHP/Laravel.
Essentially, I want to be able to render a static version of a view on the server side, but have the Javascript views start kicking in as soon as the page is rendered.
The idea being that when a user goes to an internal page for the first time, all of the content is rendered ahead of time on the server, yet the one page application will continue to work as soon as the page is loaded in the browser.
The backend of the application is currently written in Laravel, so I would feel comfortable writing the view logic in PHP.
What would be the best direction to go for this? I really want to avoid passing the pages to a third party service such as prerender.io or first rendering the page in phantomjs.
Essentially: having Javascript disabled on a web browser will not make any one page AngularJS app run. This is why I want to find a way to render the full page on the server, and once the page is loaded in the browser, either re-render the page (if that is the way it must be done) with my Angular application or somehow bind all of the data with the static views with my AngularJS controllers and models.

Backbone routers and compatibility with web server controller

How do I get compatibility between my web server's controllers and Backbone router?
I have it set it so when a user clicks on a link, a view is rendered, and the URL looks like this: /test/1, which is what I want. The problem comes in when the user tries to access test/1 by entering it into the address bar. My backend has controllers that is in charge of routing URLS.
How would I get it so it uses the Backbone routes rather than the backend routes?
One way that works is when I access the url #test/1. It is bookmarkable and can be entered into the address bar. The problem is that backbone stripes the # on load.
So, I see two solutions to my problem:
Get the backend controllers to interact with Backbone routes
Make it so the #'s aren't removed when they are entered inside of the address bar.
Which of the above solutions is recommended. And, how would I implement them. The second solution seems easier, but how would I make it so backbone doesn't strip the URLs of the hashes?
From what I understand when the user navigates to the root page and then test/1 via a link the logic is handled by backbone and a view is rendered. But when the user navigates directly to test/1 this is not handled correctly.
To handle this you need to setup a route on your server that points any URLs handled by backbone to the root page. The logic for this depends on your server which you have not specified. To do something like this in ASP you might setup a route like this:
RouteTable.Routes.MapWebPageRoute("test/{id}", "~/Default.cshtml", new {}, new { id = "\\d+" });
This would cause a URL such as test/1 to be handled by the default page which be the same handler as if the user navigated to /. Once the page has loaded on the client the Backbone router would fire for the test/1 route.
Well, really, there are many reasons why you want the URL to include the # all the time. It makes lots of things work better. For example, the correct controller is automatically selected by the web server and the correct route is automatically provided to Backbone whether you manually type in the URL, use a bookmark, use a link from another site, or use the back and forward buttons on the web browser. So choice 2 is definitely the one you want. This is also the standard behavior of Backbone.
So my question is "How did you get backbone to stop using the # in the first place?"
Edit: Thanks to Chris Herring for pointing us to a great article explaining why # is bad. With that, I will leave it as an exercise to the reader about which kind of pain they want to endure. I think # is still the way to go so long as all the Backbone route is changing is how the information on the page is displayed and not what information is on the page. If a web crawler that does not support JavaScript can scrape all the same information regardless of what comes after the #, then I still don't see a problem with it.

Categories

Resources