Skip to content

Commit bed9970

Browse files
mateusjmafjhosefmarks
authored andcommitted
feat(checkbox): novo componente
Adicionado novo componente Checkbox ao pacote Portinari-UI. Fixes DTHFUI-2397
1 parent a3f74c6 commit bed9970

13 files changed

+685
-2
lines changed

projects/ui/src/lib/components/po-field/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
export * from './po-checkbox/po-checkbox.component';
12
export * from './po-checkbox-group/interfaces/po-checkbox-group-option.interface';
23
export * from './po-checkbox-group/po-checkbox-group.component';
34
export * from './po-combo/po-combo-filter-mode.enum';
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
import { expectPropertiesValues } from '../../../util-test/util-expect.spec';
2+
3+
import { PoCheckboxBaseComponent } from './po-checkbox-base.component';
4+
5+
class PoCheckboxComponent extends PoCheckboxBaseComponent {
6+
protected changeModelValue(value: boolean | null) { }
7+
}
8+
9+
describe('PoCheckboxBaseComponent:', () => {
10+
let component: PoCheckboxBaseComponent;
11+
12+
beforeEach((() => {
13+
component = new PoCheckboxComponent();
14+
component.propagateChange = (value: any) => { };
15+
}));
16+
17+
it('should be created', () => {
18+
component.registerOnChange(() => { });
19+
component.registerOnTouched(() => { });
20+
expect(component instanceof PoCheckboxBaseComponent).toBeTruthy();
21+
});
22+
23+
describe('Properties:', () => {
24+
25+
it('disabled: should update with true value', () => {
26+
const booleanValidTrueValues = [ true, 'true', 1, '' ];
27+
28+
expectPropertiesValues(component, 'disabled', booleanValidTrueValues, true);
29+
});
30+
31+
it('disabled: should update with false value', () => {
32+
const booleanInvalidValues = [ undefined, null, 2, 'string', 0, NaN, false ];
33+
34+
expectPropertiesValues(component, 'disabled', booleanInvalidValues, false);
35+
});
36+
37+
});
38+
39+
describe('Methods:', () => {
40+
41+
it('changeValue: should call `propagateChange` if it is defined and call `change.emit` with `checkboxValue`', () => {
42+
component.checkboxValue = true;
43+
44+
component.propagateChange = () => {};
45+
46+
spyOn(component, 'propagateChange');
47+
spyOn(component.change, 'emit');
48+
49+
component.changeValue();
50+
51+
expect(component.propagateChange).toHaveBeenCalledWith(component.checkboxValue);
52+
expect(component.change.emit).toHaveBeenCalledWith(component.checkboxValue);
53+
});
54+
55+
it('changeValue: should call only `change.emit` with `checkboxValue` if propagateChange is `null`', () => {
56+
component.checkboxValue = true;
57+
component.propagateChange = null;
58+
59+
spyOn(component.change, 'emit');
60+
61+
component.changeValue();
62+
63+
expect(component.change.emit).toHaveBeenCalledWith(component.checkboxValue);
64+
});
65+
66+
it('checkOption: should call `changeModelValue` and `changeValue` if `disabled` is false.', () => {
67+
component.disabled = false;
68+
const spyOnChangeValue = spyOn(component, 'changeValue');
69+
const spyOnChangeModelValue = spyOn(component, <any>'changeModelValue');
70+
71+
component.checkOption(true);
72+
73+
expect(spyOnChangeValue).toHaveBeenCalled();
74+
expect(spyOnChangeModelValue).toHaveBeenCalled();
75+
});
76+
77+
it('checkOption: shouldn`t call `changeModelValue` and `changeValue` if `disabled` is true.', () => {
78+
component.disabled = true;
79+
const spyOnChangeValue = spyOn(component, 'changeValue');
80+
const spyOnChangeModelValue = spyOn(component, <any>'changeModelValue');
81+
82+
component.checkOption(true);
83+
84+
expect(spyOnChangeValue).not.toHaveBeenCalled();
85+
expect(spyOnChangeModelValue).not.toHaveBeenCalled();
86+
});
87+
88+
it('registerOnChange: should set `propagateChange` with value of `fnParam`', () => {
89+
const fnParam = () => {};
90+
91+
component.registerOnChange(fnParam);
92+
93+
expect(component['propagateChange']).toBe(fnParam);
94+
});
95+
96+
it('writeValue: should call `changeModelValue` if value is different from `checkboxValue`', () => {
97+
const valueParam = true;
98+
component.checkboxValue = undefined;
99+
100+
spyOn(component, <any>'changeModelValue');
101+
102+
component.writeValue(valueParam);
103+
104+
expect(component['changeModelValue']).toHaveBeenCalledWith(valueParam);
105+
});
106+
107+
it('writeValue: shouldn`t call `changeModelValue` if value is same as `checkboxValue`', () => {
108+
const valueParam = undefined;
109+
component.checkboxValue = undefined;
110+
111+
spyOn(component, <any>'changeModelValue');
112+
113+
component.writeValue(valueParam);
114+
115+
expect(component['changeModelValue']).not.toHaveBeenCalled();
116+
});
117+
118+
});
119+
120+
});
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import { ControlValueAccessor } from '@angular/forms';
2+
import { EventEmitter, Input, Output } from '@angular/core';
3+
4+
import { convertToBoolean, uuid } from './../../../utils/util';
5+
6+
/**
7+
* @description
8+
*
9+
* O componente `po-checkbox` exibe uma caixa de opção com um texto ao lado, na qual é possível marcar e desmarcar através tanto
10+
* no *click* do *mouse* quanto por meio da tecla *space* quando estiver com foco.
11+
*
12+
* Cada opção poderá receber um estado de marcado, desmarcado, indeterminado e desabilitado, como também uma ação que será disparada quando
13+
* ocorrer mudanças do valor.
14+
*
15+
* > O *model* deste componente aceitará valores igual à `true`, `false` ou `null` para quando for indeterminado.
16+
*/
17+
export abstract class PoCheckboxBaseComponent implements ControlValueAccessor {
18+
19+
checkboxValue: boolean | null;
20+
id = uuid();
21+
propagateChange: any;
22+
23+
private _disabled?: boolean = false;
24+
25+
/** Define o nome do *checkbox*. */
26+
@Input('name') name: string;
27+
28+
/**
29+
* @optional
30+
*
31+
* @description
32+
*
33+
* Define o estado do *checkbox* como desabilitado.
34+
*
35+
* @default `false`
36+
*/
37+
@Input('p-disabled') set disabled(value: boolean) {
38+
this._disabled = convertToBoolean(value);
39+
}
40+
41+
get disabled(): boolean {
42+
return this._disabled;
43+
}
44+
45+
/** Texto de exibição do *checkbox*. */
46+
@Input('p-label') label?: string;
47+
48+
/** Evento disparado quando o valor do *checkbox* for alterado. */
49+
@Output('p-change') change?: EventEmitter<any> = new EventEmitter<any>();
50+
51+
changeValue() {
52+
if (this.propagateChange) {
53+
this.propagateChange(this.checkboxValue);
54+
}
55+
56+
this.change.emit(this.checkboxValue);
57+
}
58+
59+
checkOption(value: boolean | null) {
60+
if (!this.disabled) {
61+
this.changeModelValue(!value);
62+
this.changeValue();
63+
}
64+
}
65+
66+
registerOnChange(fn: any): void {
67+
this.propagateChange = fn;
68+
}
69+
70+
registerOnTouched(fn: any): void { }
71+
72+
writeValue(value: any) {
73+
if (value !== this.checkboxValue) {
74+
this.changeModelValue(value);
75+
}
76+
}
77+
78+
protected abstract changeModelValue(value: boolean | null);
79+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<div class="po-checkbox">
2+
3+
<input
4+
class="po-input po-checkbox-input"
5+
type="checkbox"
6+
[class.po-checkbox-input-checked]="checkboxValue"
7+
[class.po-checkbox-input-indeterminate]="checkboxValue === null"
8+
[checked]="checkboxValue"
9+
[disabled]="disabled"
10+
[id]="id"
11+
[value]="checkboxValue">
12+
13+
<label #checkboxLabel
14+
class="po-checkbox-label"
15+
[class.po-clickable]="!disabled"
16+
[for]="id"
17+
[tabindex]="disabled ? -1 : 0"
18+
(click)="checkOption(checkboxValue)"
19+
(keydown)="onKeyDown($event, checkboxValue)">
20+
{{ label }}
21+
</label>
22+
</div>

0 commit comments

Comments
 (0)