6 Commits

Author SHA1 Message Date
  Kevin C. Coram ff1268e129
Add summary of static method approach to main README 1 year ago
  Kevin C. Coram 5d0c467849
Document static method approach 1 year ago
  Kevin C. Coram f1344707e7
Stronger statement about potential problem with tying form creation to component rendering 1 year ago
  Kevin C. Coram 8802b52e54
Use OnPush change detection strategy 1 year ago
  Kevin C. Coram b7870b607b
Remove FormBuilder dependency; rname factory methods 1 year ago
  Kevin C. Coram cb8144044e
Add fourth approach: Static methods on child components 1 year ago
37 changed files with 694 additions and 2 deletions
Split View
  1. +7
    -1
      README.md
  2. +87
    -0
      angular.json
  3. +1
    -1
      apps/parent-form/README.md
  4. +87
    -0
      apps/static-factory-methods/README.md
  5. +12
    -0
      apps/static-factory-methods/browserslist
  6. +9
    -0
      apps/static-factory-methods/jest.config.js
  7. +0
    -0
      apps/static-factory-methods/src/app/address-list/address-list.component.css
  8. +3
    -0
      apps/static-factory-methods/src/app/address-list/address-list.component.html
  9. +28
    -0
      apps/static-factory-methods/src/app/address-list/address-list.component.spec.ts
  10. +35
    -0
      apps/static-factory-methods/src/app/address-list/address-list.component.ts
  11. +0
    -0
      apps/static-factory-methods/src/app/address/address.component.css
  12. +27
    -0
      apps/static-factory-methods/src/app/address/address.component.html
  13. +27
    -0
      apps/static-factory-methods/src/app/address/address.component.spec.ts
  14. +32
    -0
      apps/static-factory-methods/src/app/address/address.component.ts
  15. +0
    -0
      apps/static-factory-methods/src/app/app.component.css
  16. +8
    -0
      apps/static-factory-methods/src/app/app.component.html
  17. +33
    -0
      apps/static-factory-methods/src/app/app.component.spec.ts
  18. +44
    -0
      apps/static-factory-methods/src/app/app.component.ts
  19. +23
    -0
      apps/static-factory-methods/src/app/app.module.ts
  20. +0
    -0
      apps/static-factory-methods/src/app/name/name.component.css
  21. +27
    -0
      apps/static-factory-methods/src/app/name/name.component.html
  22. +26
    -0
      apps/static-factory-methods/src/app/name/name.component.spec.ts
  23. +32
    -0
      apps/static-factory-methods/src/app/name/name.component.ts
  24. +0
    -0
      apps/static-factory-methods/src/assets/.gitkeep
  25. +3
    -0
      apps/static-factory-methods/src/environments/environment.prod.ts
  26. +16
    -0
      apps/static-factory-methods/src/environments/environment.ts
  27. BIN
      apps/static-factory-methods/src/favicon.ico
  28. +14
    -0
      apps/static-factory-methods/src/index.html
  29. +13
    -0
      apps/static-factory-methods/src/main.ts
  30. +62
    -0
      apps/static-factory-methods/src/polyfills.ts
  31. +1
    -0
      apps/static-factory-methods/src/styles.css
  32. +1
    -0
      apps/static-factory-methods/src/test-setup.ts
  33. +9
    -0
      apps/static-factory-methods/tsconfig.app.json
  34. +7
    -0
      apps/static-factory-methods/tsconfig.json
  35. +10
    -0
      apps/static-factory-methods/tsconfig.spec.json
  36. +7
    -0
      apps/static-factory-methods/tslint.json
  37. +3
    -0
      nx.json

+ 7
- 1
README.md View File

@@ -24,4 +24,10 @@ The [Parent Form](apps/parent-form) application explores this approach.

Another approach is to allow the outermost, or parent, component create the full Reactive Form. Each child component is given the `FormGroup` containing the portion of the form that it is responsible for rendering.

The [Global Form](apps/global-form) application explores this approach.
The [Global Form](apps/global-form) application explores this approach.

## Parent Component Creates Form; Child Components Define Structure

Another approach is to allow the parent component to maintain control of creating the full Reactive Form, while allowing each child component to define the shape of the form data by means of static factory methods defined within the child component code.

The [Static Method](apps/static-factory-methods/README.md) application explores this approach.

+ 87
- 0
angular.json View File

@@ -287,6 +287,93 @@
}
}
}
},
"static-factory-methods": {
"projectType": "application",
"schematics": {},
"root": "apps/static-factory-methods",
"sourceRoot": "apps/static-factory-methods/src",
"prefix": "nested-forms",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "dist/apps/static-factory-methods",
"index": "apps/static-factory-methods/src/index.html",
"main": "apps/static-factory-methods/src/main.ts",
"polyfills": "apps/static-factory-methods/src/polyfills.ts",
"tsConfig": "apps/static-factory-methods/tsconfig.app.json",
"aot": false,
"assets": [
"apps/static-factory-methods/src/favicon.ico",
"apps/static-factory-methods/src/assets"
],
"styles": ["apps/static-factory-methods/src/styles.css"],
"scripts": []
},
"configurations": {
"production": {
"fileReplacements": [
{
"replace": "apps/static-factory-methods/src/environments/environment.ts",
"with": "apps/static-factory-methods/src/environments/environment.prod.ts"
}
],
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"extractCss": true,
"namedChunks": false,
"aot": true,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"budgets": [
{
"type": "initial",
"maximumWarning": "2mb",
"maximumError": "5mb"
}
]
}
}
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "static-factory-methods:build"
},
"configurations": {
"production": {
"browserTarget": "static-factory-methods:build:production"
}
}
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"options": {
"browserTarget": "static-factory-methods:build"
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"apps/static-factory-methods/tsconfig.app.json",
"apps/static-factory-methods/tsconfig.spec.json"
],
"exclude": ["**/node_modules/**", "!apps/static-factory-methods/**"]
}
},
"test": {
"builder": "@nrwl/jest:jest",
"options": {
"jestConfig": "apps/static-factory-methods/jest.config.js",
"tsConfig": "apps/static-factory-methods/tsconfig.spec.json",
"setupFile": "apps/static-factory-methods/src/test-setup.ts"
}
}
}
}
},
"cli": {


+ 1
- 1
apps/parent-form/README.md View File

@@ -78,6 +78,6 @@ Calling `this.parent.addControl(....)` is what ensures that the controls created

## Cons

- The creation of the form controls is tightly coupled with the templates
- The creation of the form controls is tightly coupled with the templates, to the point that if a child component is not rendered for some reason, the form controls won't exist either.
- Since each child component encapsulates its form controls, the overall shape of the form data is not always clear


+ 87
- 0
apps/static-factory-methods/README.md View File

@@ -0,0 +1,87 @@
# Parent Component Creates Form; Child Components Define Structure

Another approach for refactoring a component into child sub-components where the parent component is responsible for creating the entre Reactive Form would be to define static factory methods within each child component rather than within a full-fledged service. As with the [Parent Component Creates Form and Passes Form Controls Into Child Components (Global Form)](../global-form/README.md) approach, the appropriate form controls would be passed into the children.

In many ways, this approach is a hybrid between the Parent Form and Global Form approaches.

```typescript
export class AppComponent implements OnInit, OnDestroy {
contact: Contact;
form: FormGroup;

private subscription: Subscription;

constructor(private service: ContactService, private fb: FormBuilder) {}

public ngOnInit() {
this.subscription = this.service
.loadContact()
.subscribe((data: Contact) => {
this.contact = data;
this.form = this.fb.group({
name: NameComponent.buildForm(data.name),
addresses: AddressListComponent.buildForm(data.addresses),
});
});
}
}
```

The HTML templating will be identical to the Global Form approach.

## Static Form Builder Methods

Rather than having a separate factory service, this approach uses static methods on each of the child sub-classes. This approach intentionally couples the logic for creating a sub-form structure with the component that would display it, keeping the logic in one place rather than separating it between components and an otherwise unrelated service. The rule-of-thumb in this approach is that the component which needs to display the form to a user will best know what the structure of that form needs to be.

### Name Component

```typescript
static buildForm(name: Name): FormGroup {
return new FormGroup({
firstName: new FormControl(name ? name.firstName : ''),
lastName: new FormControl(name ? name.lastName : ''),
middleName: new FormControl(name ? name.middleName : ''),
prefix: new FormControl(name ? name.prefix : ''),
suffix: new FormControl(name ? name.suffix : ''),
});
}
```

### Address List Component

```typescript
static buildForm(addresses: Address[]): FormArray {
const list: FormArray = new FormArray([]);

if (addresses) {
addresses.forEach(addr => {
list.push(AddressComponent.buildForm(addr));
});
}

return list;
}
```

### Address Component

```typescript
static buildForm(addr: Address): FormGroup {
return new FormGroup({
line1: new FormControl(addr ? addr.line1 : ''),
line2: new FormControl(addr ? addr.line2 : ''),
city: new FormControl(addr ? addr.city : ''),
state: new FormControl(addr ? addr.state : ''),
postalCode: new FormControl(addr ? addr.postalCode : ''),
});
}
```

## Pros

- The child components encapsulate the form controls and their display, while keeping the form creation logic separate from the actual template rendering
- The child components can easily be re-used

## Cons

- The overall shape of the form from the parent component's perspective is not always clear

+ 12
- 0
apps/static-factory-methods/browserslist View File

@@ -0,0 +1,12 @@
# This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
# For additional information regarding the format and rule options, please see:
# https://github.com/browserslist/browserslist#queries

# You can see what browsers were selected by your queries by running:
# npx browserslist

> 0.5%
last 2 versions
Firefox ESR
not dead
not IE 9-11 # For IE 9-11 support, remove 'not'.

+ 9
- 0
apps/static-factory-methods/jest.config.js View File

@@ -0,0 +1,9 @@
module.exports = {
name: 'static-factory-methods',
preset: '../../jest.config.js',
coverageDirectory: '../../coverage/apps/static-factory-methods',
snapshotSerializers: [
'jest-preset-angular/AngularSnapshotSerializer.js',
'jest-preset-angular/HTMLCommentSerializer.js',
],
};

+ 0
- 0
apps/static-factory-methods/src/app/address-list/address-list.component.css View File


+ 3
- 0
apps/static-factory-methods/src/app/address-list/address-list.component.html View File

@@ -0,0 +1,3 @@
<ng-container *ngFor="let addr of addressArray?.controls">
<nested-forms-address [addressGroup]="addr"></nested-forms-address>
</ng-container>

+ 28
- 0
apps/static-factory-methods/src/app/address-list/address-list.component.spec.ts View File

@@ -0,0 +1,28 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ReactiveFormsModule } from '@angular/forms';

import { AddressComponent } from './../address/address.component';
import { AddressListComponent } from './address-list.component';

describe('AddressListComponent', () => {
let component: AddressListComponent;
let fixture: ComponentFixture<AddressListComponent>;

beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [ReactiveFormsModule],
declarations: [ AddressListComponent, AddressComponent ]
})
.compileComponents();
}));

beforeEach(() => {
fixture = TestBed.createComponent(AddressListComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});

+ 35
- 0
apps/static-factory-methods/src/app/address-list/address-list.component.ts View File

@@ -0,0 +1,35 @@
import {
ChangeDetectionStrategy,
Component,
Input,
OnInit,
} from '@angular/core';
import { FormArray } from '@angular/forms';
import { Address } from '@nested-forms/contact';
import { AddressComponent } from '../address/address.component';

@Component({
selector: 'nested-forms-address-list',
templateUrl: './address-list.component.html',
styleUrls: ['./address-list.component.css'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AddressListComponent implements OnInit {
@Input() addressArray: FormArray;

static buildForm(addresses: Address[]): FormArray {
const list: FormArray = new FormArray([]);

if (addresses) {
addresses.forEach(addr => {
list.push(AddressComponent.buildForm(addr));
});
}

return list;
}

constructor() {}

ngOnInit() {}
}

+ 0
- 0
apps/static-factory-methods/src/app/address/address.component.css View File


+ 27
- 0
apps/static-factory-methods/src/app/address/address.component.html View File

@@ -0,0 +1,27 @@
<form *ngIf="addressGroup" [formGroup]="addressGroup">
<div>
<label for="line1">Line 1: </label>
<input name="line1" formControlName="line1">
</div>
<div>
<label for="line2">Line 2: </label>
<input name="line2" formControlName="line2">
</div>
<div>
<label for="city">City: </label>
<input name="city" formControlName="city">
</div>
<div>
<label for="state">State: </label>
<input name="state" formControlName="state">
</div>
<div>
<label for="postalCode">Postal Code: </label>
<input name="postalCode" formControlName="postalCode">
</div>
</form>

+ 27
- 0
apps/static-factory-methods/src/app/address/address.component.spec.ts View File

@@ -0,0 +1,27 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ReactiveFormsModule } from '@angular/forms';

import { AddressComponent } from './address.component';

describe('AddressComponent', () => {
let component: AddressComponent;
let fixture: ComponentFixture<AddressComponent>;

beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [ReactiveFormsModule],
declarations: [ AddressComponent ]
})
.compileComponents();
}));

beforeEach(() => {
fixture = TestBed.createComponent(AddressComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});

+ 32
- 0
apps/static-factory-methods/src/app/address/address.component.ts View File

@@ -0,0 +1,32 @@
import {
ChangeDetectionStrategy,
Component,
Input,
OnInit,
} from '@angular/core';
import { FormControl, FormGroup } from '@angular/forms';
import { Address } from '@nested-forms/contact';

@Component({
selector: 'nested-forms-address',
templateUrl: './address.component.html',
styleUrls: ['./address.component.css'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AddressComponent implements OnInit {
@Input() addressGroup: FormGroup;

static buildForm(addr: Address): FormGroup {
return new FormGroup({
line1: new FormControl(addr ? addr.line1 : ''),
line2: new FormControl(addr ? addr.line2 : ''),
city: new FormControl(addr ? addr.city : ''),
state: new FormControl(addr ? addr.state : ''),
postalCode: new FormControl(addr ? addr.postalCode : ''),
});
}

constructor() {}

ngOnInit() {}
}

+ 0
- 0
apps/static-factory-methods/src/app/app.component.css View File


+ 8
- 0
apps/static-factory-methods/src/app/app.component.html View File

@@ -0,0 +1,8 @@
<form [formGroup]="form">
<nested-forms-name [nameGroup]="form.get('name')"></nested-forms-name>
<nested-forms-address-list [addressArray]="form.get('addresses')"></nested-forms-address-list>
</form>
<hr />
<pre>
{{ form.value | json }}
</pre>

+ 33
- 0
apps/static-factory-methods/src/app/app.component.spec.ts View File

@@ -0,0 +1,33 @@
import { ReactiveFormsModule } from '@angular/forms';
import { RouterTestingModule } from '@angular/router/testing';
import { TestBed, async } from '@angular/core/testing';
import { AppComponent } from './app.component';
import { NameComponent } from './name/name.component';
import { AddressListComponent } from './address-list/address-list.component';
import { AddressComponent } from './address/address.component';
import { ContactModule } from '@nested-forms/contact';

describe('AppComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
RouterTestingModule,
ReactiveFormsModule,
ContactModule.forRoot(),
],
declarations: [
AppComponent,
NameComponent,
AddressComponent,
AddressListComponent,
],
providers: [],
}).compileComponents();
}));

it('should create the app', () => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app).toBeTruthy();
});
});

+ 44
- 0
apps/static-factory-methods/src/app/app.component.ts View File

@@ -0,0 +1,44 @@
import {
ChangeDetectionStrategy,
Component,
OnDestroy,
OnInit,
} from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';
import { Contact, ContactService } from '@nested-forms/contact';
import { Subscription } from 'rxjs';
import { AddressListComponent } from './address-list/address-list.component';
import { NameComponent } from './name/name.component';

@Component({
selector: 'nested-forms-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AppComponent implements OnInit, OnDestroy {
contact: Contact;
form: FormGroup;

private subscription: Subscription;

constructor(private service: ContactService, private fb: FormBuilder) {}

public ngOnInit() {
this.subscription = this.service
.loadContact()
.subscribe((data: Contact) => {
this.contact = data;
this.form = this.fb.group({
name: NameComponent.buildForm(data.name),
addresses: AddressListComponent.buildForm(data.addresses),
});
});
}

public ngOnDestroy() {
if (this.subscription) {
this.subscription.unsubscribe();
}
}
}

+ 23
- 0
apps/static-factory-methods/src/app/app.module.ts View File

@@ -0,0 +1,23 @@
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';
import { RouterModule } from '@angular/router';
import { ReactiveFormsModule } from '@angular/forms';
import { NameComponent } from './name/name.component';
import { ContactModule } from '@nested-forms/contact';
import { AddressListComponent } from './address-list/address-list.component';
import { AddressComponent } from './address/address.component';

@NgModule({
declarations: [AppComponent, NameComponent, AddressListComponent, AddressComponent],
imports: [
BrowserModule,
RouterModule.forRoot([], { initialNavigation: 'enabled' }),
ReactiveFormsModule,
ContactModule.forRoot()
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule {}

+ 0
- 0
apps/static-factory-methods/src/app/name/name.component.css View File


+ 27
- 0
apps/static-factory-methods/src/app/name/name.component.html View File

@@ -0,0 +1,27 @@
<form *ngIf="nameGroup" [formGroup]="nameGroup">
<div>
<label for="firstName">First Name: </label>
<input name="firstName" formControlName="firstName">
</div>
<div>
<label for="lastName">Last Name: </label>
<input name="lastName" formControlName="lastName">
</div>
<div>
<label for="middleName">Middle Name: </label>
<input name="middleName" formControlName="middleName">
</div>
<div>
<label for="prefix">Prefix: </label>
<input name="prefix" formControlName="prefix">
</div>
<div>
<label for="suffix">Suffix: </label>
<input name="suffix" formControlName="suffix">
</div>
</form>

+ 26
- 0
apps/static-factory-methods/src/app/name/name.component.spec.ts View File

@@ -0,0 +1,26 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ReactiveFormsModule } from '@angular/forms';

import { NameComponent } from './name.component';

describe('NameComponent', () => {
let component: NameComponent;
let fixture: ComponentFixture<NameComponent>;

beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [ReactiveFormsModule],
declarations: [NameComponent]
}).compileComponents();
}));

beforeEach(() => {
fixture = TestBed.createComponent(NameComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});

+ 32
- 0
apps/static-factory-methods/src/app/name/name.component.ts View File

@@ -0,0 +1,32 @@
import {
ChangeDetectionStrategy,
Component,
Input,
OnInit,
} from '@angular/core';
import { FormControl, FormGroup } from '@angular/forms';
import { Name } from '@nested-forms/contact';

@Component({
selector: 'nested-forms-name',
templateUrl: './name.component.html',
styleUrls: ['./name.component.css'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class NameComponent implements OnInit {
@Input() nameGroup: FormGroup;

static buildForm(name: Name): FormGroup {
return new FormGroup({
firstName: new FormControl(name ? name.firstName : ''),
lastName: new FormControl(name ? name.lastName : ''),
middleName: new FormControl(name ? name.middleName : ''),
prefix: new FormControl(name ? name.prefix : ''),
suffix: new FormControl(name ? name.suffix : ''),
});
}

constructor() {}

ngOnInit() {}
}

+ 0
- 0
apps/static-factory-methods/src/assets/.gitkeep View File


+ 3
- 0
apps/static-factory-methods/src/environments/environment.prod.ts View File

@@ -0,0 +1,3 @@
export const environment = {
production: true
};

+ 16
- 0
apps/static-factory-methods/src/environments/environment.ts View File

@@ -0,0 +1,16 @@
// This file can be replaced during build by using the `fileReplacements` array.
// `ng build --prod` replaces `environment.ts` with `environment.prod.ts`.
// The list of file replacements can be found in `angular.json`.

export const environment = {
production: false
};

/*
* For easier debugging in development mode, you can import the following file
* to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`.
*
* This import should be commented out in production mode because it will have a negative impact
* on performance if an error is thrown.
*/
// import 'zone.js/dist/zone-error'; // Included with Angular CLI.

BIN
apps/static-factory-methods/src/favicon.ico View File

Before After

+ 14
- 0
apps/static-factory-methods/src/index.html View File

@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>GlobalForm</title>
<base href="/" />

<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" type="image/x-icon" href="favicon.ico" />
</head>
<body>
<nested-forms-root></nested-forms-root>
</body>
</html>

+ 13
- 0
apps/static-factory-methods/src/main.ts View File

@@ -0,0 +1,13 @@
import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

import { AppModule } from './app/app.module';
import { environment } from './environments/environment';

if (environment.production) {
enableProdMode();
}

platformBrowserDynamic()
.bootstrapModule(AppModule)
.catch(err => console.error(err));

+ 62
- 0
apps/static-factory-methods/src/polyfills.ts View File

@@ -0,0 +1,62 @@
/**
* This file includes polyfills needed by Angular and is loaded before the app.
* You can add your own extra polyfills to this file.
*
* This file is divided into 2 sections:
* 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
* 2. Application imports. Files imported after ZoneJS that should be loaded before your main
* file.
*
* The current setup is for so-called "evergreen" browsers; the last versions of browsers that
* automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
* Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
*
* Learn more in https://angular.io/guide/browser-support
*/

/***************************************************************************************************
* BROWSER POLYFILLS
*/

/** IE10 and IE11 requires the following for NgClass support on SVG elements */
// import 'classlist.js'; // Run `npm install --save classlist.js`.

/**
* Web Animations `@angular/platform-browser/animations`
* Only required if AnimationBuilder is used within the application and using IE/Edge or Safari.
* Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0).
*/
// import 'web-animations-js'; // Run `npm install --save web-animations-js`.

/**
* By default, zone.js will patch all possible macroTask and DomEvents
* user can disable parts of macroTask/DomEvents patch by setting following flags
* because those flags need to be set before `zone.js` being loaded, and webpack
* will put import in the top of bundle, so user need to create a separate file
* in this directory (for example: zone-flags.ts), and put the following flags
* into that file, and then add the following code before importing zone.js.
* import './zone-flags.ts';
*
* The flags allowed in zone-flags.ts are listed here.
*
* The following flags will work for all browsers.
*
* (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame
* (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
* (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames
*
* in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js
* with the following flag, it will bypass `zone.js` patch for IE/Edge
*
* (window as any).__Zone_enable_cross_context_check = true;
*
*/

/***************************************************************************************************
* Zone JS is required by default for Angular itself.
*/
import 'zone.js/dist/zone'; // Included with Angular CLI.

/***************************************************************************************************
* APPLICATION IMPORTS
*/

+ 1
- 0
apps/static-factory-methods/src/styles.css View File

@@ -0,0 +1 @@
/* You can add global styles to this file, and also import other style files */

+ 1
- 0
apps/static-factory-methods/src/test-setup.ts View File

@@ -0,0 +1 @@
import 'jest-preset-angular';

+ 9
- 0
apps/static-factory-methods/tsconfig.app.json View File

@@ -0,0 +1,9 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../dist/out-tsc",
"types": []
},
"include": ["**/*.ts"],
"exclude": ["src/test-setup.ts", "**/*.spec.ts"]
}

+ 7
- 0
apps/static-factory-methods/tsconfig.json View File

@@ -0,0 +1,7 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"types": ["node", "jest"]
},
"include": ["**/*.ts"]
}

+ 10
- 0
apps/static-factory-methods/tsconfig.spec.json View File

@@ -0,0 +1,10 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../dist/out-tsc",
"module": "commonjs",
"types": ["jest", "node"]
},
"files": ["src/test-setup.ts"],
"include": ["**/*.spec.ts", "**/*.d.ts"]
}

+ 7
- 0
apps/static-factory-methods/tslint.json View File

@@ -0,0 +1,7 @@
{
"extends": "../../tslint.json",
"rules": {
"directive-selector": [true, "attribute", "nestedForms", "camelCase"],
"component-selector": [true, "element", "nested-forms", "kebab-case"]
}
}

+ 3
- 0
nx.json View File

@@ -19,6 +19,9 @@
},
"baseline": {
"tags": []
},
"static-factory-methods": {
"tags": []
}
}
}

Loading…
Cancel
Save