Skip to content

Commit

Permalink
Merge pull request #51 from cloudnc/feat/disabled-input-for-top-level…
Browse files Browse the repository at this point in the history
…-forms

feat(lib): add a `disabled` input for top level form components
  • Loading branch information
zakhenry authored Jun 15, 2019
2 parents 518da9d + 23f1593 commit ad63e2d
Show file tree
Hide file tree
Showing 10 changed files with 61 additions and 35 deletions.
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -163,9 +163,15 @@ Every time the form changes, that component will `emit` a value from the `dataOu
From the parent component you can do like the following:

```html
<app-listing-form [listing]="listing$ | async" (listingUpdated)="upsertListing($event)"></app-listing-form>
<app-listing-form
[disabled]="false"
[listing]="listing$ | async"
(listingUpdated)="upsertListing($event)"
></app-listing-form>
```

_Note the presence of disabled, this is an optional input provided by both `NgxRootFormComponent` and `NgxAutomaticRootFormComponent` that let you disable (or enable when true) the whole form._

Differences between:

- `NgxRootFormComponent`: Will never emit the form value automatically when it changes, to emit the value you'll have to call the method `manualSave` when needed
Expand Down
34 changes: 32 additions & 2 deletions projects/ngx-sub-form/src/lib/ngx-root-form.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,16 @@ const getNewValues = (): Required<Vehicle> => ({

@Component({
template: `
<app-root-form [vehicle]="vehicle$ | async" (vehicleUpdated)="vehicleUpdated($event)"></app-root-form>
<app-root-form
[disabled]="disabled"
[vehicle]="vehicle$ | async"
(vehicleUpdated)="vehicleUpdated($event)"
></app-root-form>
`,
})
class TestWrapperComponent {
public disabled: boolean | null | undefined = false;

public vehicle$: BehaviorSubject<Required<Vehicle>> = new BehaviorSubject(getDefaultValues());

public vehicleUpdated(vehicle: Required<Vehicle>): void {}
Expand All @@ -54,7 +60,7 @@ class RootFormComponent extends NgxRootFormComponent<Vehicle> {
@DataInput()
// tslint:disable-next-line:no-input-rename
@Input('vehicle')
public dataInput: Required<Vehicle> | null = null;
public dataInput: Required<Vehicle> | null | undefined = null;

// tslint:disable-next-line:no-output-rename
@Output('vehicleUpdated')
Expand Down Expand Up @@ -115,4 +121,28 @@ describe(`NgxRootFormComponent`, () => {

expect(vehicleUpdatedSpy).toHaveBeenCalledWith(getNewValues());
});

it(`should be able to disable/enable the form via the "disabled" input`, () => {
expect(componentForm.formGroup.enabled).toBe(true);

component.disabled = true;
componentFixture.detectChanges();
expect(componentForm.formGroup.disabled).toBe(true);

component.disabled = null;
componentFixture.detectChanges();
expect(componentForm.formGroup.enabled).toBe(true);

component.disabled = undefined;
componentFixture.detectChanges();
expect(componentForm.formGroup.enabled).toBe(true);

component.disabled = false;
componentFixture.detectChanges();
expect(componentForm.formGroup.enabled).toBe(true);

component.disabled = true;
componentFixture.detectChanges();
expect(componentForm.formGroup.disabled).toBe(true);
});
});
7 changes: 6 additions & 1 deletion projects/ngx-sub-form/src/lib/ngx-root-form.component.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { EventEmitter, OnInit } from '@angular/core';
import { EventEmitter, OnInit, Input } from '@angular/core';
import isEqual from 'lodash-es/isEqual';
import { BehaviorSubject, Subject } from 'rxjs';
import { filter, tap } from 'rxjs/operators';
Expand All @@ -24,6 +24,11 @@ export abstract class NgxRootFormComponent<ControlInterface, FormInterface = Con
/** @internal */
protected _dataOutput$: Subject<ControlInterface> = new Subject();

@Input()
public set disabled(shouldDisable: boolean | undefined) {
this.setDisabledState(shouldDisable);
}

protected emitInitialValueOnInit = false;
protected emitNullOnDestroy = false;

Expand Down
2 changes: 1 addition & 1 deletion projects/ngx-sub-form/src/lib/ngx-sub-form.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ export abstract class NgxSubFormComponent<ControlInterface, FormInterface = Cont
this.onTouched = fn;
}

public setDisabledState(shouldDisable: boolean): void {
public setDisabledState(shouldDisable: boolean | undefined): void {
if (!this.formGroup) {
return;
}
Expand Down
2 changes: 0 additions & 2 deletions src/app/main/listing/listing-form/listing-form.component.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
<mat-slide-toggle class="readonly" data-readonly [formControl]="readonlyFormControl">Readonly</mat-slide-toggle>

<mat-card>
<mat-card-header>
<mat-card-title data-title [class.not-visible]="!formGroupValues.title">
Expand Down
4 changes: 0 additions & 4 deletions src/app/main/listing/listing-form/listing-form.component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,6 @@ mat-form-field {
width: 100%;
}

.readonly {
padding: 15px 0;
}

.invalid-form {
padding: 15px 0;
}
25 changes: 2 additions & 23 deletions src/app/main/listing/listing-form/listing-form.component.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Component, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core';
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { FormControl, Validators } from '@angular/forms';
import {
Controls,
Expand Down Expand Up @@ -36,8 +36,7 @@ interface OneListingForm {
styleUrls: ['./listing-form.component.scss'],
})
// export class ListingFormComponent extends NgxAutomaticRootFormComponent<OneListing, OneListingForm>
export class ListingFormComponent extends NgxRootFormComponent<OneListing, OneListingForm>
implements OnInit, OnDestroy {
export class ListingFormComponent extends NgxRootFormComponent<OneListing, OneListingForm> {
@DataInput()
// tslint:disable-next-line:no-input-rename
@Input('listing')
Expand All @@ -49,9 +48,6 @@ export class ListingFormComponent extends NgxRootFormComponent<OneListing, OneLi

public ListingType: typeof ListingType = ListingType;

public readonlyFormControl: FormControl = new FormControl(false);
public autoSubmitFormControl: FormControl = new FormControl(false);

// protected handleEmissionRate(): (obs$: Observable<OneListingForm>) => Observable<OneListingForm> {
// return NGX_SUB_FORM_HANDLE_VALUE_CHANGES_RATE_STRATEGIES.debounce(500);
// }
Expand All @@ -68,23 +64,6 @@ export class ListingFormComponent extends NgxRootFormComponent<OneListing, OneLi
};
}

public ngOnInit(): void {
super.ngOnInit();

this.readonlyFormControl.valueChanges
.pipe(
tap((readonly: boolean) => {
if (readonly) {
this.formGroup.disable();
} else {
this.formGroup.enable();
}
}),
takeUntilDestroyed(this),
)
.subscribe();
}

protected transformFromFormGroup(formValue: OneListingForm): OneListing | null {
const { vehicleProduct, droidProduct, listingType, ...commonValues } = formValue;

Expand Down
8 changes: 7 additions & 1 deletion src/app/main/listing/listing.component.html
Original file line number Diff line number Diff line change
@@ -1 +1,7 @@
<app-listing-form [listing]="listing$ | async" (listingUpdated)="upsertListing($event)"></app-listing-form>
<mat-slide-toggle class="readonly" data-readonly [formControl]="readonlyFormControl">Readonly</mat-slide-toggle>

<app-listing-form
[disabled]="readonlyFormControl.value"
[listing]="listing$ | async"
(listingUpdated)="upsertListing($event)"
></app-listing-form>
3 changes: 3 additions & 0 deletions src/app/main/listing/listing.component.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.readonly {
padding: 15px 0;
}
3 changes: 3 additions & 0 deletions src/app/main/listing/listing.component.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Component } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { FormControl } from '@angular/forms';
import { NullableObject } from 'ngx-sub-form';
import { Observable, of } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
Expand All @@ -13,6 +14,8 @@ import { UuidService } from '../../services/uuid.service';
styleUrls: ['./listing.component.scss'],
})
export class ListingComponent {
public readonlyFormControl: FormControl = new FormControl(false);

constructor(
private route: ActivatedRoute,
private listingService: ListingService,
Expand Down

0 comments on commit ad63e2d

Please sign in to comment.