SlideShare a Scribd company logo
Use Angular Schematics to Simplify Your Life
August 15, 2019
Matt Raible | @mraible
Photo by Trish McGinity mcginityphoto.com
Blogger on raibledesigns.com and

developer.okta.com/blog
Web Developer and Java Champion
Father, Husband, Skier, Mountain
Biker, Whitewater Rafter
Open Source Connoisseur
Hi, I’m Matt Raible!
Bus Lover
Okta Developer Advocate
Use Angular Schematics to Simplify Your Life - Develop Denver 2019
Use Angular Schematics to Simplify Your Life - Develop Denver 2019
developer.okta.com
Agenda
1. What are Angular Schematics?
2. Create and Test a Schematic
3. Schematic Templates
4. Template Expression Language
5. OpenID Connect Authentication
6. Schematics for React, Vue, and Ionic
What are Angular Schematics?
Create a Schematic
$ npm i -g @angular-devkit/schematics-cli
$ schematics blank —-name=my-component
CREATE /my-component/README.md (639 bytes)
CREATE /my-component/.gitignore (191 bytes)
CREATE /my-component/.npmignore (64 bytes)
CREATE /my-component/package.json (539 bytes)
CREATE /my-component/tsconfig.json (656 bytes)
CREATE /my-component/src/collection.json (231 bytes)
CREATE /my-component/src/my-component/index.ts (318 bytes)
CREATE /my-component/src/my-component/index_spec.ts (474 bytes)
Project metadata: collection.json
{
"$schema": "../node_modules/@angular-devkit/schematics/collection-schema.json",
"schematics": {
"my-component": {
"description": "A blank schematic.",
"factory": "./my-component/index#myComponent"
}
}
Factory function: index.ts
import { Rule, SchematicContext, Tree } from '@angular-devkit/schematics';
export function myComponent(_options: any): Rule {
return (tree: Tree, _context: SchematicContext) => {
return tree;
};
}
Unit test: index_spec.ts
import { Tree } from '@angular-devkit/schematics';
import { SchematicTestRunner } from '@angular-devkit/schematics/testing';
import * as path from 'path';
const collectionPath = path.join(__dirname, '../collection.json');
describe('my-component', () => {
it('works', () => {
const runner = new SchematicTestRunner('schematics', collectionPath);
const tree = runner.runSchematic('my-component', {}, Tree.empty());
expect(tree.files).toEqual([]);
});
});
Schematic Templates
Copy and Manipulate Templates: directory structure
$ tree .
src/my-component/
├── files
│ └── src
│ └── app
│ ├── app.component.html
│ └── app.component.ts
├── index.ts
└── index_spec.ts
Copy and Manipulate Templates: app.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
name = '<%= name %>';
}
src/my-component/files/src/app/app.component.ts
Copy and Manipulate Templates: app.component.html
src/my-component/files/src/app/app.component.html
<div style="text-align:center">
<h1>
Hello, {{ name }}
</h1>
</div>
<router-outlet></router-outlet>
Copy and Manipulate Templates: schema.json
{
"$schema": "http://json-schema.org/schema",
"id": "SchematicsMyComponent",
"title": "My Component Schema",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Your Name",
"x-prompt": "What is your name?"
}
},
"required": ["name"]
}
Copy and Manipulate Templates: collection.json
{
"$schema": "../node_modules/@angular-devkit/schematics/collection-schema.json",
"schematics": {
"my-component": {
"description": "A blank schematic.",
"factory": "./my-component/index#myComponent",
"schema": "./my-component/schema.json"
}
}
}
Copy and Manipulate Templates: index.ts
export function myComponent(_options: any): Rule {
return (tree: Tree, _context: SchematicContext) => {
setupOptions(tree, _options);
const movePath = normalize(_options.path + '/');
const templateSource = apply(url('./files/src'), [
template({..._options}),
move(movePath),
// fix for https://github.com/angular/angular-cli/issues/11337
forEach((fileEntry: FileEntry) => {
if (tree.exists(fileEntry.path)) {
tree.overwrite(fileEntry.path, fileEntry.content);
}
return fileEntry;
}),
]);
const rule = mergeWith(templateSource, MergeStrategy.Overwrite);
return rule(tree, _context);
};
}
Copy and Manipulate Templates: setupOptions()
export function setupOptions(host: Tree, options: any): Tree {
const workspace = getWorkspace(host);
if (!options.project) {
options.project = Object.keys(workspace.projects)[0];
}
const project = workspace.projects[options.project];
options.path = join(normalize(project.root), 'src');
return host;
}
Copy and Manipulate Templates: index_spec.ts
beforeEach(() => {
appTree = schematicRunner.runExternalSchematic(
'@schematics/angular', 'workspace', workspaceOptions);
appTree = schematicRunner.runExternalSchematic(
'@schematics/angular', 'application', appOptions, appTree);
});
it('works', () => {
const runner = new SchematicTestRunner('schematics', collectionPath);
runner.runSchematicAsync(
'my-component', schemaOptions, appTree).toPromise().then(tree => {
const appComponent = tree.readContent(
‘/projects/schematest/src/app/app.component.ts');
expect(appComponent).toContain(`name = '${schemaOptions.name}'`);
});
});
Run Your Schematic with Angular CLI
$ npm pack
$ ng new my-test-app --routing --style css
$ cd my-test-app
$ npm install ../my-component/my-component-0.0.0.tgz
$ ng g my-component:my-component
Publish Your Schematic to npm
!22
By default, .npmignore ignores all TypeScript files
Modify .npmignore so it doesn't exclude your template files!
Run npm publish
Add Support for ng add with Angular CLI
!23
{
"$schema": "../node_modules/@angular-devkit/schematics/collection-schema.json",
"schematics": {
"my-component": {
"description": "A blank schematic.",
"factory": "./my-component/index#myComponent",
"schema": "./my-component/schema.json"
},
"ng-add": {
"factory": "./ng-add/index",
"description": "Add schematic",
"schema": "./my-component/schema.json"
}
}
}
Add Support for ng add with Angular CLI
!24
import { chain, Rule, schematic, SchematicContext, Tree, }
from '@angular-devkit/schematics';
export default function (options: any): Rule {
return (host: Tree, context: SchematicContext) => {
return chain([
schematic('my-component', options)
])(host, context);
};
}
Template Expression Language
Placeholder Description
<%= expression %>
Replaced with the result of the call of the given expression. This only supports
direct expressions, no structural (for/if/...) JavaScript.
<%- expression %>
Same as above, but the value of the result will be escaped for HTML when
inserted (i.e. replacing '<' with '<')
<% inline code %>
Inserts the given code into the template structure, allowing to insert structural
JavaScript.
<%# text %> A comment, which gets entirely dropped.
https://www.npmjs.com/package/@angular-devkit/schematics#content-templating
Example Template Code
import { Injectable } from '@angular/core';
<% if (platform === 'cordova') { %>
import { CordovaBrowser } from 'ionic-appauth/lib/cordova';
<% } else { %>
import { CapacitorBrowser } from 'ionic-appauth/lib/capacitor';
<% } %>
@Injectable({
providedIn: 'root'
})
export class BrowserService extends
<%= (platform === 'cordova') ? 'CordovaBrowser' : 'CapacitorBrowser' %> {
}
Secure Your Angular App in Minutes!
$ ng new my-secure-app --routing
$ cd my-secure-app
// create a SPA app on Okta, copy settings
$ ng add @oktadev/schematics
Use Angular Schematics to Simplify Your Life - Develop Denver 2019
Use Angular Schematics to Simplify Your Life - Develop Denver 2019
git clone https://github.com/oktadeveloper/okta-spring-webflux-react-
example.git
Blog, Screencast, and Source Code
https://developer.okta.com/blog/2019/02/13/angular-schematics
Supports Angular, React, Vue, and Ionic 4
Detects JavaScript or TypeScript
https://github.com/oktadeveloper/schematics
OktaDev Schematics
!31
📱
Thanks!
Keep in Touch
raibledesigns.com
@mraible
Presentations
speakerdeck.com/mraible
Code
github.com/oktadeveloper
developer.okta.com
developer.okta.com

More Related Content

What's hot (20)

PDF
Lock That Shit Down! Auth Security Patterns for Apps, APIs, and Infra - Sprin...
Matt Raible
 
PDF
Case Study: Migrating Hyperic from EJB to Spring from JBoss to Apache Tomcat
VMware Hyperic
 
PDF
10 Excellent Ways to Secure Your Spring Boot Application - Devoxx Belgium 2019
Matt Raible
 
PDF
What's New in Spring 3.1
Matt Raible
 
PDF
Front End Development for Back End Java Developers - Jfokus 2020
Matt Raible
 
PDF
Front End Development for Back End Developers - vJUG24 2017
Matt Raible
 
PDF
Java Web Application Security - Jazoon 2011
Matt Raible
 
PDF
Java REST API Framework Comparison - PWX 2021
Matt Raible
 
PDF
Java Web Application Security - Utah JUG 2011
Matt Raible
 
PDF
Bootiful Development with Spring Boot and React - UberConf 2018
Matt Raible
 
PDF
A Gentle Introduction to Angular Schematics - Devoxx Belgium 2019
Matt Raible
 
PDF
Front End Development for Back End Java Developers - NYJavaSIG 2019
Matt Raible
 
PDF
Java Web Application Security with Java EE, Spring Security and Apache Shiro ...
Matt Raible
 
PDF
A Gentle Introduction to Angular Schematics - Angular SF 2019
Matt Raible
 
PDF
Reactive Java Microservices with Spring Boot and JHipster - Denver JUG 2021
Matt Raible
 
PDF
Clojure Web Development
Hong Jiang
 
PDF
Java Microservices with Spring Boot and Spring Cloud - Denver JUG 2019
Matt Raible
 
PDF
Front End Development for Back End Developers - Denver Startup Week 2017
Matt Raible
 
PDF
JAX-RS JavaOne Hyderabad, India 2011
Shreedhar Ganapathy
 
PDF
Spark IT 2011 - Developing RESTful Web services with JAX-RS
Arun Gupta
 
Lock That Shit Down! Auth Security Patterns for Apps, APIs, and Infra - Sprin...
Matt Raible
 
Case Study: Migrating Hyperic from EJB to Spring from JBoss to Apache Tomcat
VMware Hyperic
 
10 Excellent Ways to Secure Your Spring Boot Application - Devoxx Belgium 2019
Matt Raible
 
What's New in Spring 3.1
Matt Raible
 
Front End Development for Back End Java Developers - Jfokus 2020
Matt Raible
 
Front End Development for Back End Developers - vJUG24 2017
Matt Raible
 
Java Web Application Security - Jazoon 2011
Matt Raible
 
Java REST API Framework Comparison - PWX 2021
Matt Raible
 
Java Web Application Security - Utah JUG 2011
Matt Raible
 
Bootiful Development with Spring Boot and React - UberConf 2018
Matt Raible
 
A Gentle Introduction to Angular Schematics - Devoxx Belgium 2019
Matt Raible
 
Front End Development for Back End Java Developers - NYJavaSIG 2019
Matt Raible
 
Java Web Application Security with Java EE, Spring Security and Apache Shiro ...
Matt Raible
 
A Gentle Introduction to Angular Schematics - Angular SF 2019
Matt Raible
 
Reactive Java Microservices with Spring Boot and JHipster - Denver JUG 2021
Matt Raible
 
Clojure Web Development
Hong Jiang
 
Java Microservices with Spring Boot and Spring Cloud - Denver JUG 2019
Matt Raible
 
Front End Development for Back End Developers - Denver Startup Week 2017
Matt Raible
 
JAX-RS JavaOne Hyderabad, India 2011
Shreedhar Ganapathy
 
Spark IT 2011 - Developing RESTful Web services with JAX-RS
Arun Gupta
 

Similar to Use Angular Schematics to Simplify Your Life - Develop Denver 2019 (20)

PDF
Angular Schematics
Christoffer Noring
 
PPTX
JS Fest 2019/Autumn. Maciej Treder. Angular Schematics - Develop for developers
JSFestUA
 
PDF
Everything You Should Know About the New Angular CLI
Amadou Sall
 
PDF
Basic overview of Angular
Aleksei Bulgak
 
PDF
Angular를 활용한 웹 프론트단 개발과 2.0에서 달라진점
Jeado Ko
 
PDF
Angular를 활용한 웹 프론트단 개발과 2.0에서 달라진점
WebFrameworks
 
PPTX
Talentica - JS Meetup - Angular Schematics
Krishnan Mudaliar
 
PPTX
Angularjs2 presentation
dharisk
 
PPTX
Ext Web Components - Dev Week 2019
Sandeep Adwankar
 
PDF
An introduction to Angular2
Apptension
 
PPTX
mean stack
michaelaaron25322
 
PDF
Capstone ms2
TanishGupta44
 
PDF
Angular 2 Essential Training
Patrick Schroeder
 
PDF
Exploring Angular 2 - Episode 1
Ahmed Moawad
 
PDF
Angular for Java Enterprise Developers: Oracle Code One 2018
Loiane Groner
 
PPTX
Angular 2
alinabiliashevych
 
PPTX
Angularj2.0
Mallikarjuna G D
 
PPTX
Foster - Getting started with Angular
MukundSonaiya1
 
PPTX
Angular 2 KTS
John Vall
 
PPTX
yrs of IT experience in enterprise programming
narasimhulum1623
 
Angular Schematics
Christoffer Noring
 
JS Fest 2019/Autumn. Maciej Treder. Angular Schematics - Develop for developers
JSFestUA
 
Everything You Should Know About the New Angular CLI
Amadou Sall
 
Basic overview of Angular
Aleksei Bulgak
 
Angular를 활용한 웹 프론트단 개발과 2.0에서 달라진점
Jeado Ko
 
Angular를 활용한 웹 프론트단 개발과 2.0에서 달라진점
WebFrameworks
 
Talentica - JS Meetup - Angular Schematics
Krishnan Mudaliar
 
Angularjs2 presentation
dharisk
 
Ext Web Components - Dev Week 2019
Sandeep Adwankar
 
An introduction to Angular2
Apptension
 
mean stack
michaelaaron25322
 
Capstone ms2
TanishGupta44
 
Angular 2 Essential Training
Patrick Schroeder
 
Exploring Angular 2 - Episode 1
Ahmed Moawad
 
Angular for Java Enterprise Developers: Oracle Code One 2018
Loiane Groner
 
Angularj2.0
Mallikarjuna G D
 
Foster - Getting started with Angular
MukundSonaiya1
 
Angular 2 KTS
John Vall
 
yrs of IT experience in enterprise programming
narasimhulum1623
 
Ad

More from Matt Raible (20)

PDF
Keep Identities in Sync the SCIMple Way - ApacheCon NA 2022
Matt Raible
 
PDF
Micro Frontends for Java Microservices - Belfast JUG 2022
Matt Raible
 
PDF
Micro Frontends for Java Microservices - Dublin JUG 2022
Matt Raible
 
PDF
Micro Frontends for Java Microservices - Cork JUG 2022
Matt Raible
 
PDF
Comparing Native Java REST API Frameworks - Seattle JUG 2022
Matt Raible
 
PDF
Reactive Java Microservices with Spring Boot and JHipster - Spring I/O 2022
Matt Raible
 
PDF
Comparing Native Java REST API Frameworks - Devoxx France 2022
Matt Raible
 
PDF
Lock That Sh*t Down! Auth Security Patterns for Apps, APIs, and Infra - Devne...
Matt Raible
 
PDF
Native Java with Spring Boot and JHipster - Garden State JUG 2021
Matt Raible
 
PDF
Mobile App Development with Ionic, React Native, and JHipster - Connect.Tech ...
Matt Raible
 
PDF
Lock That Shit Down! Auth Security Patterns for Apps, APIs, and Infra - Joker...
Matt Raible
 
PDF
Java REST API Framework Comparison - UberConf 2021
Matt Raible
 
PDF
Native Java with Spring Boot and JHipster - SF JUG 2021
Matt Raible
 
PDF
Get Hip with JHipster - Colorado Springs Open Source User Group 2021
Matt Raible
 
PDF
JHipster and Okta - JHipster Virtual Meetup December 2020
Matt Raible
 
PDF
Java REST API Comparison: Micronaut, Quarkus, and Spring Boot - jconf.dev 2020
Matt Raible
 
PDF
Security Patterns for Microservice Architectures - SpringOne 2020
Matt Raible
 
PDF
Security Patterns for Microservice Architectures - ADTMag Microservices & API...
Matt Raible
 
PDF
Microservices for the Masses with Spring Boot, JHipster, and OAuth - South We...
Matt Raible
 
PDF
Security Patterns for Microservice Architectures - London Java Community 2020
Matt Raible
 
Keep Identities in Sync the SCIMple Way - ApacheCon NA 2022
Matt Raible
 
Micro Frontends for Java Microservices - Belfast JUG 2022
Matt Raible
 
Micro Frontends for Java Microservices - Dublin JUG 2022
Matt Raible
 
Micro Frontends for Java Microservices - Cork JUG 2022
Matt Raible
 
Comparing Native Java REST API Frameworks - Seattle JUG 2022
Matt Raible
 
Reactive Java Microservices with Spring Boot and JHipster - Spring I/O 2022
Matt Raible
 
Comparing Native Java REST API Frameworks - Devoxx France 2022
Matt Raible
 
Lock That Sh*t Down! Auth Security Patterns for Apps, APIs, and Infra - Devne...
Matt Raible
 
Native Java with Spring Boot and JHipster - Garden State JUG 2021
Matt Raible
 
Mobile App Development with Ionic, React Native, and JHipster - Connect.Tech ...
Matt Raible
 
Lock That Shit Down! Auth Security Patterns for Apps, APIs, and Infra - Joker...
Matt Raible
 
Java REST API Framework Comparison - UberConf 2021
Matt Raible
 
Native Java with Spring Boot and JHipster - SF JUG 2021
Matt Raible
 
Get Hip with JHipster - Colorado Springs Open Source User Group 2021
Matt Raible
 
JHipster and Okta - JHipster Virtual Meetup December 2020
Matt Raible
 
Java REST API Comparison: Micronaut, Quarkus, and Spring Boot - jconf.dev 2020
Matt Raible
 
Security Patterns for Microservice Architectures - SpringOne 2020
Matt Raible
 
Security Patterns for Microservice Architectures - ADTMag Microservices & API...
Matt Raible
 
Microservices for the Masses with Spring Boot, JHipster, and OAuth - South We...
Matt Raible
 
Security Patterns for Microservice Architectures - London Java Community 2020
Matt Raible
 
Ad

Recently uploaded (20)

PDF
From Chaos to Clarity: Mastering Analytics Governance in the Modern Enterprise
Wiiisdom
 
PDF
Difference Between Kubernetes and Docker .pdf
Kindlebit Solutions
 
PDF
Transform Retail with Smart Technology: Power Your Growth with Ginesys
Ginesys
 
PPTX
MiniTool Power Data Recovery Full Crack Latest 2025
muhammadgurbazkhan
 
PPTX
Quality on Autopilot: Scaling Testing in Uyuni
Oscar Barrios Torrero
 
PDF
Continouous failure - Why do we make our lives hard?
Papp Krisztián
 
PDF
GridView,Recycler view, API, SQLITE& NetworkRequest.pdf
Nabin Dhakal
 
PPTX
Automatic_Iperf_Log_Result_Excel_visual_v2.pptx
Chen-Chih Lee
 
PPTX
WYSIWYG Web Builder Crack 2025 – Free Download Full Version with License Key
HyperPc soft
 
PPTX
How Apagen Empowered an EPC Company with Engineering ERP Software
SatishKumar2651
 
PDF
Salesforce CRM Services.VALiNTRY360
VALiNTRY360
 
PPTX
EO4EU Ocean Monitoring: Maritime Weather Routing Optimsation Use Case
EO4EU
 
PPTX
CONCEPT OF PROGRAMMING in language .pptx
tamim41
 
PDF
HiHelloHR – Simplify HR Operations for Modern Workplaces
HiHelloHR
 
PPTX
MailsDaddy Outlook OST to PST converter.pptx
abhishekdutt366
 
PDF
Linux Certificate of Completion - LabEx Certificate
VICTOR MAESTRE RAMIREZ
 
PPTX
NeuroStrata: Harnessing Neuro-Symbolic Paradigms for Improved Testability and...
Ivan Ruchkin
 
PDF
LPS25 - Operationalizing MLOps in GEP - Terradue.pdf
terradue
 
PDF
interacting-with-ai-2023---module-2---session-3---handout.pdf
cniclsh1
 
PPTX
Migrating Millions of Users with Debezium, Apache Kafka, and an Acyclic Synch...
MD Sayem Ahmed
 
From Chaos to Clarity: Mastering Analytics Governance in the Modern Enterprise
Wiiisdom
 
Difference Between Kubernetes and Docker .pdf
Kindlebit Solutions
 
Transform Retail with Smart Technology: Power Your Growth with Ginesys
Ginesys
 
MiniTool Power Data Recovery Full Crack Latest 2025
muhammadgurbazkhan
 
Quality on Autopilot: Scaling Testing in Uyuni
Oscar Barrios Torrero
 
Continouous failure - Why do we make our lives hard?
Papp Krisztián
 
GridView,Recycler view, API, SQLITE& NetworkRequest.pdf
Nabin Dhakal
 
Automatic_Iperf_Log_Result_Excel_visual_v2.pptx
Chen-Chih Lee
 
WYSIWYG Web Builder Crack 2025 – Free Download Full Version with License Key
HyperPc soft
 
How Apagen Empowered an EPC Company with Engineering ERP Software
SatishKumar2651
 
Salesforce CRM Services.VALiNTRY360
VALiNTRY360
 
EO4EU Ocean Monitoring: Maritime Weather Routing Optimsation Use Case
EO4EU
 
CONCEPT OF PROGRAMMING in language .pptx
tamim41
 
HiHelloHR – Simplify HR Operations for Modern Workplaces
HiHelloHR
 
MailsDaddy Outlook OST to PST converter.pptx
abhishekdutt366
 
Linux Certificate of Completion - LabEx Certificate
VICTOR MAESTRE RAMIREZ
 
NeuroStrata: Harnessing Neuro-Symbolic Paradigms for Improved Testability and...
Ivan Ruchkin
 
LPS25 - Operationalizing MLOps in GEP - Terradue.pdf
terradue
 
interacting-with-ai-2023---module-2---session-3---handout.pdf
cniclsh1
 
Migrating Millions of Users with Debezium, Apache Kafka, and an Acyclic Synch...
MD Sayem Ahmed
 

Use Angular Schematics to Simplify Your Life - Develop Denver 2019

  • 1. Use Angular Schematics to Simplify Your Life August 15, 2019 Matt Raible | @mraible Photo by Trish McGinity mcginityphoto.com
  • 2. Blogger on raibledesigns.com and developer.okta.com/blog Web Developer and Java Champion Father, Husband, Skier, Mountain Biker, Whitewater Rafter Open Source Connoisseur Hi, I’m Matt Raible! Bus Lover Okta Developer Advocate
  • 6. Agenda 1. What are Angular Schematics? 2. Create and Test a Schematic 3. Schematic Templates 4. Template Expression Language 5. OpenID Connect Authentication 6. Schematics for React, Vue, and Ionic
  • 7. What are Angular Schematics?
  • 8. Create a Schematic $ npm i -g @angular-devkit/schematics-cli $ schematics blank —-name=my-component CREATE /my-component/README.md (639 bytes) CREATE /my-component/.gitignore (191 bytes) CREATE /my-component/.npmignore (64 bytes) CREATE /my-component/package.json (539 bytes) CREATE /my-component/tsconfig.json (656 bytes) CREATE /my-component/src/collection.json (231 bytes) CREATE /my-component/src/my-component/index.ts (318 bytes) CREATE /my-component/src/my-component/index_spec.ts (474 bytes)
  • 9. Project metadata: collection.json { "$schema": "../node_modules/@angular-devkit/schematics/collection-schema.json", "schematics": { "my-component": { "description": "A blank schematic.", "factory": "./my-component/index#myComponent" } }
  • 10. Factory function: index.ts import { Rule, SchematicContext, Tree } from '@angular-devkit/schematics'; export function myComponent(_options: any): Rule { return (tree: Tree, _context: SchematicContext) => { return tree; }; }
  • 11. Unit test: index_spec.ts import { Tree } from '@angular-devkit/schematics'; import { SchematicTestRunner } from '@angular-devkit/schematics/testing'; import * as path from 'path'; const collectionPath = path.join(__dirname, '../collection.json'); describe('my-component', () => { it('works', () => { const runner = new SchematicTestRunner('schematics', collectionPath); const tree = runner.runSchematic('my-component', {}, Tree.empty()); expect(tree.files).toEqual([]); }); });
  • 13. Copy and Manipulate Templates: directory structure $ tree . src/my-component/ ├── files │ └── src │ └── app │ ├── app.component.html │ └── app.component.ts ├── index.ts └── index_spec.ts
  • 14. Copy and Manipulate Templates: app.component.ts import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { name = '<%= name %>'; } src/my-component/files/src/app/app.component.ts
  • 15. Copy and Manipulate Templates: app.component.html src/my-component/files/src/app/app.component.html <div style="text-align:center"> <h1> Hello, {{ name }} </h1> </div> <router-outlet></router-outlet>
  • 16. Copy and Manipulate Templates: schema.json { "$schema": "http://json-schema.org/schema", "id": "SchematicsMyComponent", "title": "My Component Schema", "type": "object", "properties": { "name": { "type": "string", "description": "Your Name", "x-prompt": "What is your name?" } }, "required": ["name"] }
  • 17. Copy and Manipulate Templates: collection.json { "$schema": "../node_modules/@angular-devkit/schematics/collection-schema.json", "schematics": { "my-component": { "description": "A blank schematic.", "factory": "./my-component/index#myComponent", "schema": "./my-component/schema.json" } } }
  • 18. Copy and Manipulate Templates: index.ts export function myComponent(_options: any): Rule { return (tree: Tree, _context: SchematicContext) => { setupOptions(tree, _options); const movePath = normalize(_options.path + '/'); const templateSource = apply(url('./files/src'), [ template({..._options}), move(movePath), // fix for https://github.com/angular/angular-cli/issues/11337 forEach((fileEntry: FileEntry) => { if (tree.exists(fileEntry.path)) { tree.overwrite(fileEntry.path, fileEntry.content); } return fileEntry; }), ]); const rule = mergeWith(templateSource, MergeStrategy.Overwrite); return rule(tree, _context); }; }
  • 19. Copy and Manipulate Templates: setupOptions() export function setupOptions(host: Tree, options: any): Tree { const workspace = getWorkspace(host); if (!options.project) { options.project = Object.keys(workspace.projects)[0]; } const project = workspace.projects[options.project]; options.path = join(normalize(project.root), 'src'); return host; }
  • 20. Copy and Manipulate Templates: index_spec.ts beforeEach(() => { appTree = schematicRunner.runExternalSchematic( '@schematics/angular', 'workspace', workspaceOptions); appTree = schematicRunner.runExternalSchematic( '@schematics/angular', 'application', appOptions, appTree); }); it('works', () => { const runner = new SchematicTestRunner('schematics', collectionPath); runner.runSchematicAsync( 'my-component', schemaOptions, appTree).toPromise().then(tree => { const appComponent = tree.readContent( ‘/projects/schematest/src/app/app.component.ts'); expect(appComponent).toContain(`name = '${schemaOptions.name}'`); }); });
  • 21. Run Your Schematic with Angular CLI $ npm pack $ ng new my-test-app --routing --style css $ cd my-test-app $ npm install ../my-component/my-component-0.0.0.tgz $ ng g my-component:my-component
  • 22. Publish Your Schematic to npm !22 By default, .npmignore ignores all TypeScript files Modify .npmignore so it doesn't exclude your template files! Run npm publish
  • 23. Add Support for ng add with Angular CLI !23 { "$schema": "../node_modules/@angular-devkit/schematics/collection-schema.json", "schematics": { "my-component": { "description": "A blank schematic.", "factory": "./my-component/index#myComponent", "schema": "./my-component/schema.json" }, "ng-add": { "factory": "./ng-add/index", "description": "Add schematic", "schema": "./my-component/schema.json" } } }
  • 24. Add Support for ng add with Angular CLI !24 import { chain, Rule, schematic, SchematicContext, Tree, } from '@angular-devkit/schematics'; export default function (options: any): Rule { return (host: Tree, context: SchematicContext) => { return chain([ schematic('my-component', options) ])(host, context); }; }
  • 25. Template Expression Language Placeholder Description <%= expression %> Replaced with the result of the call of the given expression. This only supports direct expressions, no structural (for/if/...) JavaScript. <%- expression %> Same as above, but the value of the result will be escaped for HTML when inserted (i.e. replacing '<' with '<') <% inline code %> Inserts the given code into the template structure, allowing to insert structural JavaScript. <%# text %> A comment, which gets entirely dropped. https://www.npmjs.com/package/@angular-devkit/schematics#content-templating
  • 26. Example Template Code import { Injectable } from '@angular/core'; <% if (platform === 'cordova') { %> import { CordovaBrowser } from 'ionic-appauth/lib/cordova'; <% } else { %> import { CapacitorBrowser } from 'ionic-appauth/lib/capacitor'; <% } %> @Injectable({ providedIn: 'root' }) export class BrowserService extends <%= (platform === 'cordova') ? 'CordovaBrowser' : 'CapacitorBrowser' %> { }
  • 27. Secure Your Angular App in Minutes! $ ng new my-secure-app --routing $ cd my-secure-app // create a SPA app on Okta, copy settings $ ng add @oktadev/schematics
  • 30. git clone https://github.com/oktadeveloper/okta-spring-webflux-react- example.git Blog, Screencast, and Source Code https://developer.okta.com/blog/2019/02/13/angular-schematics
  • 31. Supports Angular, React, Vue, and Ionic 4 Detects JavaScript or TypeScript https://github.com/oktadeveloper/schematics OktaDev Schematics !31 📱