Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into fb-RFDAP-1136-custo…
Browse files Browse the repository at this point in the history
…m-buttons-bar
  • Loading branch information
igortg committed Sep 26, 2018
2 parents 01a048b + 77dfe4c commit a382def
Show file tree
Hide file tree
Showing 17 changed files with 293 additions and 8 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
<a name="0.19.0"></a>
# [0.19.0](https://github.com/ESSS/ng-xform/compare/v0.18.0...v0.19.0) (2018-09-20)


### Features

* **NgXform:** validate all fields on submit ([#34](https://github.com/ESSS/ng-xform/issues/34)) ([4067c28](https://github.com/ESSS/ng-xform/commit/4067c28)), closes [#35](https://github.com/ESSS/ng-xform/issues/35) [#36](https://github.com/ESSS/ng-xform/issues/36)



<a name="0.18.0"></a>
# [0.18.0](https://github.com/ESSS/ng-xform/compare/v0.17.0...v0.18.0) (2018-08-21)

Expand Down
15 changes: 14 additions & 1 deletion demo/src/app/home/home.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Title } from '@angular/platform-browser';
import {
CheckboxField,
DateField,
DateRangeField,
DynamicField,
MeasureField,
MultilineField,
Expand All @@ -18,6 +19,7 @@ import {
import { Observable, of } from 'rxjs';
import { delay, map } from 'rxjs/operators';


@Component({
selector: 'app-home',
templateUrl: './home.component.html',
Expand Down Expand Up @@ -99,6 +101,7 @@ export class HomeComponent implements OnInit {
label: 'Street',
searchHandler: this.observableSource.bind(this),
searchByValueKeyHandler: this.observableSourceByPlaceId.bind(this),
searchOnFocus: true,
searchable: true,
optionLabelKey: 'formatted_address',
optionValueKey: 'place_id',
Expand Down Expand Up @@ -161,6 +164,11 @@ export class HomeComponent implements OnInit {
minDate: minDate,
maxDate: maxDate
}),
new DateRangeField({
key: 'range',
label: 'Date range',
theme: 'blue'
}),
new CustomField({
key: 'custom_amount',
label: 'Custom Field Amount',
Expand Down Expand Up @@ -195,12 +203,17 @@ export class HomeComponent implements OnInit {
'vel viverra nisi. Mauris aliquet nunc non turpis scelerisque, eget. Casamentiss faiz malandris se pirulitá. Sapien in monti ' +
'palavris qui num significa nadis i pareci latim.',
birth: new Date(),
range: [
'2018-09-06T03:00:00.000Z',
'2018-10-08T03:00:00.000Z'
],
custom_amount: 456
});
}

public observableSource(keyword: any): Observable<any[]> {
const url = `https://maps.googleapis.com/maps/api/geocode/json?address=${keyword}`;
const apiKey = 'AIzaSyB4Hm7LBQ4482DJC5PoHv37UkRBmT4gNFU';
const url = `https://maps.googleapis.com/maps/api/geocode/json?key=${apiKey}&address=${keyword}`;
if (keyword) {
return this.http.get(url)
.pipe(map((res) => res['results']));
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@esss/ng-xform",
"description": "Angular lib",
"version": "0.18.0",
"version": "0.19.0",
"homepage": "https://github.com/ESSS/ng-xform",
"author": {
"name": "Eder Soares",
Expand Down
7 changes: 5 additions & 2 deletions src/ng-xform/date-field/date-field.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ export class DateFieldComponent extends BaseDynamicFieldComponent<DateField> imp

ngAfterContentInit() {
this.componentControl.setValidators(this.field.validators);
this.config = Object.assign({}, {
this.config = {
containerClass: `theme-${this.field.theme}`,
});
};
}

ngAfterViewInit() {
Expand All @@ -63,12 +63,15 @@ export class DateFieldComponent extends BaseDynamicFieldComponent<DateField> imp
this.componentControl.setValue(obj);
}
}

registerOnChange(fn: any): void {
this._onChange = fn;
}

registerOnTouched(fn: any): void {
this._onTouched = fn;
}

setDisabledState?(isDisabled: boolean): void {
this.input.disabled = isDisabled;
}
Expand Down
8 changes: 8 additions & 0 deletions src/ng-xform/date-range-field/date-range-field.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<ng-xform-form-control-layout [fieldComponent]="instance">
<input bsDaterangepicker type="text" class="form-control" [formControl]="componentControl" id="{{elementId}}"
[bsConfig]="config"
[bsValue]="field.initialValue"
[placement]="field.placement"
[maxDate]="field.maxDate"
[minDate]="field.minDate" />
</ng-xform-form-control-layout>
127 changes: 127 additions & 0 deletions src/ng-xform/date-range-field/date-range-field.component.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import { CommonModule } from '@angular/common';
import { Component, ViewChild } from '@angular/core';
import { ComponentFixture, fakeAsync, TestBed } from '@angular/core/testing';
import { FormControl, FormsModule, ReactiveFormsModule } from '@angular/forms';
import { BsDatepickerModule } from 'ngx-bootstrap/datepicker';

import { tickAndDetectChanges } from '../../testing/helpers';
import { OptionalTagComponent } from '../field-components/optional-tag.component';
import { ErrorMessagePipe } from '../field-error-message/error-message.pipe';
import { FieldErrorMessageComponent } from '../field-error-message/field-error-message.component';
import { DateRangeField } from '../fields';
import { FormControlLayoutComponent } from '../form-control-layout/form-control-layout.component';
import { NgXformGroup } from '../ng-xform-group';
import { DateRangeFieldComponent } from './date-range-field.component';


describe('DateRangeFieldComponent', () => {
it('should create DateRangeField', () => {
const fixture = createTestingModule(`
<ng-xform-date-range-field [field]="field" [form]="form">
</ng-xform-date-range-field>
`);

expect(fixture.componentInstance).toBeTruthy();
});

it('should patch value to DateRangeField', fakeAsync(() => {
const fixture = createTestingModule(`
<form [formGroup]="form">
<ng-xform-date-range-field [field]="field"
[formControlName]="field.key"
[form]="form"
[(ngModel)]="dateValue">
</ng-xform-date-range-field>
</form>
`);
tickAndDetectChanges(fixture);
const dateRangeField: DateRangeFieldTestComponent = fixture.componentInstance;

expect(dateRangeField.dateValue).toBe(undefined);
expect(dateRangeField.dateRangeField.componentControl.value).toBe(undefined);

const changeTo = [new Date(2018, 1, 28, 0, 0, 0), new Date(2018, 1, 28, 0, 0, 0)];
dateRangeField.form.patchValue({date: changeTo});
tickAndDetectChanges(fixture);

expect(dateRangeField.dateRangeField.componentControl.value[0].toISOString()).toBe(changeTo[0].toISOString());
expect(dateRangeField.dateRangeField.componentControl.value[1].toISOString()).toBe(changeTo[1].toISOString());

}));

it('should be set to null when form resets ', fakeAsync(() => {
const fixture = createTestingModule(`
<form [formGroup]="form">
<ng-xform-date-range-field [field]="field"
[formControlName]="field.key"
[form]="form"
[(ngModel)]="dateValue">
</ng-xform-date-range-field>
</form>
`);
tickAndDetectChanges(fixture);
const dateRangeField: DateRangeFieldTestComponent = fixture.componentInstance;

const changeTo = [new Date(2018, 1, 28, 0, 0, 0), new Date(2018, 1, 28, 0, 0, 0)];

dateRangeField.form.patchValue({date: changeTo});
tickAndDetectChanges(fixture);

expect(dateRangeField.dateRangeField.componentControl.value[0].toISOString()).toBe(changeTo[0].toISOString());
expect(dateRangeField.dateRangeField.componentControl.value[1].toISOString()).toBe(changeTo[1].toISOString());


dateRangeField.form.reset();
tickAndDetectChanges(fixture);

expect(dateRangeField.dateValue).toBe(null);
expect(dateRangeField.dateRangeField.componentControl.value).toBe(null);

}));

});

function createTestingModule( template: string): ComponentFixture<any> {
TestBed.configureTestingModule({
imports: [
FormsModule,
ReactiveFormsModule,
CommonModule,
BsDatepickerModule.forRoot(),
],
declarations: [
DateRangeFieldTestComponent,
DateRangeFieldComponent,
FormControlLayoutComponent,
FieldErrorMessageComponent,
OptionalTagComponent,
ErrorMessagePipe,
]
}).overrideComponent(DateRangeFieldTestComponent, {
set: {
template: template
}
}).compileComponents();

const fixture = TestBed.createComponent(DateRangeFieldTestComponent);
fixture.detectChanges();

return fixture;
}


@Component({
template: ``,
})
class DateRangeFieldTestComponent {
@ViewChild(DateRangeFieldComponent) dateRangeField: DateRangeFieldComponent;

field = new DateRangeField({
key: 'date',
label: 'Date',
});

form = new NgXformGroup({date: new FormControl()});

dateValue: Date;
}
88 changes: 88 additions & 0 deletions src/ng-xform/date-range-field/date-range-field.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { DateRangeField } from './../fields/date-range-field';
import { DatePipe } from '@angular/common';
import { ControlValueAccessor, FormControl, NG_VALUE_ACCESSOR } from '@angular/forms';
import { Component, AfterContentInit, ElementRef, AfterViewInit, Inject, LOCALE_ID } from '@angular/core';
import { BsDatepickerConfig } from 'ngx-bootstrap/datepicker';

import { BaseDynamicFieldComponent } from '../field-components/base-dynamic-field.component';
import { DateField } from '../fields';

/**
* Component to generate a bootstrap form field of Date type
*
* :editing: Flag to control component state
* :form: FormGroup containing the field
* :field: Intance of field configurations
*/
@Component({
selector: 'ng-xform-date-range-field',
templateUrl: './date-range-field.component.html',
providers: [{
provide: NG_VALUE_ACCESSOR,
useExisting: DateRangeFieldComponent,
multi: true
}],
})
export class DateRangeFieldComponent extends BaseDynamicFieldComponent<DateRangeField> implements AfterViewInit, AfterContentInit,
ControlValueAccessor {
config: Partial<BsDatepickerConfig>;
componentControl = new FormControl();
private input: HTMLInputElement;

_onChange = (value: any) => { };
_onTouched = () => { };

// the elementRef will be used to get the input element after the view is initialized.
constructor(private elementRef: ElementRef, @Inject(LOCALE_ID) private locale: string) {
super();
this.componentControl.valueChanges.subscribe((val: any) => {
// replay changes from view to the form value
this._onChange(val);
});
}

ngAfterContentInit() {
this.componentControl.setValidators(this.field.validators);
this.config = {
containerClass: `theme-${this.field.theme}`,
};
}

ngAfterViewInit() {
this.input = this.elementRef.nativeElement.querySelector('input');
if (this.input) {
this.input.onblur = this._onTouched
}
}

writeValue(obj: any): void {
if (obj instanceof Array) {
this.componentControl.setValue(obj.map(item => new Date(item)));
} else {
this.componentControl.setValue(obj);
}
}

registerOnChange(fn: any): void {
this._onChange = fn;
}

registerOnTouched(fn: any): void {
this._onTouched = fn;
}

setDisabledState?(isDisabled: boolean): void {
this.input.disabled = isDisabled;
}

get formattedValue(): string {
const dateFormatter = new DatePipe(this.field.locale || this.locale);
if (!this.form.controls[this.elementId].value) {
return '-';
}
const start = dateFormatter.transform(this.form.controls[this.elementId].value[0], 'mediumDate');
const end = dateFormatter.transform(this.form.controls[this.elementId].value[1], 'mediumDate');
return `${start} - ${end}`;
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<div class="help-block" *ngIf="control && control.invalid && control.touched">
<div *ngIf="control.errors">
<div *ngIf="control.errors" class="alert alert-danger" role="alert" style="padding: 5px;">
{{ control.errors | errorMessage }}
</div>
</div>
9 changes: 9 additions & 0 deletions src/ng-xform/fields/date-range-field.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { DateField } from './date-field';

export class DateRangeField extends DateField {
public controlType ? = 'DATERANGE';

constructor(options: DateRangeField) {
super(options);
}
}
1 change: 1 addition & 0 deletions src/ng-xform/fields/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ export * from './radiogroup-field';
export * from './multiline-field';
export * from './nested-form-group';
export * from './date-field';
export * from './date-range-field';
2 changes: 2 additions & 0 deletions src/ng-xform/fields/select-field.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export class SelectField<T = any> extends DynamicField<T> {
public optionLabelKey?: string;
public searchHandler?: (value: string) => Observable<any[]>;
public searchByValueKeyHandler?: (value: string) => Observable<any>;
public searchOnFocus?: boolean;
public searchable?: boolean;
public markFirst?: boolean;
public separator?: string;
Expand All @@ -28,6 +29,7 @@ export class SelectField<T = any> extends DynamicField<T> {
this.optionLabelKey = options.optionLabelKey;
this.searchable = options.searchable === true;
this.searchHandler = options.searchHandler;
this.searchOnFocus = options.searchOnFocus || false;
this.searchByValueKeyHandler = options.searchByValueKeyHandler;
this.markFirst = options.markFirst === true;
this.separator = options.separator || ', ';
Expand Down
3 changes: 3 additions & 0 deletions src/ng-xform/form-group/form-group.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ <h4 *ngIf='field.label'>
<ng-xform-date-field *ngSwitchCase="'DATE'" [labelWidth]="labelWidth" [isHorizontal]="isHorizontal" [field]="field" [form]="form" [formControlName]="field.key" [editing]="editing !== false">
</ng-xform-date-field>

<ng-xform-date-range-field *ngSwitchCase="'DATERANGE'" [labelWidth]="labelWidth" [isHorizontal]="isHorizontal" [field]="field" [form]="form" [formControlName]="field.key" [editing]="editing !== false">
</ng-xform-date-range-field>

<pre *ngSwitchDefault>{{ field | json}}</pre>
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/ng-xform/ng-xform.component.html
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
<form [formGroup]="form" [class.form-horizontal]="horizontalForm">
<ng-xform-form-group [isHorizontal]="horizontalForm" [labelWidth]="labelWidth" [fields]='fields' [form]=form [editing]='editing'></ng-xform-form-group>
</form>
</form>

0 comments on commit a382def

Please sign in to comment.