Skip to content

Commit 1b7444c

Browse files
Samir Hassan Ayoubrafaellygruber
authored andcommitted
feat(rich-text): adiciona eventos de mudança de valores
Definidas propriedades relacionadas aos eventos change e changeModel. Fixes DTHFUI-1719
1 parent 881d7b1 commit 1b7444c

File tree

9 files changed

+136
-2
lines changed

9 files changed

+136
-2
lines changed

projects/ui/src/lib/components/po-field/po-rich-text/po-rich-text-base.component.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { AbstractControl, ControlValueAccessor, Validator } from '@angular/forms';
2-
import { Input } from '@angular/core';
2+
import { EventEmitter, Input, Output } from '@angular/core';
33

44
import { convertToBoolean } from '../../../utils/util';
55
import { requiredFailed } from '../validators';
@@ -139,6 +139,12 @@ export abstract class PoRichTextBaseComponent implements ControlValueAccessor, V
139139
return this._required;
140140
}
141141

142+
/** Evento disparado ao deixar o campo e que recebe como parâmetro o valor alterado. */
143+
@Output('p-change') change?: EventEmitter<any> = new EventEmitter();
144+
145+
/** Evento disparado ao modificar valor do model e que recebe como parâmetro o valor alterado. */
146+
@Output('p-change-model') changeModel?: EventEmitter<any> = new EventEmitter();
147+
142148
// Função implementada do ControlValueAccessor
143149
// Usada para interceptar as mudanças e não atualizar automaticamente o Model
144150
registerOnChange(func: any): void {

projects/ui/src/lib/components/po-field/po-rich-text/po-rich-text-body/po-rich-text-body.component.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@
33
[attr.contenteditable]="!readonly"
44
[attr.data-placeholder]="placeholder"
55
[style.height.px]="height"
6+
(blur)="onBlur()"
67
(click)="onClick()"
78
(cut)="update()"
9+
(focus)="onFocus()"
810
(keyup)="onKeyUp()"
911
(paste)="update()">
1012
</div>

projects/ui/src/lib/components/po-field/po-rich-text/po-rich-text-body/po-rich-text-body.component.spec.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,54 @@ describe('PoRichTextBodyComponent:', () => {
162162
expect(component.bodyElement.nativeElement.insertAdjacentHTML).toHaveBeenCalledWith('afterbegin', component.modelValue);
163163
});
164164

165+
it('onFocus: should set a value to `valueBeforeChange`', () => {
166+
component.modelValue = 'value';
167+
168+
component.onFocus();
169+
170+
expect(component['valueBeforeChange']).toBe('value');
171+
});
172+
173+
it('onBlur: should emit modelValue change', fakeAsync((): void => {
174+
const fakeThis = {
175+
modelValue: 'value',
176+
valueBeforeChange: '1',
177+
change: component.change,
178+
bodyElement: {
179+
nativeElement: {
180+
innerHTML: 'value'
181+
}
182+
}
183+
};
184+
185+
spyOn(fakeThis.change, 'emit');
186+
component.onBlur.call(fakeThis);
187+
tick(250);
188+
189+
expect(fakeThis.change.emit).toHaveBeenCalledWith(fakeThis.modelValue);
190+
}));
191+
192+
it('onBlur: shouldn`t emit change value doesn`t changed', fakeAsync((): void => {
193+
const fakeThis = {
194+
modelValue: 'value',
195+
valueBeforeChange: 'value',
196+
change: {
197+
emit: () => {}
198+
},
199+
bodyElement: {
200+
nativeElement: {
201+
innerHTML: 'value'
202+
}
203+
}
204+
};
205+
206+
spyOn(fakeThis.change, 'emit');
207+
component.onBlur.call(fakeThis);
208+
tick(250);
209+
210+
expect(fakeThis.change.emit).not.toHaveBeenCalled();
211+
}));
212+
165213
});
166214

167215
describe('Templates: ', () => {

projects/ui/src/lib/components/po-field/po-rich-text/po-rich-text-body/po-rich-text-body.component.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ const poRichTextBodyCommands = [
1010
})
1111
export class PoRichTextBodyComponent implements OnInit {
1212

13+
private timeoutChange: any;
14+
private valueBeforeChange: any;
15+
1316
@ViewChild('bodyElement', { static: true }) bodyElement: ElementRef;
1417

1518
@Input('p-height') height?: string;
@@ -20,6 +23,8 @@ export class PoRichTextBodyComponent implements OnInit {
2023

2124
@Input('p-readonly') readonly?: string;
2225

26+
@Output('p-change') change = new EventEmitter<any>();
27+
2328
@Output('p-commands') commands = new EventEmitter<any>();
2429

2530
@Output('p-value') value = new EventEmitter<any>();
@@ -38,10 +43,23 @@ export class PoRichTextBodyComponent implements OnInit {
3843
this.value.emit(this.modelValue);
3944
}
4045

46+
onBlur() {
47+
if (this.modelValue !== this.valueBeforeChange) {
48+
clearTimeout(this.timeoutChange);
49+
this.timeoutChange = setTimeout(() => {
50+
this.change.emit(this.modelValue);
51+
}, 200);
52+
}
53+
}
54+
4155
onClick() {
4256
this.emitSelectionCommands();
4357
}
4458

59+
onFocus() {
60+
this.valueBeforeChange = this.modelValue;
61+
}
62+
4563
onKeyUp() {
4664
// Tratamento necessário para eliminar a tag <br> criada no firefox quando o body for limpo.
4765
const bodyElement = this.bodyElement.nativeElement;

projects/ui/src/lib/components/po-field/po-rich-text/po-rich-text.component.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
[p-model-value]="value"
1111
[p-placeholder]="placeholder"
1212
[p-readonly]="readonly"
13+
(p-change)="onChangeValue($event)"
1314
(p-commands)="richTextToolbar.setButtonsStates($event)"
1415
(p-value)="updateValue($event)">
1516
</po-rich-text-body>

projects/ui/src/lib/components/po-field/po-rich-text/po-rich-text.component.spec.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,12 +128,14 @@ describe('PoRichTextComponent:', () => {
128128

129129
it('updateValue: should apply values to value, invalid and call updateModel', () => {
130130
spyOn(component, <any>'updateModel');
131+
spyOn(component, <any>'controlChangeModelEmitter');
131132

132133
component.updateValue('value');
133134

134135
expect(component.value).toBe('value');
135136
expect(component.invalid).toBeFalsy();
136137
expect(component['updateModel']).toHaveBeenCalledWith(component.value);
138+
expect(component['controlChangeModelEmitter']).toHaveBeenCalledWith(component.value);
137139
});
138140

139141
it('validateClassesForRequired: should add ng-invalid and dirty classes if value is null and is required', fakeAsync(() => {
@@ -167,5 +169,36 @@ describe('PoRichTextComponent:', () => {
167169

168170
expect(nativeElement.classList).not.toContain('ng-invalid');
169171
}));
172+
173+
it('onChangeValue: should emit change', () => {
174+
spyOn(component.change, 'emit');
175+
176+
component.onChangeValue('value');
177+
178+
expect(component.change.emit).toHaveBeenCalledWith('value');
179+
});
180+
181+
it('controlChangeModelEmitter: should emit changeModel and set modelLastUpdate value', () => {
182+
const value = 'value';
183+
component['modelLastUpdate'] = '1';
184+
185+
spyOn(component.changeModel, 'emit');
186+
187+
component['controlChangeModelEmitter'](value);
188+
189+
expect(component.changeModel.emit).toHaveBeenCalledWith(value);
190+
expect(component['modelLastUpdate']).toBe(value);
191+
});
192+
193+
it('controlChangeModelEmitter: shouldn`t emit changeModel if modelLastValue and value have same value', () => {
194+
const value = 'value';
195+
component['modelLastUpdate'] = 'value';
196+
197+
spyOn(component.changeModel, 'emit');
198+
199+
component['controlChangeModelEmitter'](value);
200+
201+
expect(component.changeModel.emit).not.toHaveBeenCalled();
202+
});
170203
});
171204
});

projects/ui/src/lib/components/po-field/po-rich-text/po-rich-text.component.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ import { PoRichTextBaseComponent } from './po-rich-text-base.component';
4242
export class PoRichTextComponent extends PoRichTextBaseComponent implements AfterViewInit, OnDestroy {
4343

4444
private listener = this.validateClassesForRequired.bind(this);
45+
private modelLastUpdate: any;
4546

4647
get errorMsg() {
4748
return (this.errorMessage !== '' && !this.value && this.required && this.invalid) ? this.errorMessage : '';
@@ -68,12 +69,24 @@ export class PoRichTextComponent extends PoRichTextBaseComponent implements Afte
6869
}
6970
}
7071

72+
onChangeValue(value: any) {
73+
this.change.emit(value);
74+
}
75+
7176
updateValue(value: string) {
7277
this.value = value;
7378
this.invalid = !value;
79+
this.controlChangeModelEmitter(this.value);
7480
this.updateModel(this.value);
7581
}
7682

83+
private controlChangeModelEmitter(value: any) {
84+
if (this.modelLastUpdate !== value) {
85+
this.changeModel.emit(value);
86+
this.modelLastUpdate = value;
87+
}
88+
}
89+
7790
private validateClassesForRequired() {
7891
setTimeout(() => {
7992
const value = this.value;

projects/ui/src/lib/components/po-field/po-rich-text/samples/sample-po-rich-text-labs/sample-po-rich-text-labs.component.html

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@
88
[p-optional]="properties.includes('optional')"
99
[p-placeholder]="placeholder"
1010
[p-readonly]="properties.includes('readonly')"
11-
[p-required]="properties.includes('required')">
11+
[p-required]="properties.includes('required')"
12+
(p-change)="changeEvent('p-change')"
13+
(p-change-model)="changeEvent('p-change-model')">
1214
</po-rich-text>
1315

1416
<po-divider></po-divider>
@@ -19,6 +21,12 @@
1921
p-label="Model"
2022
[p-value]="richText">
2123
</po-info>
24+
25+
<po-info
26+
class="po-md-6"
27+
p-label="Event"
28+
[p-value]="event">
29+
</po-info>
2230
</div>
2331

2432
<po-divider p-label="Properties"></po-divider>

projects/ui/src/lib/components/po-field/po-rich-text/samples/sample-po-rich-text-labs/sample-po-rich-text-labs.component.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { PoCheckboxGroupOption } from '@portinari/portinari-ui';
88
})
99
export class SamplePoRichTextLabsComponent implements OnInit {
1010
errorMessage: string;
11+
event: string;
1112
help: string;
1213
height: number;
1314
label: string;
@@ -25,6 +26,10 @@ export class SamplePoRichTextLabsComponent implements OnInit {
2526
this.restore();
2627
}
2728

29+
changeEvent(event: string) {
30+
this.event = event;
31+
}
32+
2833
restore() {
2934
this.errorMessage = '';
3035
this.help = '';

0 commit comments

Comments
 (0)