Component:

import { Component, Input, ChangeDetectionStrategy, EventEmitter, Output } from '@angular/core';

@Component({
selector: 'stock-counter',
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<div class="stock-counter">
<div>
<div
(keydown)="onKeyUp($event)"
(blur)="onBlur($event)"
(focus)="onFocus($event)"
tabindex="0">
<p>{{ value }}</p>
<div tabindex="-1">
<button type="button" tabindex="-1" (click)="increment()" [disabled]="value === max">
+
</button>
<button type="button" tabindex="-1" (click)="decrement()" [disabled]="value === min">
-
</button>
</div>
</div>
</div>
</div>
`
})
export class StockCounterComponent {
@Input() step: number = 1;
@Input() min: number = 0;
@Input() max: number = 100; @Output() changed = new EventEmitter<number>(); value: number = 0;
focused: boolean; increment() {
if (this.value < this.max) {
this.value = this.value + this.step;
this.changed.emit(this.value);
}
} decrement() {
if (this.value > this.min) {
this.value = this.value - this.step;
this.changed.emit(this.value);
}
} private onBlur(event: FocusEvent) {
this.focused = false;
event.preventDefault();
event.stopPropagation();
} private onKeyUp(event: KeyboardEvent) {
let handlers = {
ArrowDown: () => this.decrement(),
ArrowUp: () => this.increment()
}; if (handlers[event.code]) {
handlers[event.code]();
event.preventDefault();
event.stopPropagation();
}
} private onFocus(event: FocusEvent) {
this.focused = true;
event.preventDefault();
event.stopPropagation();
} }

Test @Input & @Output:

import {ComponentFixture, TestBed} from '@angular/core/testing';
import {BrowserDynamicTestingModule, platformBrowserDynamicTesting} from '@angular/platform-browser-dynamic/testing'; import {StockCounterComponent} from './stock-counter.component'; TestBed.initTestEnvironment(
BrowserDynamicTestingModule,
platformBrowserDynamicTesting()
); describe('StockCounterComponent', () => { let component: StockCounterComponent;
let fixture: ComponentFixture<StockCounterComponent>; beforeEach(() => {
TestBed.configureTestingModule({
declarations: [
StockCounterComponent
]
}); fixture = TestBed.createComponent(StockCounterComponent);
component = fixture.componentInstance; component.value = ;
}); it('should not increase over the max value', () => {
component.step = ;
component.max = ;
component.increment();
component.increment();
expect(component.value).toEqual();
}); it('should not decrease below the min value', () => {
component.step = ;
component.min = ;
component.value = ;
component.decrement();
expect(component.value).toEqual();
component.decrement();
expect(component.value).toEqual();
}); it('should call the output on a value change', () => {
spyOn(component.changed, 'emit').and.callThrough();
component.step = ;
component.increment();
expect(component.changed.emit).toHaveBeenCalledWith()
});
});

最新文章

  1. EXCEL中多级分类汇总空白字段填充
  2. 无法加载协定为xx的终结点配置部分,因为找到了该协定的多个终结点配置。请按名称指示首选的终结点配置部分。
  3. 图像边缘检测——Sobel算子
  4. js 数组排序要注意的问题,返回的值最好为 -1, 0, 1之间的值
  5. Volatile总结
  6. struts2使用iterator标签显示嵌套Map - 云自无心水自闲 - BlogJava
  7. 解剖 Elasticsearch 集群 - 之三
  8. 在多个Activity中回传值(startActivityForResult())
  9. 【PHP】制作日历
  10. 第三方库API接口
  11. PostgreSQL:安装及中文显示
  12. SimMechanics/Second Generation倒立摆模型建立及初步仿真学习
  13. 复杂sql查询语句
  14. HTTP 500 Invalid bound statement错误
  15. Win10上使用VS2015编译Caffe2
  16. windows 创建共享文件夹
  17. python的执行过程
  18. Markdown编辑器使用说明
  19. Oracle创建database link(dblink)和同义词(synonym)
  20. error_log

热门文章

  1. Leetcode:signal_number_ii
  2. malloc,colloc,realloc内存分配,动态库,静态库的生成与调用
  3. samba-设定文件共享
  4. BZOJ3238: [Ahoi2013]差异(后缀数组)
  5. CORS原理
  6. 删除online日志測试及ora-600 [4194]错误的处理
  7. Android睡眠唤醒机制--Kernel态
  8. input表单验证(全面)
  9. Jpa 的Persistence.xml配置讲解
  10. [D3] Add image to the node