Skip to content

Commit 7fdfcb3

Browse files
authored
Merge branch 'master' into puppeteer
2 parents 4ab29d8 + 3cc045c commit 7fdfcb3

29 files changed

+1088
-258
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ All notable changes for each version of this project will be documented in this
55
## 15.1.0
66

77
### New Features
8+
- `IgxGrid`, `IgxTreeGrid`, `IgxHierarchicalGrid`:
9+
- `GroupMemberCountSortingStrategy` is added, which can be used to sort the grid by number of items in each group in ASC or DESC order, if grouping is applied.
810
- `IgxColumnComponent`
911
- Added `currRec` and `groupRec` parameters to the `groupingComparer` function that give access to the all properties of the compared records.
1012

@@ -23,11 +25,14 @@ All notable changes for each version of this project will be documented in this
2325
- **Breaking Change** The `onSlideChanged`, `onSlideAdded`, `onSlideRemoved`, `onCarouselPaused` and `onCarouselPlaying` outputs have been renamed to `slideChanged`, `slideAdded`, `slideRemoved`, `carouselPaused` and `carouselPlaying` to not violate the no on-prefixed outputs convention. Automatic migrations are available and will be applied on `ng update`.
2426
- `IgxRadio`, `IgxRadioGroup`
2527
- Added component validation along with styles for invalid state
28+
- `igxMask` directive
29+
- Added the capability to escape mask pattern literals.
2630
- `IgxBadge`
2731
- Added `shape` property that controls the shape of the badge and can be either `square` or `rounded`. The default shape of the badge is rounded.
2832
- `IgxAvatar`
2933
- **Breaking Change** The `roundShape` property has been deprecated and will be removed in a future version. Users can control the shape of the avatar by the newly added `shape` attribute that can be `square`, `rounded` or `circle`. The default shape of the avatar is `square`.
3034

35+
3136
## 15.0.1
3237

3338
- `IgxGrid`

projects/igniteui-angular/src/lib/checkbox/checkbox.component.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
[indeterminate]="indeterminate"
99
[checked]="checked"
1010
[required]="required"
11+
[attr.aria-required]="required"
12+
[attr.aria-invalid]="invalid"
1113
[attr.aria-checked]="ariaChecked"
1214
[attr.aria-labelledby]="ariaLabel ? null : ariaLabelledBy"
1315
[attr.aria-label]="ariaLabel"

projects/igniteui-angular/src/lib/checkbox/checkbox.component.spec.ts

Lines changed: 107 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Component, ViewChild } from '@angular/core';
22
import { fakeAsync, TestBed, tick, waitForAsync } from '@angular/core/testing';
3-
import { UntypedFormBuilder, FormsModule, ReactiveFormsModule } from '@angular/forms';
3+
import { UntypedFormBuilder, FormsModule, ReactiveFormsModule, Validators, NgForm } from '@angular/forms';
44
import { By } from '@angular/platform-browser';
55
import { IgxRippleModule } from '../directives/ripple/ripple.directive';
66
import { IgxCheckboxComponent } from './checkbox.component';
@@ -21,6 +21,7 @@ describe('IgxCheckbox', () => {
2121
CheckboxExternalLabelComponent,
2222
CheckboxInvisibleLabelComponent,
2323
CheckboxDisabledTransitionsComponent,
24+
CheckboxFormComponent,
2425
CheckboxFormGroupComponent,
2526
IgxCheckboxComponent
2627
],
@@ -275,6 +276,7 @@ describe('IgxCheckbox', () => {
275276
expect(nativeCheckbox.required).toBeTruthy();
276277

277278
checkboxInstance.required = false;
279+
nativeCheckbox.required = false;
278280
fixture.detectChanges();
279281

280282
expect(checkboxInstance.required).toBe(false);
@@ -316,6 +318,79 @@ describe('IgxCheckbox', () => {
316318
expect(testInstance.clickCounter).toEqual(2);
317319
});
318320

321+
it('Should update style when required checkbox\'s value is set.', () => {
322+
const fixture = TestBed.createComponent(CheckboxRequiredComponent);
323+
fixture.detectChanges();
324+
325+
const checkboxInstance = fixture.componentInstance.cb;
326+
const domCheckbox = fixture.debugElement.query(By.css('igx-checkbox')).nativeElement;
327+
328+
expect(domCheckbox.classList.contains('igx-checkbox--invalid')).toBe(false);
329+
expect(checkboxInstance.invalid).toBe(false);
330+
expect(checkboxInstance.checked).toBe(false);
331+
expect(checkboxInstance.required).toBe(true);
332+
333+
dispatchCbEvent('keyup', domCheckbox, fixture);
334+
expect(domCheckbox.classList.contains('igx-checkbox--focused')).toBe(true);
335+
dispatchCbEvent('blur', domCheckbox, fixture);
336+
337+
expect(checkboxInstance.invalid).toBe(true);
338+
expect(domCheckbox.classList.contains('igx-checkbox--invalid')).toBe(true);
339+
340+
dispatchCbEvent('keyup', domCheckbox, fixture);
341+
expect(domCheckbox.classList.contains('igx-checkbox--focused')).toBe(true);
342+
dispatchCbEvent('click', domCheckbox, fixture);
343+
344+
expect(domCheckbox.classList.contains('igx-checkbox--checked')).toBe(true);
345+
expect(checkboxInstance.checked).toBe(true);
346+
expect(checkboxInstance.invalid).toBe(false);
347+
expect(domCheckbox.classList.contains('igx-checkbox--invalid')).toBe(false);
348+
349+
dispatchCbEvent('click', domCheckbox, fixture);
350+
dispatchCbEvent('keyup', domCheckbox, fixture);
351+
expect(domCheckbox.classList.contains('igx-checkbox--focused')).toBe(true);
352+
dispatchCbEvent('blur', domCheckbox, fixture);
353+
354+
expect(checkboxInstance.checked).toBe(false);
355+
expect(checkboxInstance.invalid).toBe(true);
356+
expect(domCheckbox.classList.contains('igx-checkbox--invalid')).toBe(true);
357+
});
358+
359+
it('Should work properly with ngModel', fakeAsync(() => {
360+
const fixture = TestBed.createComponent(CheckboxFormComponent);
361+
fixture.detectChanges();
362+
tick();
363+
364+
const checkbox = fixture.componentInstance.checkbox;
365+
expect(checkbox.invalid).toEqual(false);
366+
367+
checkbox.onBlur();
368+
expect(checkbox.invalid).toEqual(true);
369+
370+
fixture.componentInstance.ngForm.resetForm();
371+
tick();
372+
expect(checkbox.invalid).toEqual(false);
373+
}));
374+
375+
it('Should work properly with reactive forms validation.', () => {
376+
const fixture = TestBed.createComponent(CheckboxFormGroupComponent);
377+
fixture.detectChanges();
378+
379+
const checkbox = fixture.componentInstance.cb;
380+
checkbox.checked = false;
381+
expect(checkbox.required).toBe(true);
382+
expect(checkbox.nativeElement.getAttribute('aria-required')).toEqual('true');
383+
expect(checkbox.nativeElement.getAttribute('aria-invalid')).toEqual('false');
384+
385+
fixture.debugElement.componentInstance.markAsTouched();
386+
fixture.detectChanges();
387+
388+
const invalidCheckbox = fixture.debugElement.nativeElement.querySelectorAll(`.igx-checkbox--invalid`);
389+
expect(invalidCheckbox.length).toBe(1);
390+
expect(checkbox.invalid).toBe(true);
391+
expect(checkbox.nativeElement.getAttribute('aria-invalid')).toEqual('true');
392+
});
393+
319394
describe('EditorProvider', () => {
320395
it('Should return correct edit element', () => {
321396
const fixture = TestBed.createComponent(CheckboxSimpleComponent);
@@ -410,7 +485,37 @@ class CheckboxDisabledTransitionsComponent {
410485
class CheckboxFormGroupComponent {
411486
@ViewChild('cb', { static: true }) public cb: IgxCheckboxComponent;
412487

413-
public myForm = this.fb.group({ checkbox: [null] });
488+
public myForm = this.fb.group({ checkbox: ['', Validators.required] });
414489

415490
constructor(private fb: UntypedFormBuilder) {}
491+
492+
public markAsTouched() {
493+
if (!this.myForm.valid) {
494+
for (const key in this.myForm.controls) {
495+
if (this.myForm.controls[key]) {
496+
this.myForm.controls[key].markAsTouched();
497+
this.myForm.controls[key].updateValueAndValidity();
498+
}
499+
}
500+
}
501+
}
416502
}
503+
@Component({
504+
template: `
505+
<form #form="ngForm">
506+
<igx-checkbox #checkbox [(ngModel)]="subscribed" name="checkbox" required>Checkbox</igx-checkbox>
507+
</form>
508+
`
509+
})
510+
class CheckboxFormComponent {
511+
@ViewChild('checkbox', { read: IgxCheckboxComponent, static: true })
512+
public checkbox: IgxCheckboxComponent;
513+
@ViewChild(NgForm, { static: true })
514+
public ngForm: NgForm;
515+
public subscribed: string;
516+
}
517+
518+
const dispatchCbEvent = (eventName, cbNativeElement, fixture) => {
519+
cbNativeElement.dispatchEvent(new Event(eventName));
520+
fixture.detectChanges();
521+
};

0 commit comments

Comments
 (0)