Skip to content

Commit 0ab2c2f

Browse files
committed
SVY-20863 Using a Format on a Field is causing Odd Behavior on New
1 parent 0d5e30e commit 0ab2c2f

1 file changed

Lines changed: 113 additions & 101 deletions

File tree

  • components/projects/bootstrapcomponents/src/textbox

components/projects/bootstrapcomponents/src/textbox/textbox.ts

Lines changed: 113 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -4,116 +4,128 @@ import { Format, FormatDirective, WindowRefService } from '@servoy/public';
44
import { ServoyBootstrapBasefield } from '../bts_basefield';
55

66
@Component({
7-
selector: 'bootstrapcomponents-textbox',
8-
templateUrl: './textbox.html',
9-
changeDetection: ChangeDetectionStrategy.OnPush,
10-
standalone: false
7+
selector: 'bootstrapcomponents-textbox',
8+
templateUrl: './textbox.html',
9+
changeDetection: ChangeDetectionStrategy.OnPush,
10+
standalone: false
1111
})
1212
export class ServoyBootstrapTextbox extends ServoyBootstrapBasefield<HTMLInputElement> {
1313

14-
readonly format = input<Format>(undefined);
15-
readonly inputType = input<string>(undefined);
16-
readonly autocomplete = input<string>(undefined);
17-
readonly styleClassForEye = input<string>(undefined);
18-
19-
readonly inputTypeChange = output<string>();
20-
21-
readonly svyFormat = viewChild(FormatDirective);
22-
23-
protected _inputType = signal<string>(undefined);
24-
protected _autocomplete = signal<string>(undefined);
25-
26-
showPass = false;
27-
classForEye = '';
28-
29-
constructor(renderer: Renderer2, cdRef: ChangeDetectorRef, @Inject(DOCUMENT) doc: Document, protected windowService: WindowRefService) {
30-
super(renderer, cdRef, doc);
31-
}
32-
33-
svyOnInit() {
34-
super.svyOnInit();
35-
this._autocomplete.set(this.autocomplete());
36-
this._inputType.set(this.inputType());
37-
if(this.autocomplete() === 'off') {
38-
this._autocomplete.set(this.windowService.nativeWindow.navigator.userAgent.match(/chrome/i) ? 'chrome-off' : 'off');
39-
}
40-
if (this.onActionMethodID()) {
41-
this.renderer.listen(this.getFocusElement(), 'click', e => {
42-
if (this._editable() === false) {
43-
this.onActionMethodID()(e);
44-
}
45-
});
46-
}
47-
}
48-
49-
svyOnChanges(changes: SimpleChanges) {
50-
super.svyOnChanges(changes);
51-
if (changes.inputType) {
52-
this.setInputType(this.inputType());
53-
}
54-
if (changes.styleClassForEye) {
14+
readonly format = input<Format>(undefined);
15+
readonly inputType = input<string>(undefined);
16+
readonly autocomplete = input<string>(undefined);
17+
readonly styleClassForEye = input<string>(undefined);
18+
19+
readonly inputTypeChange = output<string>();
20+
21+
readonly svyFormat = viewChild(FormatDirective);
22+
23+
protected _inputType = signal<string>(undefined);
24+
protected _autocomplete = signal<string>(undefined);
25+
26+
showPass = false;
27+
classForEye = '';
28+
29+
constructor(renderer: Renderer2, cdRef: ChangeDetectorRef, @Inject(DOCUMENT) doc: Document, protected windowService: WindowRefService) {
30+
super(renderer, cdRef, doc);
31+
}
32+
33+
svyOnInit() {
34+
super.svyOnInit();
35+
this._autocomplete.set(this.autocomplete());
36+
this._inputType.set(this.inputType());
37+
if (this.autocomplete() === 'off') {
38+
this._autocomplete.set(this.windowService.nativeWindow.navigator.userAgent.match(/chrome/i) ? 'chrome-off' : 'off');
39+
}
40+
if (this.onActionMethodID()) {
41+
this.renderer.listen(this.getFocusElement(), 'click', e => {
42+
if (this._editable() === false) {
43+
this.onActionMethodID()(e);
44+
}
45+
});
46+
}
47+
}
48+
49+
svyOnChanges(changes: SimpleChanges) {
50+
super.svyOnChanges(changes);
51+
if (changes.inputType) {
52+
this.setInputType(this.inputType());
53+
}
54+
if (changes.styleClassForEye) {
5555
this.addClassForEye();
5656
}
57-
}
58-
59-
onModelChange(newValue) {
60-
// if format or invalid date, force dataprovider display with formated value / invalid date text
61-
if(this.format() || (newValue && typeof newValue.getTime === 'function' && isNaN(newValue.getTime()))) {
62-
this.svyFormat().writeValue(newValue);
63-
}
64-
this._dataProviderID.set(newValue);
65-
66-
if (this.isDateType()) {
57+
}
58+
59+
onModelChange(newValue) {
60+
// if format or invalid date, force dataprovider display with formated value / invalid date text
61+
if (this.format() || (newValue && typeof newValue.getTime === 'function' && isNaN(newValue.getTime()))) {
62+
this.svyFormat().writeValue(newValue);
63+
}
64+
this._dataProviderID.set(newValue);
65+
66+
if (this.isDateType()) {
6767
this.pushUpdate();
6868
}
69-
}
70-
71-
setInputType(inputType: string) {
72-
const types = ['text', 'password', 'password-with-eye', 'email', 'tel', 'date', 'time', 'datetime-local', 'month', 'week', 'number', 'color', 'search', 'url'];
73-
74-
if (types.indexOf(inputType) > -1) {
75-
const inputTypeValue = this._inputType();
76-
if (inputTypeValue !== inputType) {
77-
this._inputType.set(inputType);
78-
this.inputTypeChange.emit(inputType);
79-
}
80-
const dp = this._dataProviderID();
81-
if (dp) {
82-
this.svyFormat().writeValue(dp);
83-
}
84-
return true;
85-
} else {
86-
return false;
87-
}
88-
}
89-
90-
showHidePass() {
91-
this.showPass = !this.showPass;
92-
this.addClassForEye();
93-
}
94-
95-
private addClassForEye() {
96-
let [mainClass, openClass, closeClass] = ['fa', 'fa-eye', 'fa-eye-slash'];
97-
const styleClassForEye = this.styleClassForEye();
98-
if (styleClassForEye) {
99-
const classes = styleClassForEye.split(' ');
100-
if (classes.length === 3) {
101-
[mainClass, openClass, closeClass] = classes;
102-
} else if (classes.length === 2) {
103-
mainClass = '';
104-
[openClass, closeClass] = classes;
105-
}
106-
}
107-
108-
this.classForEye = mainClass + ' ' + closeClass;
109-
110-
if (this.showPass) {
111-
this.classForEye = mainClass + ' ' + openClass;
112-
}
113-
}
114-
69+
}
70+
71+
setInputType(inputType: string) {
72+
const types = ['text', 'password', 'password-with-eye', 'email', 'tel', 'date', 'time', 'datetime-local', 'month', 'week', 'number', 'color', 'search', 'url'];
73+
74+
if (types.indexOf(inputType) > -1) {
75+
const inputTypeValue = this._inputType();
76+
if (inputTypeValue !== inputType) {
77+
this._inputType.set(inputType);
78+
this.inputTypeChange.emit(inputType);
79+
}
80+
const dp = this._dataProviderID();
81+
if (dp) {
82+
this.svyFormat().writeValue(dp);
83+
}
84+
return true;
85+
} else {
86+
return false;
87+
}
88+
}
89+
90+
showHidePass() {
91+
this.showPass = !this.showPass;
92+
this.addClassForEye();
93+
}
94+
95+
private addClassForEye() {
96+
let [mainClass, openClass, closeClass] = ['fa', 'fa-eye', 'fa-eye-slash'];
97+
const styleClassForEye = this.styleClassForEye();
98+
if (styleClassForEye) {
99+
const classes = styleClassForEye.split(' ');
100+
if (classes.length === 3) {
101+
[mainClass, openClass, closeClass] = classes;
102+
} else if (classes.length === 2) {
103+
mainClass = '';
104+
[openClass, closeClass] = classes;
105+
}
106+
}
107+
108+
this.classForEye = mainClass + ' ' + closeClass;
109+
110+
if (this.showPass) {
111+
this.classForEye = mainClass + ' ' + openClass;
112+
}
113+
}
114+
115115
isDateType() {
116116
const types = ['date', 'time', 'datetime-local', 'month', 'week'];
117117
return types.includes(this.inputType());
118118
}
119+
120+
requestFocus(mustExecuteOnFocusGainedMethod: boolean) {
121+
if (this.format() && this.format().isMask && this.dataProviderID() != (this.getFocusElement() as HTMLInputElement).value) {
122+
// wait for ui value to be updated before focus, otherwise mask library will be initialized with the old value and not work properly
123+
setTimeout(() => {
124+
super.requestFocus(mustExecuteOnFocusGainedMethod);
125+
});
126+
}
127+
else {
128+
super.requestFocus(mustExecuteOnFocusGainedMethod);
129+
}
130+
}
119131
}

0 commit comments

Comments
 (0)