0 to M.E.A.N

in 30 minutes

by Travis Tidwell | https://form.io
@softwaregnome | travist

Follow along @

http://travistidwell.com/presentations/0toMEAN

http://travistidwell.com/zerotomean

https://github.com/travist/zerotomean

We are going to build

A complete Event Registration System

yes... in 30 minutes

The structure of M.E.A.N Apps

Pre-requisites

Start MongoDB Server


						mongod
					

API First

Open Source Form.io API Platform
https://github.com/formio/formio

pssst... you can also use https://form.io for free

Setup Form.io


						git clone https://github.com/formio/formio --depth=1
						cd formio
						npm install
						node main
					

@ http://localhost:3001

The API Platform

@ http://localhost:3001/user

Build out the API by creating an Event Resource

Building the Application

Fountain.js - A Yeoman Generator

http://fountainjs.io

Installing Fountain


						npm install -g yo generator-fountain-webapp
						mkdir meanapp && cd meanapp
						yo fountain-webapp
					

Running our app


						npm run serve
					

Upgrade to Angular 4!

Make sure you upgrade dependencies as follows.


"dependencies": {
	"@angular/common": "^4.1.1",
	"@angular/compiler": "^4.1.1",
	"@angular/core": "^4.1.1",
	"@angular/http": "^4.1.1",
	"@angular/platform-browser": "^4.1.1",
	"@angular/platform-browser-dynamic": "^4.1.1",
	"@angular/router": "^4.1.1",
	"bootstrap-sass": "^3.3.7",
	"bootswatch": "^3.3.7",
	"core-js": "^2.4.1",
	"lodash": "^4.17.4",
	"ng2-formio": "^1.0.0-rc.10",
	"rxjs": "5.3.1",
	"zone.js": "^0.8.10"
}
					

Installing Modules


						npm install --save ng2-formio
						npm install --save bootstrap-sass
						npm install --save bootswatch
						npm install --save lodash
						npm install --save-dev file-loader
						npm install --save-dev angular2-load-children-loader
						npm install --save-dev es6-promise-loader
					

Adding additional Webpack Loaders

config/webpack.conf.js
config/webpack-dist.conf.js
config/webpack-test.conf.js{ test: /\.ts$/, exclude: /node_modules/, loaders: ['ts-loader', 'angular2-load-children-loader'] }, { test: /\.(woff2?|ttf|eot|svg)(\?v=\d+\.\d+\.\d+)?$/, loader: "file-loader?name=fonts/[name].[ext]" }

Setting up Bootstrap

src/app/index.scss
						$icon-font-path: "../node_modules/bootstrap-sass/assets/fonts/bootstrap/";
						@import "../node_modules/bootswatch/yeti/_variables.scss";
						@import "../node_modules/bootstrap-sass/assets/stylesheets/_bootstrap.scss";
						@import "../node_modules/bootswatch/yeti/_bootswatch.scss";

						.footer {
						  text-align: center;
						  padding: 3em;
						  color: #777;
						  border-top: .05rem solid #e5e5e5;
						  margin-top: 20px;
						}
					

Changing the Navbar

src/app/header.html

					

Changing Main Content

src/app/main.html

Adding a Home Page

src/app/home.html
					

Welcome to the Event Manager!

src/app/home.ts
						import { Component } from '@angular/core';
						@Component({
						   template: require('./home.html')
						})
						export class HomeComponent {}
					

Changing the route structure

src/index.html
						Loading...
					
src/app/index.ts
					  import { HomeComponent } from './home';
					  ...
					  declarations: [
					     HomeComponent,
					     ...
					  ],
					  bootstrap: [MainComponent]
					
src/app/routes.ts
						import {HomeComponent} from './home';
						export const routes: Routes = [{
						   path: '',
						   component: HomeComponent
						}];
					

User Authentication

Create a Configuration File

src/app/config.ts
import { FormioAppConfig } from 'ng2-formio';
import { FormioAuthConfig } from 'ng2-formio/auth';

export const AppConfig: FormioAppConfig = {
  appUrl: 'http://localhost:3001',
  apiUrl: 'http://localhost:3001'
};

export const AuthConfig: FormioAuthConfig = {
  login: {
    form: 'user/login'
  },
  register: {
    form: 'user/register'
  }
};
					

Provide the FormioAuthService

src/app/index.ts
import { FormioAppConfig } from 'ng2-formio';
import { FormioAuthService, FormioAuthConfig } from 'ng2-formio/auth';
import { AuthConfig, AppConfig } from './config';
...
@NgModule({
   ...
   providers: [
      FormioAuthService,
      {provide: FormioAuthConfig, useValue: AuthConfig},
      {provide: FormioAppConfig, useValue: AppConfig}
   ]
})
					

Create the Authentication Module

src/app/auth.module.ts
import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { FormioAuth, FormioAuthRoutes } from 'ng2-formio/auth';
@NgModule({
  imports: [
    FormioAuth,
    RouterModule.forChild(FormioAuthRoutes())
  ]
})
export class AuthModule {}
					
src/app/routes.ts
{
  path: 'auth',
  loadChildren: 'es6-promise-loader?,[name]!./auth.module#AuthModule'
}
					

Adding Navigation Bar

src/app/header.html

					
src/app/header.ts
import { FormioAuthService } from 'ng2-formio/auth';

...
export class HeaderComponent {
  constructor(private auth: FormioAuthService) {}
}
					

Redirect to Home after login

src/app/main.ts
import { Router } from '@angular/router';
import { FormioAuthService } from 'ng2-formio/auth';

...
export class MainComponent {
  constructor(private auth: FormioAuthService, private router: Router) {
    this.auth.onLogin.subscribe(() => {
      this.router.navigate(['/']);
    });

    this.auth.onLogout.subscribe(() => {
      this.router.navigate(['/']);
    });

    this.auth.onRegister.subscribe(() => {
      this.router.navigate(['/']);
    });
  }
}

					

Event Resource

Create a Resource Module

src/app/event.module.ts
import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { FormioResource, FormioResourceRoutes, FormioResourceConfig, FormioResourceService } from 'ng2-formio/resource';

@NgModule({
  imports: [
    FormioResource,
    RouterModule.forChild(FormioResourceRoutes())
  ],
  providers: [
    FormioResourceService,
    {provide: FormioResourceConfig, useValue: {
      name: 'event',
      form: 'event'
    }}
  ]
})
export class EventResource {}
					

Mount the Resource to the routes

src/app/routes.ts
export const routes: Routes = [
  ...
  {
    path: 'event',
    loadChildren: 'es6-promise-loader?,[name]!./event.module#EventResource'
  }
];
					

We now have all of the available Routes!

  • event - Index of events
  • event/new - Create a new event
  • event/:id/view - View an event
  • event/:id/edit - Edit an event
  • event/:id/delete - Delete an event

Override the Event View Component

src/app/event.module.ts
import { NgModule, Component } from '@angular/core';
...
import { ..., FormioResourceViewComponent } from 'ng2-formio/resource';
@Component({
  template: require('./event.html')
})
export class EventViewComponent extends FormioResourceViewComponent {
  constructor(service: FormioResourceService) {
    super(service);
  }
}

@NgModule({
  imports: [
    FormioResource,
    RouterModule.forChild(FormioResourceRoutes({
      view: EventViewComponent
    }))
  ],
  declarations: [
    EventViewComponent
  ],
  ...
})
export class EventResource {}
					

Create the Event View Template

src/app/event.html

{{ service.resource?.data.title }}

{{ service.resource?.data.description }}

  • Start: {{ service.resource?.data.start }}
  • End: {{ service.resource?.data.end }}

Add a link to the header



					

We have an Event Management System!

Building your application

npm run build

This creates a new build in the dist folder.

Commit to Github Pages

git push origin master:gh-pages

Thank you!