/
abstract-dorf-field.component.ts
95 lines (87 loc) · 3.18 KB
/
abstract-dorf-field.component.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
import { Input } from '@angular/core';
import { FormControl } from '@angular/forms';
import { DorfFieldMetadata } from './abstract-dorf-field.metadata';
import { DorfNestedMetadata } from './dorf-nested.metadata';
import { IDorfFieldDefinition } from './abstract-dorf-field.definition';
import { IDorfCommonCssClasses, DorfCssClasses } from '../../base/dorf-css-classes';
import { DorfConfigService } from '../../dorf-config.service';
/**
* Base for each DORF field.
* `@Component()` annotation should be set on the subclass level and then no more annotations should be presented
* (e.g. no `@Input()` or `@Output()` on properties).
* If there is no way to go without additional annotations in subclass, `metadata` should be listed directly
* in the subclass once again, with the corresponding `@Input` annotation.
*
* @example
* ```
*
* //
* @Component({
* moduleId: module.id,
* selector: "star",
* styleUrls: ["star-rating.component.css"],
* templateUrl: "star-rating.component.html"
* })
* export class StarRatingComponent<T> extends AbstractDorfFieldComponent<T, StarRatingMetadata<T>> implements IStarRatingDefinition<T> {
*
* constructor(config: DorfConfigService) {
* super(config);
* }
*
* setValue(val: number) {
* this.formControl.setValue(val + 1);
* }
*
* get max() { return this.metadata.max; }
*
* get stars() { return new Array(this.max); }
* get value() { return this.formControl.value; }
* }
* ```
*
* @stable
*/
// TODO: decorator which adds the same behavior as this class/DorfField factory method
export abstract class AbstractDorfFieldComponent<T, M extends DorfFieldMetadata<T, IDorfFieldDefinition<T>>> {
/**
* Essence, needed by DORF field.
*/
@Input()
metadata: M;
/**
* Cache to simplify getter logic.
*/
private _labelCss: string;
/**
* @param config {DorfConfigService} injected [service]{@link DorfConfigService}
*/
constructor(public config: DorfConfigService) { }
get key() { return this.metadata.key; }
get label() { return this.metadata.label; }
get htmlFieldCss() { return this.getCss('htmlField'); }
get labelCss() {
if (!this._labelCss) {
this._labelCss = '';
if (this.config.requiredWithStar && this.metadata.isRequired) {
this._labelCss = 'dorf-required';
}
let labelClasses = this.getCss('label');
if (labelClasses) {
this._labelCss = `${labelClasses} ${this._labelCss}`;
}
}
return this._labelCss;
}
// TODO: is there a way for `touch`? FormControl.markAsTouched is triggered on blur on elemenent with formControl directive
get invalid() { return this.metadata.invalid; }
get formControl() { return this.metadata.formControl; }
protected getCss(cssClass: string) {
let result = this.metadata.getCss(cssClass);
if (this.metadata.parentCss) {
result = result || this.config.getCssClassForNestedTag(this.metadata.tag, cssClass);
} else {
result = result || this.config.getCssClassForTag(this.metadata.tag, cssClass);
}
return result;
}
}