Skip to content

Commit

Permalink
feat(module: checkbox&radio): ngModel&Onpush support (#167)
Browse files Browse the repository at this point in the history
  • Loading branch information
fisherspy committed Dec 19, 2018
1 parent b4af7c7 commit b1b4807
Show file tree
Hide file tree
Showing 21 changed files with 439 additions and 294 deletions.
1 change: 0 additions & 1 deletion components/checkbox/agree-item.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
[value]="value"
[checked]="checked"
[disabled]="disabled"
(click)="agree()"
(onChange)="change($event)"
>
<ng-content></ng-content>
Expand Down
64 changes: 49 additions & 15 deletions components/checkbox/agree-item.component.ts
Original file line number Diff line number Diff line change
@@ -1,41 +1,75 @@
import { Component, Input, Output, EventEmitter, HostBinding } from '@angular/core';
import {
Component,
forwardRef,
Input,
Output,
EventEmitter,
HostBinding,
ViewEncapsulation,
ChangeDetectionStrategy
} from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';

export interface OnChangeEvent {
export interface CheckboxStatus {
name: string;
value: string;
checked: boolean;
}

@Component({
selector: 'AgreeItem, nzm-agree-item',
templateUrl: './agree-item.component.html'
templateUrl: './agree-item.component.html',
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush,
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => AgreeItem),
multi: true
}
]
})
export class AgreeItem {
export class AgreeItem implements ControlValueAccessor {
prefixCls: string = 'am-checkbox';
checked: boolean = false;
private _disabled: boolean = false;

private _ngModelOnChange: (value: boolean) => {};
private _ngModelOnTouched: () => {};

@Input()
name: string;
@Input()
value: string;
@Input()
checked: boolean = false;
@Input()
disabled: boolean = false;
get disabled(): boolean {
return this._disabled;
}
set disabled(value: boolean) {
this._disabled = value;
}
@Output()
onChange = new EventEmitter<OnChangeEvent>();
onChange = new EventEmitter<CheckboxStatus>();

@HostBinding('class.am-checkbox-agree')
checkboxAgree: boolean = true;

constructor() {}

agree() {
if (!this.disabled) {
this.checked = !this.checked;
}
}
constructor() { }

change(event) {
this._ngModelOnChange(event.checked);
this.onChange.emit(event);
}

writeValue(value: boolean): void {
this.checked = value;
}

registerOnChange(fn: (_: boolean) => {}): void {
this._ngModelOnChange = fn;
}

registerOnTouched(fn: () => {}): void {
this._ngModelOnTouched = fn;
}
}
59 changes: 40 additions & 19 deletions components/checkbox/checkbox-item.component.ts
Original file line number Diff line number Diff line change
@@ -1,43 +1,64 @@
import { Component, Input, Output, EventEmitter } from '@angular/core';
import { Component, forwardRef, Input, Output, EventEmitter, ChangeDetectionStrategy, ViewEncapsulation } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';

export interface OnChangeEvent {
export interface CheckboxStatus {
name: string;
value: string;
checked: boolean;
}

@Component({
selector: 'CheckboxItem, nzm-checkbox-item',
templateUrl: './checkbox-item.component.html'
templateUrl: './checkbox-item.component.html',
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush,
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => CheckboxItem),
multi: true
}
]
})
export class CheckboxItem {
export class CheckboxItem implements ControlValueAccessor {
prefixCls = 'am-checkbox';
checked: boolean = false;
private _disabled: boolean = false;
private _ngModelOnChange: (value: boolean) => {};
private _ngModelOnTouched: () => {};

@Input()
name: string;
@Input()
value: string;
@Input()
checked: boolean = false;
@Input()
disabled: boolean = false;
@Output()
onChange = new EventEmitter<OnChangeEvent>();
get disabled(): boolean {
return this._disabled;
}
set disabled(value: boolean) {
this._disabled = value;
}
@Output()
onClick = new EventEmitter();
onChange = new EventEmitter<CheckboxStatus>();

constructor() {}
constructor() { }

onCheckboxClick(event) {
if (!this.disabled) {
this.checked = !this.checked;
}
if (this.onClick.observers.length > 0) {
this.onClick.emit(event);
}
}
onCheckboxClick(event) { }

change(event) {
this._ngModelOnChange(event.checked);
this.onChange.emit(event);
}

writeValue(value: boolean): void {
this.checked = value;
}

registerOnChange(fn: (_: boolean) => {}): void {
this._ngModelOnChange = fn;
}

registerOnTouched(fn: () => {}): void {
this._ngModelOnTouched = fn;
}
}
31 changes: 4 additions & 27 deletions components/checkbox/checkbox.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,24 +69,6 @@ describe('checkbox', () => {
// expect(component.onChange).toHaveBeenCalledTimes(1);
});

it('checkbox item onClick work', () => {
const checkboxItem = fixture.debugElement.query(By.css('ListItem'));
component.onClick = jasmine.createSpy('onClick callback');
component.disabled = false;
component.checked = false;
fixture.detectChanges();
checkboxItem.nativeElement.click();
fixture.detectChanges();
expect(component.onClick).toHaveBeenCalledTimes(1);

component.disabled = true;
component.checked = false;
fixture.detectChanges();
checkboxItem.nativeElement.click();
fixture.detectChanges();
expect(component.onClick).toHaveBeenCalledTimes(2);
});

it('agreeItem onChange work', () => {
const agreeItem = fixture.debugElement.query(By.css('AgreeItem')).nativeElement;
component.onChange = jasmine.createSpy('onChange callback');
Expand All @@ -111,23 +93,21 @@ describe('checkbox', () => {
<label Checkbox
[disabled]="disabled"
[checked]="checked"
[(ngModel)]="checked"
(onChange)= "onChange($event)"
></label>
<CheckboxItem [disabled]="disabled"
[checked]="checked"
[(ngModel)]="checked"
(onChange)="onChange($event)"
(onClick)="onClick($event)"
></CheckboxItem>
<AgreeItem [disabled]="disabled"
[checked]="checked"
[(ngModel)]="checked"
(onChange)= "onChange($event)"
></AgreeItem>
`
})
export class TestCheckboxComponent {
checked = false;
disabled = false;
checked: boolean = false;
disabled: boolean = false;

@ViewChild(Checkbox)
checkbox: Checkbox;
Expand All @@ -136,7 +116,4 @@ export class TestCheckboxComponent {
console.log('onChange', e);
}

onClick(e) {
console.log('onClick', e);
}
}
65 changes: 19 additions & 46 deletions components/checkbox/checkbox.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,12 @@ import {
Input,
Output,
OnInit,
OnChanges,
EventEmitter,
HostBinding,
HostListener,
ViewEncapsulation,
forwardRef
ChangeDetectionStrategy
} from '@angular/core';
import { toBoolean } from '../core/util/convert';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';

export interface OnChangeEvent {
name: string;
Expand All @@ -24,25 +21,17 @@ export interface OnChangeEvent {
templateUrl: './checkbox.component.html',
preserveWhitespaces: false,
encapsulation: ViewEncapsulation.None,
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => Checkbox),
multi: true
}
]
changeDetection: ChangeDetectionStrategy.OnPush
})
export class Checkbox implements OnInit, OnChanges, ControlValueAccessor {
export class Checkbox implements OnInit {
prefixCls: string = 'am-checkbox';
classMap: object = {
[this.prefixCls]: true,
[`${this.prefixCls}-checked`]: this.checked,
[`${this.prefixCls}-disabled`]: this.disabled
[`${this.prefixCls}-checked`]: false,
[`${this.prefixCls}-disabled`]: false
};
private _checked = false;
private _disabled = false;
private _ngModelOnChange: any = Function.prototype;
private _ngModelOnTouched: any = Function.prototype;
private _checked: boolean = false;
private _disabled: boolean = false;

@Input()
name: string;
Expand All @@ -53,17 +42,16 @@ export class Checkbox implements OnInit, OnChanges, ControlValueAccessor {
return this._checked;
}
set checked(value: boolean) {
if (!this._disabled) {
this._checked = value;
this.updateClassMap();
}
this._checked = value;
this.updateClassMap();
}
@Input()
get disabled(): boolean {
return this._disabled;
}
set disabled(value: boolean) {
this._disabled = toBoolean(value);
this._disabled = value;
this.updateClassMap();
}
@Output()
onChange = new EventEmitter<OnChangeEvent>();
Expand All @@ -75,41 +63,26 @@ export class Checkbox implements OnInit, OnChanges, ControlValueAccessor {
onClick(event): void {
event.preventDefault();
if (!this._disabled) {
this.updateValue(!this._checked);
this.updateValue(!this.checked);
}
}

constructor() {}
constructor() { }

updateValue(value: boolean): void {
this._ngModelOnChange(value);
this.onChange.emit({ name: this.name, value: this.value, checked: value });
this.checked = value;
}

writeValue(value: boolean): void {
if (null !== value) {
this.checked = value;
}
}

registerOnChange(fn: (_: boolean) => {}): void {
this._ngModelOnChange = fn;
}

registerOnTouched(fn: () => {}): void {
this._ngModelOnTouched = fn;
this.onChange.emit({
name: this.name,
value: this.value,
checked: value
});
}

ngOnInit() {
this.updateClassMap();
}

ngOnChanges(): void {
this.updateClassMap();
}

private updateClassMap(): void {
private updateClassMap() {
this.classMap = {
[this.prefixCls]: true,
[`${this.prefixCls}-checked`]: this.checked,
Expand Down
Loading

0 comments on commit b1b4807

Please sign in to comment.