Skip to content

Commit 19127db

Browse files
committed
fix(mask): don't call model change on model write #6783
1 parent dcd49b1 commit 19127db

File tree

3 files changed

+50
-3
lines changed

3 files changed

+50
-3
lines changed

projects/igniteui-angular/src/lib/directives/mask/mask.directive.spec.ts

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@ import {
77
} from '@angular/core/testing';
88
import { FormsModule } from '@angular/forms';
99
import { IgxInputGroupModule } from '../../input-group/input-group.component';
10-
import { IgxMaskModule } from './mask.directive';
10+
import { IgxMaskModule, IgxMaskDirective } from './mask.directive';
1111

1212
import { configureTestSuite } from '../../test-utils/configure-suite';
1313
import { UIInteractions } from '../../test-utils/ui-interactions.spec';
14+
import { Replaced } from './mask-parsing.service';
1415

1516
describe('igxMask', () => {
1617
configureTestSuite();
@@ -399,6 +400,53 @@ describe('igxMask', () => {
399400
}));
400401
});
401402

403+
describe('igxMaskDirective ControlValueAccessor Unit', () => {
404+
let mask: IgxMaskDirective;
405+
it('Should correctly implement interface methods', () => {
406+
const mockNgControl = jasmine.createSpyObj('NgControl', ['registerOnChangeCb', 'registerOnTouchedCb']);
407+
408+
const mockParser = jasmine.createSpyObj('MaskParsingService', {
409+
applyMask: 'test____',
410+
replaceInMask: { value: 'test_2__', end: 6 } as Replaced,
411+
parseValueFromMask: 'test2'
412+
});
413+
const format = 'CCCCCCCC';
414+
415+
// init
416+
mask = new IgxMaskDirective(null, mockParser, null);
417+
mask.mask = format;
418+
mask.registerOnChange(mockNgControl.registerOnChangeCb);
419+
mask.registerOnTouched(mockNgControl.registerOnTouchedCb);
420+
spyOn(mask.onValueChange, 'emit');
421+
const inputGet = spyOnProperty(mask as any, 'inputValue', 'get');
422+
const inputSet = spyOnProperty(mask as any, 'inputValue', 'set');
423+
424+
// writeValue
425+
inputGet.and.returnValue('formatted');
426+
mask.writeValue('test');
427+
expect(mockParser.applyMask).toHaveBeenCalledWith('test', jasmine.objectContaining({ format }));
428+
expect(inputSet).toHaveBeenCalledWith('test____');
429+
expect(mockNgControl.registerOnChangeCb).not.toHaveBeenCalled();
430+
expect(mask.onValueChange.emit).toHaveBeenCalledWith({ rawValue: 'test', formattedValue: 'formatted' });
431+
432+
// OnChange callback
433+
inputGet.and.returnValue('test_2___');
434+
spyOnProperty(mask as any, 'selectionEnd').and.returnValue(6);
435+
const setSelectionSpy = spyOn(mask as any, 'setSelectionRange');
436+
mask.onInputChanged();
437+
expect(mockParser.replaceInMask).toHaveBeenCalledWith('', 'test_2', jasmine.objectContaining({ format }), 0, 0);
438+
expect(inputSet).toHaveBeenCalledWith('test_2__');
439+
expect(setSelectionSpy).toHaveBeenCalledWith(6);
440+
expect(mockNgControl.registerOnChangeCb).toHaveBeenCalledWith('test2');
441+
442+
// OnTouched callback
443+
mask.onFocus();
444+
expect(mockNgControl.registerOnTouchedCb).not.toHaveBeenCalled();
445+
mask.onBlur('');
446+
expect(mockNgControl.registerOnTouchedCb).toHaveBeenCalledTimes(1);
447+
});
448+
});
449+
402450
@Component({
403451
template: `<igx-input-group>
404452
<input #input type="text" igxInput [(ngModel)]="value" [igxMask]="mask"/>

projects/igniteui-angular/src/lib/directives/mask/mask.directive.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,6 @@ export class IgxMaskDirective implements OnInit, AfterViewChecked, ControlValueA
305305
}
306306

307307
this._dataValue = this.includeLiterals ? this.inputValue : value;
308-
this._onChangeCallback(this._dataValue);
309308

310309
this.onValueChange.emit({ rawValue: value, formattedValue: this.inputValue });
311310
}

src/app/mask/mask.sample.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ <h4>Personal Data</h4>
1818
</igx-input-group>
1919
<igx-input-group>
2020
<input igxInput #ssn name="socialSecurityNumber" type="text" [igxMask]="'###-##-####'" [igxTextSelection]="true"
21-
[(ngModel)]="person.socialSecurityNumber" (blur)="validateSSN(ssn, snackbar)" />
21+
[(ngModel)]="person.socialSecurityNumber" (blur)="validateSSN(ssn, snackbar)" required/>
2222
<label igxLabel for="socialSecurityNumber">Social Security Number</label>
2323
</igx-input-group>
2424
<igx-input-group>

0 commit comments

Comments
 (0)