Compare commits

..

7 Commits

40 changed files with 315 additions and 52 deletions

View File

@ -1,3 +1,4 @@
{
"singleQuote": true
"singleQuote": true,
"trailingComma": "all"
}

View File

@ -1,9 +1,9 @@
{
"version": 1,
"projects": {
"contact-model": {
"root": "libs/contact-model",
"sourceRoot": "libs/contact-model/src",
"contact": {
"root": "libs/contact",
"sourceRoot": "libs/contact/src",
"projectType": "library",
"schematics": {},
"architect": {
@ -11,18 +11,18 @@
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"libs/contact-model/tsconfig.lib.json",
"libs/contact-model/tsconfig.spec.json"
"libs/contact/tsconfig.lib.json",
"libs/contact/tsconfig.spec.json"
],
"exclude": ["**/node_modules/**", "!libs/contact-model/**"]
"exclude": ["**/node_modules/**", "!libs/contact/**"]
}
},
"test": {
"builder": "@nrwl/jest:jest",
"options": {
"jestConfig": "libs/contact-model/jest.config.js",
"tsConfig": "libs/contact-model/tsconfig.spec.json",
"setupFile": "libs/contact-model/src/test-setup.ts"
"jestConfig": "libs/contact/jest.config.js",
"tsConfig": "libs/contact/tsconfig.spec.json",
"setupFile": "libs/contact/src/test-setup.ts"
}
}
}

View File

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

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();
});
});

View File

@ -0,0 +1,17 @@
import { Component, OnInit, Input } from '@angular/core';
import { FormArray } from '@angular/forms';
@Component({
selector: 'nested-forms-address-list',
templateUrl: './address-list.component.html',
styleUrls: ['./address-list.component.css']
})
export class AddressListComponent implements OnInit {
@Input() addressArray: FormArray;
constructor() { }
ngOnInit() {
}
}

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>

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();
});
});

View File

@ -0,0 +1,17 @@
import { Component, OnInit, Input } from '@angular/core';
import { FormGroup } from '@angular/forms';
@Component({
selector: 'nested-forms-address',
templateUrl: './address.component.html',
styleUrls: ['./address.component.css']
})
export class AddressComponent implements OnInit {
@Input() addressGroup: FormGroup;
constructor() { }
ngOnInit() {
}
}

View File

@ -1,5 +1,6 @@
<form [formGroup]="form">
<nested-forms-name [nameGroup]="form.get('nameGroup')"></nested-forms-name>
<nested-forms-address-list [addressArray]="form.get('addresses')"></nested-forms-address-list>
</form>
<hr />
<pre>

View File

@ -3,12 +3,21 @@ 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';
import { ContactFormService } from './services/contact-form.service';
describe('AppComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [RouterTestingModule, ReactiveFormsModule],
declarations: [AppComponent, NameComponent]
imports: [
RouterTestingModule,
ReactiveFormsModule,
ContactModule.forRoot()
],
declarations: [AppComponent, NameComponent, AddressComponent, AddressListComponent],
providers: [ ContactFormService ],
}).compileComponents();
}));
@ -17,5 +26,4 @@ describe('AppComponent', () => {
const app = fixture.debugElement.componentInstance;
expect(app).toBeTruthy();
});
});

View File

@ -1,23 +1,37 @@
import { FormGroup, FormBuilder } from '@angular/forms';
import { Component } from '@angular/core';
import { Component, OnDestroy, OnInit } from '@angular/core';
import { FormGroup } from '@angular/forms';
import { Contact, ContactService } from '@nested-forms/contact';
import { Subscription } from 'rxjs';
import { ContactFormService } from './services/contact-form.service';
@Component({
selector: 'nested-forms-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
styleUrls: ['./app.component.css'],
})
export class AppComponent {
export class AppComponent implements OnInit, OnDestroy {
contact: Contact;
form: FormGroup;
constructor(private fb: FormBuilder) {
this.form = this.fb.group({
nameGroup: this.fb.group({
firstName: [], // new FormControl(this.name ? this.name.firstName : ''),
lastName: [], // new FormControl(this.name ? this.name.lastName : ''),
middleName: [], // new FormControl(this.name ? this.name.middleName : ''),
prefix: [], // new FormControl(this.name ? this.name.prefix : ''),
suffix: [], // new FormControl(this.name ? this.name.suffix : ''),
})
});
private subscription: Subscription;
constructor(
private service: ContactService,
private formService: ContactFormService,
) {}
public ngOnInit() {
this.subscription = this.service
.loadContact()
.subscribe((data: Contact) => {
this.contact = data;
this.form = this.formService.createForm(data);
});
}
public ngOnDestroy() {
if (this.subscription) {
this.subscription.unsubscribe();
}
}
}

View File

@ -5,13 +5,17 @@ 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],
declarations: [AppComponent, NameComponent, AddressListComponent, AddressComponent],
imports: [
BrowserModule,
RouterModule.forRoot([], { initialNavigation: 'enabled' }),
ReactiveFormsModule
ReactiveFormsModule,
ContactModule.forRoot()
],
providers: [],
bootstrap: [AppComponent]

View File

@ -1 +1,27 @@
<p>name works!</p>
<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>

View File

@ -1,4 +1,5 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ReactiveFormsModule } from '@angular/forms';
import { NameComponent } from './name.component';
@ -8,6 +9,7 @@ describe('NameComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [ReactiveFormsModule],
declarations: [NameComponent]
}).compileComponents();
}));

View File

@ -0,0 +1,15 @@
import { TestBed } from '@angular/core/testing';
import { ReactiveFormsModule } from '@angular/forms';
import { ContactFormService } from './contact-form.service';
describe('ContactFormService', () => {
beforeEach(() => TestBed.configureTestingModule({
imports: [ReactiveFormsModule],
}));
it('should be created', () => {
const service: ContactFormService = TestBed.get(ContactFormService);
expect(service).toBeTruthy();
});
});

View File

@ -0,0 +1,43 @@
import { Injectable } from '@angular/core';
import { FormArray, FormBuilder, FormGroup } from '@angular/forms';
import { Contact } from '@nested-forms/contact';
@Injectable({
providedIn: 'root',
})
export class ContactFormService {
constructor(private fb: FormBuilder) {}
public createForm(model: Contact): FormGroup {
const name = model.name;
const addresses: FormArray = this.fb.array([]);
const group = this.fb.group({
nameGroup: this.fb.group({
firstName: [name ? name.firstName : ''],
lastName: [name ? name.lastName : ''],
middleName: [name ? name.middleName : ''],
prefix: [name ? name.prefix : ''],
suffix: [name ? name.suffix : ''],
}),
addresses: addresses,
});
if (model.addresses) {
model.addresses.forEach(addr => {
addresses.push(
this.fb.group({
line1: [addr ? addr.line_1 : ''],
line2: [addr ? addr.line_2 : ''],
city: [addr ? addr.city : ''],
state: [addr ? addr.state : ''],
postalCode: [addr ? addr.postalCode : ''],
}),
);
});
}
return group;
}
}

View File

@ -1,5 +1,5 @@
import { FormGroup, FormBuilder, FormArray } from '@angular/forms';
import { Address } from '@nested-forms/contact-model';
import { Address } from '@nested-forms/contact';
import { Component, OnInit, Input } from '@angular/core';
@Component({

View File

@ -1,5 +1,5 @@
import { FormArray, FormBuilder, FormGroup, FormControl } from '@angular/forms';
import { Address } from '@nested-forms/contact-model';
import { Address } from '@nested-forms/contact';
import { Component, OnInit, Input } from '@angular/core';
@Component({

View File

@ -5,11 +5,12 @@ import { AppComponent } from './app.component';
import { RouterTestingModule } from '@angular/router/testing';
import { ReactiveFormsModule } from '@angular/forms';
import { NameComponent } from './name/name.component';
import { ContactModule } from '@nested-forms/contact';
describe('AppComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [RouterTestingModule, ReactiveFormsModule],
imports: [RouterTestingModule, ReactiveFormsModule, ContactModule.forRoot()],
declarations: [AppComponent, NameComponent, AddressListComponent, AddressComponent]
}).compileComponents();
}));

View File

@ -1,5 +1,4 @@
import { ContactService } from './../../../../libs/contact-model/src/lib/contact.service';
import { Contact } from '@nested-forms/contact-model';
import { Contact, ContactService } from '@nested-forms/contact';
import { Component, OnInit, OnDestroy } from '@angular/core';
import { FormGroup, FormBuilder } from '@angular/forms';
import { Subscription } from 'rxjs';

View File

@ -7,6 +7,7 @@ import { ReactiveFormsModule } from '@angular/forms';
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';
@NgModule({
declarations: [AppComponent, NameComponent, AddressListComponent, AddressComponent],
@ -14,6 +15,7 @@ import { AddressComponent } from './address/address.component';
BrowserModule,
RouterModule.forRoot([], { initialNavigation: 'enabled' }),
ReactiveFormsModule,
ContactModule.forRoot(),
],
providers: [],
bootstrap: [AppComponent]

View File

@ -1,5 +1,5 @@
import { FormGroup, FormBuilder, FormControl } from '@angular/forms';
import { Name } from '@nested-forms/contact-model';
import { Name } from '@nested-forms/contact';
import { Component, OnInit, Input } from '@angular/core';
@Component({

View File

@ -107,7 +107,8 @@ module.exports = {
// A path to a custom resolver
// resolver: null,
resolver: '@nrwl/jest/plugins/resolver',
// Automatically restore mock state between every test
// restoreMocks: false,

View File

@ -1,7 +0,0 @@
# contact-model
This library was generated with [Nx](https://nx.dev).
## Running unit tests
Run `ng test contact-model` to execute the unit tests via [Jest](https://jestjs.io).

7
libs/contact/README.md Normal file
View File

@ -0,0 +1,7 @@
# contact
This library was generated with [Nx](https://nx.dev).
## Running unit tests
Run `ng test contact` to execute the unit tests via [Jest](https://jestjs.io).

View File

@ -1,9 +1,9 @@
module.exports = {
name: 'contact-model',
name: 'contact',
preset: '../../jest.config.js',
transform: {
'^.+\\.[tj]sx?$': 'ts-jest'
},
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'html'],
coverageDirectory: '../../coverage/libs/contact-model',
coverageDirectory: '../../coverage/libs/contact',
};

View File

@ -1,2 +1,3 @@
export * from './lib/contact-model';
export * from './lib/contact.service';
export * from './lib/contact.module';

View File

@ -0,0 +1,28 @@
import { NgModule, Optional, SkipSelf } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ContactService } from './contact.service';
@NgModule({
declarations: [],
imports: [
CommonModule
]
})
export class ContactModule {
constructor(
@Optional()
@SkipSelf()
parentModule: ContactModule
) {
if (parentModule) {
throw new Error('ContactModule is already loaded. Import it in the AppModule only');
}
}
static forRoot() {
return {
ngModule: ContactModule,
providers: [ ContactService ]
}
}
}

View File

@ -1,6 +1,6 @@
import { Injectable } from '@angular/core';
import { Contact } from '@nested-forms/contact-model';
import { Contact } from './contact-model';
import { Observable, of } from 'rxjs';
const contact: Contact = {
@ -27,9 +27,7 @@ const contact: Contact = {
],
};
@Injectable({
providedIn: 'root'
})
@Injectable()
export class ContactService {
constructor() { }

View File

@ -8,7 +8,7 @@
"nx.json": "*"
},
"projects": {
"contact-model": {
"contact": {
"tags": []
},
"parent-form-e2e": {

View File

@ -16,7 +16,7 @@
"skipDefaultLibCheck": true,
"baseUrl": ".",
"paths": {
"@nested-forms/contact-model": ["libs/contact-model/src/index.ts"]
"@nested-forms/contact": ["libs/contact/src/index.ts"]
}
},
"exclude": ["node_modules", "tmp"]