I am enhancing an ASP.NET MVC application with angularJS for selected pages. The primary means of navigating the site is still full page request, but some pages contain angular views and associated controllers for interactivity.
Currently, I achieve this by having something like this in the server side view:
<div ng-controller="ExampleCtrl" ng-include="exampleview.html"></div>
However, I would prefer to not inline controller and template definition like that and handle this through routing instead. However, angular routing only uses the client side of the URL (i.e. the parts after the first #). For various reasons, the page URL should remain http://domain.com/Example/Action instead of http://domain.com/Example/Action/#/example (this is just ugly) or http://domain.com/#/example (this will not work because I actually need the server side view as well).
Is there a way to make angular routing take the whole URL path into account instead of just the client part (and works in IE9)?
Related
I am working on an application which uses angularjs 1.6 for the frontend and codeigniter for the backend. Till now the home page in my application had the login form and the logic for that functionality was written in homeCtrl.js. Due to new design changes for the application, the login form is now part of the header. So I am clueless about how to implement the login functionality throughout the application as the header will be a part of all the pages. Can I use the existing code without breaking the functionality as I have a deadline to meet.
Yes, you can implement this logic. Use proper routing.
You can refer to this link.
Make use of UI-Router
This article makes use of ui-router library which you need to include.
In normal scenarios you will be having only simple states and one
state will be assoaciated with one view. But here you can configure
multiple views with your state.
UI Router with Multiple Views
In your case, for the home page header will contain the login form.
And for the other pages it will contain the actual header or whatever
you want. You can configure as many sub screens as you want.
You may get the UI-Router cdn path here
As far as I know the hash symbol(#) is the key when implementing routing in Angular. The web server only takes care about the part of the URL which is before the hash, and Angular takes care of the rest.
I´ve read some articles that explain how to remove the hash from URL. But if I remove the hash(#) from URL: Which routing works first?
OK, it is MVC. In that case we have to edit the MVC Route in order the server to understand the URL. But we are at the beginning again. Does it make any sense to use Angular Routing and MVC together ? Is not enough with MVC Routing?
Maybe I´m missing something. I hope you can help me.
Does it make any sense to use Angular Routing and MVC together ? Is
not enough with MVC Routing?
TL;DR;
I've rarely use both. The only time I use both is when I need to authenticate the user for some routes.
Long answer
1. Authentication
As you already figured out, Angular routing is great when you want to navigate to another page without the roundtrip to the server. It's usually a SPA. But there might be a scenario when you need to authenticate the user before sending the HTML, then MVC routing will be handy. I wrote an answer about it here. Note the difference between sending HTML and sending DATA to to the client. If you have no server routes the html-pages (or templates) will be fully accessible (unless you limit access in web.config or some other way). Some times the HTML-pages can contain some sensitive information as well...
The most common scenario is if you have a public site with an admin-part. But in my experience you can handle this on client side with client-side-routing only. It's usually the data that is sensitive, not the templates.
2. Server-side logging
The other scenario is when you want to do some logging on server side. For example if you want to log every page request. This can often be done on the client as well... Look at Google Analytics. But you might want to log the request even if the browser has javascript turned off.
3. SEO
There might be some SEO-issues when using client-side-routing. But this is only when we render the html with client side templates and if we compare to completely rendered views with MVC.Net. Do not confuse me posting the link with me actually agreeing with the content...
4. WCAG
In my country all government sites need to follow WCAG. One of the rules are - no javascript. Or at least that the site should be fully accessible without javascript. Without javascript client-side-routes are simply very difficult. ;)
These are some examples when you might need both server-side and client-side routes. But to sum up, in most cases client-side is enough.
My current setup is as follows:
Starting the server and going to localhost takes me to home.ejs as stated here (in my front end routing):
However, when I go to localhost:3000/posts, the posts template is infact not being injected into my index file (where my ui-view is). Ive been following the mean stack guide from thinkster, but have been making a few changes (not using inline templates)
My question is, how do I setup my routing such that localhost:3000/posts will actually take me to the posts page?
You are dealing with two types of routing, client side and server side. Client side is located in your app.config function in your angular code. That function should be calling html files, which are located in your public directory. These files are not rendered server side via express and they wouldn't not be able to read the ejs format.
Typically with MEAN stack applications, you just render your index file when the user logs in, and from there the Angular router takes over with html files and you handle your routing from there. If you don't want Angular routing, you have to set up your index.js file to render pages as they are called with res.render('posts')
You can change your posts.ejs file into an html file, and just call it via Angular when the user navigates to localhost/#/posts (depending on your version and configuration of Angular).
Your Express server side routing will handle your API calls as you have defined in index.js. In order to call those APIs, you will make GET or POST requests via Angular's $http method, through a service or factory.
Hope that helps, if not, let me know and I can elaborate or provide examples.
To solve this, I used Eric Hartmanns solution. By changing posts.ejs to posts.html, and letting the angular router take over on client side, the page was being rendered. However, when typing in localhost:3000/posts in the address bar, the page wasnt being rendered and the server was being hit for some reason. To get around that I simply made a new get route in express and re-rendered index whenever that route was hit like so:
router.get('/', function(req, res) {
res.render('index');
});
I'm building a UI using AngularJS that consumes a REST service:
Here is the Server API
/items/ GET
/items/:id GET
/items/ POST (to create new item)
/items/:id PUT (to edit item)
/items/:id DELETE
What are the best practices when setting up the routes in Angular? These routes would map to the server REST API, but obviously there is a problem. I'm guessing I would need the action as part of the URL, right? Something like this:
Angular Routes:
/items/
/items/:id
/items/new
/items/:id/edit
/items/:id/delete
However the above pattern also has a problem. /items/new will match both /items/:id and /items/new so what is the best practice when setting up a route for create?
Also keep in mind that the client side, Angular, routes you're defining could be dependent on your UI. The routes you've defined are more like a traditional web application where you click an "Add New" button that takes you to a new page that has a form that you fill out. However, this may not be the pattern you use for a Single Page App (SPA) as is often created with Angular.
By this I mean that most of the SPA apps I've done don't actually have a standalone "/items/new" route on the client side. Instead, the "/items/new" functionality is handled on the "/items/" route/partial ("page" in traditional web app terms). This page lists the existing items, and there is a form on this page that you can fill out to create a new item. Or, there is an "Add New" button on this page (just like a traditional web app); but, clicking it either slides in a modal form or ng-shows a form that is already defined (but initially hidden) on the /items/ partial template.
Upon submission, the controller hits against "POST /items/" on the server to create the new item, updates scope with the return value from the POST (assuming success, this would be the new item info), and clears/re-hides the "new" form.
Bottom line -- keep in mind that in a SPA you may not actually need a "/items/new" if the UI is such that the new is handled as a capability of the item list page. Of course, if you're needing it to be a standalone page as an addressable endpoint (i.e. you're planning to link to this from multiple places, not just from within the app), then you'll obviously need a direct route.
In our case, we typically don't need a named route for it in our apps and we just have it serviced as a capability of the "/items/" route.
Using UI-Router we can setup client side routing.
Make sure you disable html5 routes, because some browsers still doesn't support html5 and they hit the server api instead of hitting the client route
You can do this by setting $locationProvider.html5Mode(false); in app.config method while defining angular app
/items/ - this is for listing items
/items/{id:[0-9]{1,4}} - this is for displaying one item in detail
/items/add - for displaying new item form
/items/:id/edit - for displaying existing item in Form for editing
/items/:id/delete - **This is not required, I mean you just hit the API when
use clicks delete, we cant show any deletion form**
You can use regex for params '/items/{id:[0-9]{1,4}}' this means allow only numbers 0 to 9 and 1 to 4 characters long
I have a single page web app which has close to 10 different sections like
discussions
profile
video
etc , each of them have their states in the router as , it has its own controller and template and the urls are like
1. http://myapp/#/discussions
2. http://myapp/#/profile
3. http://myapp/#/video
when the angular app loads all the templates and js files are downloaded and at IIS only one request is made ie:
http://myapp/
but the things after '#' don't get passed to server. The UI router replaces templates at the client side but I want to track how many users visit the particular sections of my web app.
I cant do that from IIS logs as no resources are requested for individual sections in short i am expecting a log entry in IIS as below when a user visits discussion section
http://myapp/discussions
please let me know if I am correct in this approach or should i follow some other method.
A single page app, by definition, only makes an initial request to the server (IIS) to retrieve HTML and javascript. Subsequent interaction with your app is all handled by the javascript you loaded initially.
You won't be able to rely on your web server for tracking this. Instead, you should find something that can fire events from the javascript side, such as Google Analytics.