Skip to content

Commit

Permalink
feat(design): moved CVA implementation to a directive
Browse files Browse the repository at this point in the history
  • Loading branch information
Nolan-Arnold committed May 12, 2020
1 parent c2611c6 commit d19685b
Show file tree
Hide file tree
Showing 9 changed files with 272 additions and 48 deletions.
6 changes: 3 additions & 3 deletions apps/design-land/src/app/checkbox/checkbox.component.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<daff-checkbox-set [formGroup]="checkboxes">
<daff-checkbox formControlName="option1" value="option1">Option 1 </daff-checkbox>
<daff-checkbox formControlName="option2" value="option2">Option 2 </daff-checkbox>
<daff-checkbox formControlName="option3" value="option3">Option 3 </daff-checkbox>
<daff-checkbox formControlName="0" value="option1">Option 1 </daff-checkbox>
<daff-checkbox formControlName="1" value="option2">Option 2 </daff-checkbox>
<daff-checkbox formControlName="2" value="option3">Option 3 </daff-checkbox>
</daff-checkbox-set>
18 changes: 10 additions & 8 deletions apps/design-land/src/app/checkbox/checkbox.component.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
import { Component, OnInit } from '@angular/core';
import { FormGroup, FormControl } from '@angular/forms';
import { FormControl, FormArray } from '@angular/forms';

@Component({
selector: 'checkbox-component',
templateUrl: './checkbox.component.html',
styleUrls: ['./checkbox.component.scss'],

})
export class CheckboxComponent {
export class CheckboxComponent implements OnInit {

checkboxes = new FormGroup({
option1: new FormControl('false'),
option2: new FormControl('true'),
option3: new FormControl()
})
}
option1 = new FormControl();
option2 = new FormControl();
option3 = new FormControl();
checkboxes = new FormArray([this.option1, this.option2, this.option3]);
ngOnInit() {
this.checkboxes.setValue(['option1', 'false', 'false'])
}
}
4 changes: 2 additions & 2 deletions libs/design/src/atoms/form/checkbox/checkbox.component.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<input type="checkbox"
aria-label="ariaLabel"
aria-labelledby="ariaLabeledBy"
[attr.aria-label]="label"
[attr.aria-labelledby]="labeledBy"
[attr.checked]="checked ? true : null"
[attr.id] = "id"
[attr.value]="value"
Expand Down
24 changes: 12 additions & 12 deletions libs/design/src/atoms/form/checkbox/checkbox.component.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { Component, DebugElement } from '@angular/core';
import { By } from '@angular/platform-browser';
import { ReactiveFormsModule, FormGroup, FormControl } from '@angular/forms';
import { ReactiveFormsModule, FormGroup, FormControl, FormArray } from '@angular/forms';
import { DaffCheckboxModule } from './checkbox.module';
import { DaffCheckboxComponent } from './checkbox.component';

Expand All @@ -18,20 +18,20 @@ class CheckboxWrapperComponent { }
template: `
<daff-checkbox-set [formGroup]="checkboxGroup" name="toppings">
<daff-checkbox formControlName="lettuce" value="lettuce">Apple</daff-checkbox>
<daff-checkbox formControlName="tomato" value="tomato">Grape</daff-checkbox>
<daff-checkbox formControlName="pickle" value="pickle">Peach</daff-checkbox>
<daff-checkbox formControlName="0" value="lettuce">Apple</daff-checkbox>
<daff-checkbox formControlName="1" value="tomato">Grape</daff-checkbox>
<daff-checkbox formControlName="2" value="pickle">Peach</daff-checkbox>
</daff-checkbox-set>
`
})
class CheckboxEmbeddedComponent {
checkboxGroup = new FormGroup({
lettuce: new FormControl(),
tomato: new FormControl(),
pickle: new FormControl()
});

lettuce = new FormControl();
tomato = new FormControl();
pickle = new FormControl();
checkboxGroup = new FormArray([this.lettuce, this.tomato, this.pickle]);
setValue() {
this.checkboxGroup.setValue({ lettuce: 'false', tomato: 'false', pickle: 'false' })
this.checkboxGroup.setValue(['lettuce', 'tomato', 'pickle'])
}
disable() {
this.checkboxGroup.disable();
Expand Down Expand Up @@ -88,9 +88,9 @@ describe('DaffCheckboxComponent', () => {
});
describe('and the control value accessor implementation', () => {
it('should let the value be set from a form control', () => {
embeddedComponent.checked = true;
embeddedComponent.checked = false;
checkboxEmbedded.setValue();
expect(embeddedComponent.checked).toEqual(false);
expect(embeddedComponent.checked).toEqual(true);
});
it('should let the checkbox be disabled from a form control', () => {
checkboxEmbedded.disable();
Expand Down
66 changes: 48 additions & 18 deletions libs/design/src/atoms/form/checkbox/checkbox.component.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Component, OnInit, Input, HostBinding, ChangeDetectionStrategy, forwardRef } from '@angular/core';
import { Component, OnInit, Input, HostBinding, ChangeDetectionStrategy, forwardRef, EventEmitter, Output } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';

let checkboxIdNum = 0;
Expand All @@ -16,34 +16,52 @@ let checkboxIdNum = 0;
],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class DaffCheckboxComponent implements ControlValueAccessor {
@Input() ariaLabel: string;
@Input() ariaLabeledBy: string;
export class DaffCheckboxComponent {

/**
* The name of the checkbox.
*/
@Input() name: string;
/**
* The value of the checkbox.
*/
@Input() value: any;
/**
* Boolean value to determine whether or not the checkbox is checked.
*/
@Input() checked = false;
/**
* The id of the checkbox. Must be unique. If not entered by a user then it is generated.
*/
@Input() id: string = 'daff-checkbox-' + checkboxIdNum;
/**
* The aria-label of the checkbox. If not set by user then it defaults to the name of the checkbox.
*/
@Input() label = name;
/**
* The aria-labeledby of the checkbox.
*/
@Input() labeledBy: string;

/**
* Event on whether or not the
*/
@Output() selectionChange: EventEmitter<boolean> = new EventEmitter();

/**
* Whether the checkbox is focused.chzn-container-active
*/
focused: boolean;
/**
* Whether the checkbox is disabled.
*/
disabled: boolean;

@HostBinding('attr.role') role = 'checkbox';


onChange: () => {};
onTouched: () => {};

writeValue(value: any): void {
this.checked = (value === 'true' || value === 'checked' ? true : false)
}
registerOnChange(fn: any): void {
this.onChange = fn;
}
registerOnTouched(fn: any): void {
this.onTouched = fn;
}
setDisabledState?(isDisabled: boolean): void {
this.disabled = isDisabled;
}
@HostBinding('class.focused') get focusClass() {
return this.focused === true;
};
Expand All @@ -60,4 +78,16 @@ export class DaffCheckboxComponent implements ControlValueAccessor {
constructor() {
checkboxIdNum++;
}
/**
* Sets checked to true.
*/
select() {
this.checked = true;
}
/**
* Sets checked to false
*/
deselect() {
this.checked = false;
}
}
7 changes: 5 additions & 2 deletions libs/design/src/atoms/form/checkbox/checkbox.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,18 @@ import { NgModule } from '@angular/core';

import { DaffCheckboxComponent } from './checkbox.component';
import { DaffCheckboxSetComponent } from '../checkbox-set/checkbox-set.component';
import { DaffCheckboxControlValueAccessorDirective } from './cva/checkbox-cva.directive';

@NgModule({
exports: [
DaffCheckboxComponent,
DaffCheckboxSetComponent
DaffCheckboxSetComponent,
DaffCheckboxControlValueAccessorDirective
],
declarations: [
DaffCheckboxComponent,
DaffCheckboxSetComponent
DaffCheckboxSetComponent,
DaffCheckboxControlValueAccessorDirective
],
imports: [],
providers: []
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import { Component } from '@angular/core';
import { ComponentFixture, async, TestBed } from '@angular/core/testing';
import { ReactiveFormsModule, FormControl } from '@angular/forms';
import { By } from '@angular/platform-browser';

import { DaffCheckboxComponent } from '../checkbox.component';
import { DaffCheckboxModule } from '../checkbox.module';



@Component({
template: `
<daff-checkbox name='test' value='testValue' [formControl]='checkbox'></daff-checkbox>
`
})
class CheckboxWrapperComponent {
checkbox = new FormControl()
}

describe('DaffCheckboxControlValueAccessorDirective', () => {

describe('with the directive', () => {
let CheckboxWrapper: CheckboxWrapperComponent;

let component: DaffCheckboxComponent;

let fixture: ComponentFixture<CheckboxWrapperComponent>;

beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [
CheckboxWrapperComponent,
],
imports: [
ReactiveFormsModule,
DaffCheckboxModule
]
})
.compileComponents();
}));
describe('the DaffCheckboxComponent', () => {

beforeEach(() => {

fixture = TestBed.createComponent(CheckboxWrapperComponent);
CheckboxWrapper = fixture.componentInstance;
component = fixture.debugElement.query(By.css('daff-Checkbox')).componentInstance;
fixture.detectChanges();
});
it('has the writeValue function for formControls', async () => {

expect(component.checked).toEqual(false);

CheckboxWrapper.checkbox.setValue('testValue');

expect(component.checked).toEqual(true);
});
});

});
describe('without the directive', () => {
let CheckboxWrapper: CheckboxWrapperComponent;

let component: DaffCheckboxComponent;

let fixture: ComponentFixture<CheckboxWrapperComponent>;

beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [
CheckboxWrapperComponent,
DaffCheckboxComponent
],
imports: [
ReactiveFormsModule,
]
})
.compileComponents();
}));
describe('the DaffCheckboxComponent', () => {

it('throws an error without the directive to give the itself the CVA interface', async () => {
fixture = TestBed.createComponent(CheckboxWrapperComponent);
CheckboxWrapper = fixture.componentInstance;
expect(() => {
component = fixture.debugElement.query(By.css('daff-checkbox')).componentInstance;
fixture.detectChanges();
}).toThrowError()
});

});
});
});
Loading

0 comments on commit d19685b

Please sign in to comment.