Angular (web framework): Difference between revisions

From David's Wiki
 
(9 intermediate revisions by the same user not shown)
Line 1: Line 1:
Angular is a web framework by Google which allows you to create progressive web apps (PWAs).   
Angular is a web framework by Google which allows you to create progressive web apps (PWAs) which are single page applications (SPA).   
It can also be used to create native mobile or desktop apps.
It can also be used to create native mobile or desktop apps
Note that this is a front-end framework only. You will need to pair it with a back-end framework to get stateful functionality.


''This page is about Angular, also known as Angular 2. For AngularJS, the predecessor to Angular, see [https://angularjs.org/ https://angularjs.org/].''
''This page is about Angular, also known as Angular 2. For AngularJS, the predecessor to Angular, see [https://angularjs.org/ https://angularjs.org/].''
Line 9: Line 10:
* Install [[NodeJS]] and npm
* Install [[NodeJS]] and npm
* Install the Angular CLI: <code>npm install -g @angular/cli</code>
* Install the Angular CLI: <code>npm install -g @angular/cli</code>
===Creating a project===
<pre>
ng new <project-name>
</pre>
<pre>
ng serve --open
</pre>


==Usage==
==Usage==
Line 20: Line 30:


===Services===
===Services===
Services are singleton classes which can be accessed from any component.
<pre>
ng generate service <name>
</pre>
To access a service from a component, add a reference to the service as a parameter to the constructor of your component.
==Routing==
<pre>
ng generate module app-routing --flat --module=app
</pre>
{{hidden | Route Module Example |
<syntaxhighlight lang="typescript">
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { HeroesComponent } from './heroes/heroes.component';
const routes: Routes = [
  { path: 'heroes', component: HeroesComponent }
];
@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }
</syntaxhighlight>
}}


==Deployment==
==Deployment==
Line 44: Line 82:
</pre>
</pre>
}}
}}
===Express===
How to setup an Express server to host your Angular web application:
{{ hidden | Route |
First setup CSRF Protection:
<syntaxhighlight lang="typescript">
this.csrfProtection = csurf({cookie: true});
this.app.use(this.csrfProtection);
this.app.all(
  '*',
  (req: Request, res: Response, next: NextFunction): void => {
    res.cookie('XSRF-TOKEN', req.csrfToken());
    next();
  }
);
</syntaxhighlight>
Then setup your routes to serve your frontend:
<syntaxhighlight lang="typescript">
if (CONFIG.app.useProxy) {
  const myProxy = httpProxy.createProxyServer({ws: true});
  console.log(`Proxying to ${CONFIG.app.appProxy}`);
  router.all('/*', (req: Request, res: Response, next: NextFunction) => {
    myProxy.web(
      req,
      res,
      {target: req.protocol + '://' + CONFIG.app.appProxy}
    );
  });
} else {
  router.all('/*', express.static(CONFIG.app.appFolder));
  router.all('/*', (req: Request, res: Response, next: NextFunction) => {
    res.status(200).sendFile('index.html', {root: CONFIG.app.appFolder});
  });
}
</syntaxhighlight>
If you are proxying for development, you will also need to proxy websockets:
<syntaxhighlight lang="typescript>
server.on(
  'upgrade',
  (request: http.IncomingMessage, socket: net.Socket, head: Buffer) => {
    const pathname = url.parse(request.url).pathname;
    if (pathname === '/backend') {
      this.wss.handleUpgrade(request, socket, head, ws => {
        this.wss.emit('connection', ws);
      });
    } else if (CONFIG.app.useProxy) {
      console.log('proxying websocket');
      myProxy.ws(request, socket, head, {
        target: 'ws://' + CONFIG.app.appProxy,
      });
    } else {
      socket.destroy();
    }
  }
);
</syntaxhighlight>
}}
==Libraries==
Some interesting libraries for Angular
* [https://github.com/angular/components Angular Components]
** [[Angular Material]] ([https://material.angular.io/ website])
==Advanced Usage==
===CSRF/XSRF===
See [https://angular.io/guide/http#security-xsrf-protection http#security-xsrf-protection]
By default, the <code>HttpClientModule</code> will automatically reflect the <code>XSRF-TOKEN</code> cookie as <code>X-XSRF-TOKEN</code> if the following conditions are met:
* <code>XSRF-TOKEN</code> is a cookie under <code>/</code> with <code>HttpOnly</code> set to false.
* The outgoing request is not a <code>GET</code> or <code>HEAD</code> request.
* The outgoing request path is a relative path of form <code>api/endpoint</code> or <code>//example.com/api/endpoint</code>.
You can also set the name of the cookie and name of the header to something else if you prefer.
===Open in new tab===
If you're making an SPA, and therefore using client-side routing with <code>routerLink</code>, your buttons and links may not have open in a new link on right click. 
See [https://stackoverflow.com/questions/56627500/right-click-open-in-new-tab-is-not-available-on-routerlink-withhin-a-div-tag SO] for a way to add this.
===Advanced Routing===
* [https://medium.com/ngconf/routing-to-angular-material-dialogs-c3fb7231c177 Routing to Angular Material Dialogs]


==Resources==
==Resources==

Latest revision as of 23:49, 24 August 2020

Angular is a web framework by Google which allows you to create progressive web apps (PWAs) which are single page applications (SPA).
It can also be used to create native mobile or desktop apps.
Note that this is a front-end framework only. You will need to pair it with a back-end framework to get stateful functionality.

This page is about Angular, also known as Angular 2. For AngularJS, the predecessor to Angular, see https://angularjs.org/.

Getting Started

See Angular Guide Setup Local.

  • Install NodeJS and npm
  • Install the Angular CLI: npm install -g @angular/cli

Creating a project

ng new <project-name>
ng serve --open

Usage

Components

ng generate component <name>

Components are the building blocks of Angular.
Each component consists of a HTML block and an associated JS class.

Services

Services are singleton classes which can be accessed from any component.

ng generate service <name>

To access a service from a component, add a reference to the service as a parameter to the constructor of your component.

Routing

ng generate module app-routing --flat --module=app
Route Module Example
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { HeroesComponent } from './heroes/heroes.component';

const routes: Routes = [
  { path: 'heroes', component: HeroesComponent }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

Deployment

See Angular Guide Deployment

The basic idea is to do the following:

  1. Create a production build:
    ng build --prod
  2. Copy the dist folder to the server.
  3. Redirect missing files to index.html.

Apache

Place the following in the apache config for your site or in an .htaccess file:

Rewrite Rules
RewriteEngine On
# If an existing asset or directory is requested go to it as it is
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
RewriteRule ^ - [L]

# If the requested resource doesn't exist, use index.html
RewriteRule ^ /index.html

Express

How to setup an Express server to host your Angular web application:

Route

First setup CSRF Protection:

this.csrfProtection = csurf({cookie: true});
this.app.use(this.csrfProtection);
this.app.all(
  '*',
  (req: Request, res: Response, next: NextFunction): void => {
    res.cookie('XSRF-TOKEN', req.csrfToken());
    next();
  }
);

Then setup your routes to serve your frontend:

if (CONFIG.app.useProxy) {
  const myProxy = httpProxy.createProxyServer({ws: true});
  console.log(`Proxying to ${CONFIG.app.appProxy}`);
  router.all('/*', (req: Request, res: Response, next: NextFunction) => {
    myProxy.web(
      req,
      res,
      {target: req.protocol + '://' + CONFIG.app.appProxy}
    );
  });
} else {
  router.all('/*', express.static(CONFIG.app.appFolder));
  router.all('/*', (req: Request, res: Response, next: NextFunction) => {
    res.status(200).sendFile('index.html', {root: CONFIG.app.appFolder});
  });
}


If you are proxying for development, you will also need to proxy websockets:

server.on(
  'upgrade',
  (request: http.IncomingMessage, socket: net.Socket, head: Buffer) => {
    const pathname = url.parse(request.url).pathname;

    if (pathname === '/backend') {
      this.wss.handleUpgrade(request, socket, head, ws => {
        this.wss.emit('connection', ws);
      });
    } else if (CONFIG.app.useProxy) {
      console.log('proxying websocket');
      myProxy.ws(request, socket, head, {
        target: 'ws://' + CONFIG.app.appProxy,
      });
    } else {
      socket.destroy();
    }
  }
);

Libraries

Some interesting libraries for Angular

Advanced Usage

CSRF/XSRF

See http#security-xsrf-protection

By default, the HttpClientModule will automatically reflect the XSRF-TOKEN cookie as X-XSRF-TOKEN if the following conditions are met:

  • XSRF-TOKEN is a cookie under / with HttpOnly set to false.
  • The outgoing request is not a GET or HEAD request.
  • The outgoing request path is a relative path of form api/endpoint or //example.com/api/endpoint.

You can also set the name of the cookie and name of the header to something else if you prefer.

Open in new tab

If you're making an SPA, and therefore using client-side routing with routerLink, your buttons and links may not have open in a new link on right click.
See SO for a way to add this.

Advanced Routing

Resources