Skip to content

Commit

Permalink
Adds readonly attribute to p-inputNumber
Browse files Browse the repository at this point in the history
 - Defaults to false
 - Does not display buttons when readonly is set
 - Updates the showcase documentation
 - Adds tests for p-inputNumber default displayability as done in other inputs
 - Adds tests for readonly rules
 - closes primefaces#9827
  • Loading branch information
LeGorge committed Jul 2, 2021
1 parent 3a2f6c0 commit 5907600
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 7 deletions.
61 changes: 59 additions & 2 deletions src/app/components/inputnumber/inputnumber.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,22 @@ import { TestBed, ComponentFixture } from '@angular/core/testing';
import { InputNumber } from './inputnumber';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { FormsModule } from '@angular/forms';
import { Component } from '@angular/core';
import { By } from '@angular/platform-browser';

@Component({
template: `<p-inputNumber [(ngModel)]="val" [readonly]="readonly"></p-inputNumber>`
})
class TestInputNumberComponent {
val: number;
readonly: boolean = true;
}

describe('InputNumber', () => {
let fixture: ComponentFixture<InputNumber>;

let inputNumber: InputNumber;
let testComponent: TestInputNumberComponent;
let fixture: ComponentFixture<TestInputNumberComponent>;

beforeEach(() => {
TestBed.configureTestingModule({
Expand All @@ -14,9 +27,53 @@ describe('InputNumber', () => {
],
declarations: [
InputNumber,
TestInputNumberComponent
]
});

fixture = fixture = TestBed.createComponent(InputNumber);
fixture = TestBed.createComponent(TestInputNumberComponent);
inputNumber = fixture.debugElement.children[0].componentInstance;
testComponent = fixture.componentInstance;
});

it('should display by default', () => {
fixture.detectChanges();

const inputMaskEl = fixture.debugElement.query(By.css('input'));
expect(inputMaskEl.nativeElement).toBeTruthy();
});

it('should not update when readonly', () => {
fixture.detectChanges();

const updateModelSpy = spyOn(inputNumber, "updateModel").and.callThrough();
const inputNumberEl = fixture.debugElement.query(By.css("input"));
const event: any = document.createEvent('CustomEvent');
event.which = 13;
event.initEvent('keydown', true, true);
inputNumberEl.nativeElement.dispatchEvent(event as KeyboardEvent);
event.initEvent('input', true, true);
inputNumberEl.nativeElement.dispatchEvent(event as KeyboardEvent);
event.initEvent('keypress', true, true);
inputNumberEl.nativeElement.dispatchEvent(event as KeyboardEvent);
inputNumberEl.nativeElement.dispatchEvent(new Event("focus"));
fixture.detectChanges();

expect(document.activeElement).not.toEqual(inputNumber.input.nativeElement);
expect(updateModelSpy).not.toHaveBeenCalled();
});

it('should not display buttons when readonly', () => {
inputNumber.showButtons = true;
fixture.detectChanges();

const inputNumberButtonsElArrayReadonly = fixture.debugElement.queryAll(By.css("button"));
expect(inputNumberButtonsElArrayReadonly).toHaveSize(0);

testComponent.readonly = false;
fixture.detectChanges();

const inputNumberButtonsElArray = fixture.debugElement.queryAll(By.css("button"));
expect(inputNumberButtonsElArray).toHaveSize(2);
})
});
32 changes: 27 additions & 5 deletions src/app/components/inputnumber/inputnumber.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,21 @@ export const INPUTNUMBER_VALUE_ACCESSOR: any = {
@Component({
selector: 'p-inputNumber',
template: `
<span [ngClass]="{'p-inputnumber p-component': true,'p-inputnumber-buttons-stacked': this.showButtons && this.buttonLayout === 'stacked',
'p-inputnumber-buttons-horizontal': this.showButtons && this.buttonLayout === 'horizontal', 'p-inputnumber-buttons-vertical': this.showButtons && this.buttonLayout === 'vertical'}"
<span [ngClass]="{'p-inputnumber p-component': true,'p-inputnumber-buttons-stacked': !readonly && this.showButtons && this.buttonLayout === 'stacked',
'p-inputnumber-buttons-horizontal': !readonly && this.showButtons && this.buttonLayout === 'horizontal', 'p-inputnumber-buttons-vertical': !readonly && this.showButtons && this.buttonLayout === 'vertical'}"
[ngStyle]="style" [class]="styleClass">
<input #input [ngClass]="'p-inputnumber-input'" [ngStyle]="inputStyle" [class]="inputStyleClass" pInputText [value]="formattedValue()" [attr.placeholder]="placeholder" [attr.title]="title" [attr.id]="inputId"
[attr.size]="size" [attr.name]="name" [attr.autocomplete]="autocomplete" [attr.maxlength]="maxlength" [attr.tabindex]="tabindex" [attr.aria-label]="ariaLabel"
[attr.aria-required]="ariaRequired" [disabled]="disabled" [attr.required]="required" [attr.aria-valuemin]="min" [attr.aria-valuemax]="max"
[attr.aria-required]="ariaRequired" [disabled]="disabled" [attr.required]="required" [attr.aria-valuemin]="min" [attr.aria-valuemax]="max" [readonly]="readonly"
(input)="onUserInput($event)" (keydown)="onInputKeyDown($event)" (keypress)="onInputKeyPress($event)" (paste)="onPaste($event)" (click)="onInputClick()"
(focus)="onInputFocus($event)" (blur)="onInputBlur($event)">
<span class="p-inputnumber-button-group" *ngIf="showButtons && buttonLayout === 'stacked'">
<span class="p-inputnumber-button-group" *ngIf="!readonly && showButtons && buttonLayout === 'stacked'">
<button type="button" pButton [ngClass]="{'p-inputnumber-button p-inputnumber-button-up': true}" [class]="incrementButtonClass" [icon]="incrementButtonIcon" [disabled]="disabled"
(mousedown)="this.onUpButtonMouseDown($event)" (mouseup)="onUpButtonMouseUp()" (mouseleave)="onUpButtonMouseLeave()" (keydown)="onUpButtonKeyDown($event)" (keyup)="onUpButtonKeyUp()"></button>
<button type="button" pButton [ngClass]="{'p-inputnumber-button p-inputnumber-button-down': true}" [class]="decrementButtonClass" [icon]="decrementButtonIcon" [disabled]="disabled"
(mousedown)="this.onDownButtonMouseDown($event)" (mouseup)="onDownButtonMouseUp()" (mouseleave)="onDownButtonMouseLeave()" (keydown)="onDownButtonKeyDown($event)" (keyup)="onDownButtonKeyUp()"></button>
</span>
<button type="button" pButton [ngClass]="{'p-inputnumber-button p-inputnumber-button-up': true}" [class]="incrementButtonClass" [icon]="incrementButtonIcon" *ngIf="showButtons && buttonLayout !== 'stacked'" [disabled]="disabled"
<button type="button" pButton [ngClass]="{'p-inputnumber-button p-inputnumber-button-up': true}" [class]="incrementButtonClass" [icon]="incrementButtonIcon" *ngIf="!readonly && showButtons && buttonLayout !== 'stacked'" [disabled]="disabled"
(mousedown)="this.onUpButtonMouseDown($event)" (mouseup)="onUpButtonMouseUp()" (mouseleave)="onUpButtonMouseLeave()" (keydown)="onUpButtonKeyDown($event)" (keyup)="onUpButtonKeyUp()"></button>
<button type="button" pButton [ngClass]="{'p-inputnumber-button p-inputnumber-button-down': true}" [class]="decrementButtonClass" [icon]="decrementButtonIcon" *ngIf="showButtons && buttonLayout !== 'stacked'" [disabled]="disabled"
(mousedown)="this.onDownButtonMouseDown($event)" (mouseup)="onDownButtonMouseUp()" (mouseleave)="onDownButtonMouseLeave()" (keydown)="onDownButtonKeyDown($event)" (keyup)="onDownButtonKeyUp()"></button>
Expand Down Expand Up @@ -88,6 +88,8 @@ export class InputNumber implements OnInit,ControlValueAccessor {

@Input() decrementButtonIcon: string = 'pi pi-angle-down';

@Input() readonly: boolean = false;

@Input() step: number = 1;

@Input() inputStyle: any;
Expand Down Expand Up @@ -488,13 +490,20 @@ export class InputNumber implements OnInit,ControlValueAccessor {
}

onUserInput(event) {
if (this.readonly) {
return;
}
if (this.isSpecialChar) {
event.target.value = this.lastValue;
}
this.isSpecialChar = false;
}

onInputKeyDown(event) {
if (this.readonly) {
return;
}

this.lastValue = event.target.value;
if (event.shiftKey || event.altKey) {
this.isSpecialChar = true;
Expand Down Expand Up @@ -631,6 +640,9 @@ export class InputNumber implements OnInit,ControlValueAccessor {
}

onInputKeyPress(event) {
if (this.readonly) {
return;
}
event.preventDefault();
let code = event.which || event.keyCode;
let char = String.fromCharCode(code);
Expand All @@ -643,6 +655,9 @@ export class InputNumber implements OnInit,ControlValueAccessor {
}

onPaste(event) {
if (this.readonly) {
return;
}
if (!this.disabled) {
event.preventDefault();
let data = (event.clipboardData || window['clipboardData']).getData('Text');
Expand Down Expand Up @@ -942,11 +957,18 @@ export class InputNumber implements OnInit,ControlValueAccessor {
}

onInputFocus(event) {
if (this.readonly) {
return;
}
this.focused = true;
this.onFocus.emit(event);
}

onInputBlur(event) {
if (this.readonly) {
return;
}

this.focused = false;

let newValue = this.validateValue(this.parseValue(this.input.nativeElement.value));
Expand Down
6 changes: 6 additions & 0 deletions src/app/showcase/components/inputnumber/inputnumberdemo.html
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,12 @@ <h5>Properties</h5>
<td>false</td>
<td>When present, it specifies that the element should be disabled.</td>
</tr>
<tr>
<td>readonly</td>
<td>boolean</td>
<td>false</td>
<td>When present, it specifies that an input field is read-only and any buttons are not displayed</td>
</tr>
<tr>
<td>title</td>
<td>string</td>
Expand Down

0 comments on commit 5907600

Please sign in to comment.