Skip to content

Instantly share code, notes, and snippets.

@sohlich
Last active January 9, 2019 15:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sohlich/59899d8b0b02e79a0a2fb6e5423d2f42 to your computer and use it in GitHub Desktop.
Save sohlich/59899d8b0b02e79a0a2fb6e5423d2f42 to your computer and use it in GitHub Desktop.
<div [formGroup]="form">
<div class="container" formArrayName="optional">
<div class="row">
<div class="col-md">
<div class="buttons pull-right">
<button type="button" *ngIf="!showEdit" class="close" (click)="showEdit = true">
<span aria-hidden="true" class="fa fa-pencil"></span>
</button>
<div class="btn-edit-group">
<button type="button" *ngIf="showEdit" class="close" (click)="confirm($event)">
<i aria-hidden="true" class="fa fa-check"></i>
</button>
<button type="button" *ngIf="showEdit" class="close cancel" (click)="cancel($event)">
<i aria-hidden="true" class="fa fa-times"></i>
</button>
</div>
</div>
</div>
</div>
<div class="features" [ngClass]="{'features-edit': showEdit}">
<div class="row feature" *ngFor="let item of propertyFeatures.controls; let pointIndex=index" [formGroupName]="pointIndex">
<div class="col-md">
<label>
{{features[pointIndex].key | translate }}
</label>
</div>
<div class="col-md">
<span *ngIf="!showEdit">{{features[pointIndex].value}} &nbsp;{{resolvePropertyFeatureUnit(pointIndex)}}</span>
<div *ngIf="showEdit" class="input-group">
<input class="form-control" *ngIf="resolvePropertyFeatureType(pointIndex) === 'integer' " type="number" formControlName="value" />
<input class="form-control" *ngIf="resolvePropertyFeatureType(pointIndex) === 'decimal' " formControlName="value" />
<input class="form-control" *ngIf="resolvePropertyFeatureType(pointIndex) === 'boolean' " type="checkbox" formControlName="value" />
<textarea class="form-control" *ngIf="resolvePropertyFeatureType(pointIndex) === 'text' " formControlName="value"></textarea>
<div class="input-group-append" *ngIf="resolvePropertyFeatureUnit(pointIndex)">
<div class="input-group-text">{{resolvePropertyFeatureUnit(pointIndex)}}</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
export interface Property {
id?: string;
name: string;
address?: Address;
checklist?: Checklist;
features?: PropertyFeature[];
}
export interface Address {
streetNumber?: string;
street?: string;
city?: string;
municipality?: string;
country?: string;
countryCode?: string;
postalCode?: string;
lon?: number;
lat?: number;
}
export interface Checklist {
propertyId: string;
status: string;
ok?: boolean;
type?: string;
}
export interface PropertyFeature {
key: string;
value: string;
}
export interface PropertyFeatureType {
key: string;
note: string;
dataType: string;
unit: string;
}
import { Component, OnInit, Input, Output, EventEmitter, OnDestroy } from '@angular/core';
import { FormGroup, FormArray, FormBuilder } from '@angular/forms';
import { Property, PropertyFeature } from '../../../models/property';
import { ConstantService } from '../../../services/constant.service';
import { Observable, Subscription, timer } from 'rxjs';
import { tap, debounce, last } from 'rxjs/operators';
@Component({
selector: 'ri-property-features',
templateUrl: './property-features.component.html',
styleUrls: ['./property-features.component.scss']
})
export class PropertyFeaturesComponent implements OnInit, OnDestroy {
@Input() property: Observable<Property> = Observable.create({ name: '' });
@Output() valueChange: EventEmitter<any> = new EventEmitter<PropertyFeature[]>();
form: FormGroup;
features: PropertyFeature[] = [];
subs$: Subscription = null;
showEdit = false;
dirtyProperties: PropertyFeature[] = [];
constructor(
public constants: ConstantService,
private _fb: FormBuilder,
) {
this.form = _fb.group({
optional: _fb.array([]),
});
}
ngOnInit() {
this.property.subscribe(property => {
if (!!property.features) {
this.features = property.features;
property.features.forEach(f => {
const arr: FormArray = this.form.get('optional') as FormArray;
const group: FormGroup = this._fb.group({ value: [f.value] });
arr.push(group);
});
}
// Subscribe to changes
this.subs$ = this.form.valueChanges.pipe(
debounce(() => timer(500)),
tap(values => {
const data = values.optional.map((v, i) => {
return {
...this.features[i],
value: v.value,
};
});
this.dirtyProperties = data;
})).subscribe();
});
}
ngOnDestroy() {
if (!!this.subs$) {
this.subs$.unsubscribe();
}
}
get propertyFeatures(): FormArray {
return this.form.get('optional') as FormArray;
}
resolvePropertyFeatureType(index: number): string {
return this.constants.resolvePropertyFeatureType(this.features[index].key);
}
resolvePropertyFeatureUnit(index: number): string {
return this.constants.resolvePropertyFeatureUnit(this.features[index].key);
}
cancel() {
this.form = this._fb.group({
optional: this._fb.array([]),
});
this.features.forEach(f => {
const arr: FormArray = this.form.get('optional') as FormArray;
const group: FormGroup = this._fb.group({ value: [f.value] });
arr.push(group);
});
this.showEdit = false;
}
confirm() {
this.valueChange.emit(this.dirtyProperties);
this.features = this.dirtyProperties;
this.showEdit = false;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment