Create an Angular Application with Authentication in 20 Minutes
This article was originally published on OKTA Blog. Thank you for supporting the partners who make SitePoint possible.
Angular (formerly called Angular 2.0) is quickly becoming one of the most powerful ways to build a modern single-page app. A core strength is Angular’s focus on building reusable components, which help you decouple the various concerns in your application. Take authentication, for example: it can be painful to build, but once you wrap it in a component, the authentication logic can be reused throughout your application.
The Angular CLI makes it easy to scaffold new components, and even entire projects. If you haven’t used the Angular CLI to quickly generate Angular code, you’re in for a treat!
In this example, you’ll build a simple web application with Angular CLI, a tool for Angular development. You’ll create an application with search and edit features, then add authentication.
Create an Angular Application
TIP: If you’d like to skip building the Angular application and get right to adding authentication, you can clone my ng-demo
project, then skip to the Create an OpenID Connect App in Okta section.
git clone https://github.com/mraible/ng-demo.git
What You’ll Need
- About 20 minutes
- A favorite text editor or IDE. I recommend IntelliJ IDEA
- Node.js and npm installed. I recommend using nvm
- Angular CLI installed. If you don’t have Angular CLI installed, install it using
npm install -g @angular/cli
Create a new project using the ng new
command:
ng new ng-demo
This will create a ng-demo
project and run npm install
in it. It should take about a minute to complete, but that could vary depending on your connection speed.
[mraible:~/dev] $ ng new ng-demo
installing ng
create .editorconfig
create README.md
create src/app/app.component.css
create src/app/app.component.html
create src/app/app.component.spec.ts
create src/app/app.component.ts
create src/app/app.module.ts
create src/assets/.gitkeep
create src/environments/environment.prod.ts
create src/environments/environment.ts
create src/favicon.ico
create src/index.html
create src/main.ts
create src/polyfills.ts
create src/styles.css
create src/test.ts
create src/tsconfig.app.json
create src/tsconfig.spec.json
create src/typings.d.ts
create .angular-cli.json
create e2e/app.e2e-spec.ts
create e2e/app.po.ts
create e2e/tsconfig.e2e.json
create .gitignore
create karma.conf.js
create package.json
create protractor.conf.js
create tsconfig.json
create tslint.json
Successfully initialized git.
Installing packages for tooling via npm.
Installed packages for tooling via npm.
You can `ng set --global packageManager=yarn`.
Project 'ng-demo' successfully created.
[mraible:~] 46s $
You can see the what version of Angular CLI you’re using with ng --version
.
$ ng --version
/ _ __ __ _ _ _| | __ _ _ __ / ___| | |_ _|
/ △ | '_ / _` | | | | |/ _` | '__| | | | | | |
/ ___ | | | | (_| | |_| | | (_| | | | |___| |___ | |
/_/ __| |_|__, |__,_|_|__,_|_| ____|_____|___|
|___/
@angular/cli: 1.3.2
node: 8.4.0
os: darwin x64
Run Your Angular Application
The project is configured with webpack dev server. To start it, make sure you’re in the ng-demo
directory, then run:
ng serve
You should see a screen like the one below at http://localhost:4200.
You can make sure your new project’s tests pass, run ng test
:
$ ng test
...
Chrome 60.0.3112 (Mac OS X 10.12.6): Executed 3 of 3 SUCCESS (0.239 secs / 0.213 secs)
Add a Search Feature
To add a search feature, open the project in an IDE or your favorite text editor. For IntelliJ IDEA, use File > New Project > Static Web and point to the ng-demo
directory.
In a terminal window, cd into your project’s directory and run the following command. This will create a search component.
$ ng g component search
installing component
create src/app/search/search.component.css
create src/app/search/search.component.html
create src/app/search/search.component.spec.ts
create src/app/search/search.component.ts
update src/app/app.module.ts
Open src/app/search/search.component.html
and replace its default HTML with the following:
<h2>Search</h2>
<form>
<input type="search" name="query"[(ngModel)]="query"(keyup.enter)="search()">
<button type="button"(click)="search()"Search</button>
</form>
<pre>{{searchResults | json}}</pre>
The Router documentation for Angular provides the information you need to setup a route to the SearchComponent
you just generated. Here’s a quick summary:
In src/app/app.module.ts
, add an appRoutes
constant and import it in @NgModule
:
import{ Routes, RouterModule } from @angular/router';
const appRoutes: Routes = [
{path: 'search', component: SearchComponent},
{path: '', redirectTo: '/search', pathMatch: 'full'}
];
@NgModule({
...
imports: [
...
RouterModule.forRoot(appRoutes)
]
...
})
exportclass AppModule { }
In src/app/app.component.html
, adjust the placeholder content and add a <router-outlet>
tag to display routes.
<h1>>Welcome to !</h1>
<!-- Routed views go here -->
<router-outlet></router-outlet>
Now that you have routing setup, you can continue writing the search feature.
If you still have ng serve
running, your browser should refresh automatically. If not, navigate to http://localhost:4200. You will likely see a blank screen. Open your JavaScript console and you’ll see the problem.
To solve this, open src/app/app.module.ts
and add FormsModule
as an import in @NgModule
:
import { FormsModule } from '@angular/forms';
@NgModule({
...
imports: [
...
FormsModule
]
...
})
export class AppModule { }
Now you should see the search form.
If you want to add CSS for this components, open src/app/search/search.component.css
and add some CSS. For example:
host {
display: block;
padding: 0 20px;
}
This section has shown you how to generate a new component to a basic Angular application with Angular CLI. The next section will show you how to create a use a JSON file and localStorage
to create a fake API.
To get search results, create a SearchService
that makes HTTP requests to a JSON file. Start by generating a new service.
$ ng g service search
installing service
create src/app/search.service.spec.ts
create src/app/search.service.ts
WARNING Service is generated but not provided, it must be provided to be used
Move the generated search.service.ts
and its test to app/shared/search
. You’ll need to create this directory.
mkdir -p src/app/shared/search
mv src/app/search.service.* src/app/shared/search/.
Create src/assets/data/people.json
to hold your data.
[
{
"id": 1,
"name": "Peyton Manning",
phone": "(303) 567-8910",
"address": {
"street": "1234 Main Street",
"city": "Greenwood Village",
"state": "CO",
"zip": "80111"
}
},
{
id": 2,
"name": "Demaryius Thomas",
"phone": "(720) 213-9876",
"address": {
"street": "5555 Marion Street",
"city": "Denver",
"state": "CO",
"zip": "80202"
}
},
{
"id": 3,
"name": "Von Miller",
"phone": "(917) 323-2333",
"address": {
"street": "14 Mountain Way",
"city": "Vail",
"state": "CO",
"zip": "81657"
}
}
]
Modify src/app/shared/search/search.service.ts
and provide Http
as a dependency in its constructor. In this same file, create a getAll()
method to gather all the people. Also, define the Address
and Person
classes that JSON will be marshalled to.
import { Injectable } from '@angular/core';
import { Http, Response } >from '@angular/http';
import 'rxjs/add/operator/map';
@Injectable()
export class SearchService {
constructor(private http: Http) {}
getAll() {
return this.http.get('assets/data/people.json')
.map((res: Response) => res.json());
}
}
export class Address {
street: string;
city: string;
state: string;
zip: string;
constructor(obj?: any) {
this.street = obj && obj.street|| null;
this.city = obj && obj.city || null;
this.state = obj && obj.state || null;
this.zip = obj && obj.zip || null;
}
}
export class Person {
id: number;
name: string;
phone: string;
address: Address;
constructor(obj?: any) {
this.id = obj && Number(obj.id) || null;
this.name = obj && obj.name || null;
this.phone = obj && obj.phone || null;
this.address = obj && obj.address || null;
}
}
To make these classes available for consumption by your components, edit src/app/shared/index.ts
and add the following:
export * from './search/search.service';
The reason for creating this file is so you can import multiple classes on a single line rather than having to import each individual class on separate lines.
In src/app/search/search.component.ts
, add imports for these classes.
import { Person, SearchService } from '../shared';
You can now add query
and searchResults
variables. While you’re there, modify the constructor to inject the SearchService
.
export class SearchComponent implements OnInit {
query: string;
searchResults: Array<Person>;
constructor(private searchService: SearchService) {}
Then implement a search()
method to call the service’s getAll()
method.
search(): void {
this.searchService.getAll().subscribe(
data => { this.searchResults = data; },
error => console.log(error)
);
}
Continue reading %Create an Angular Application with Authentication in 20 Minutes%
LEAVE A REPLY
You must be logged in to post a comment.