mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-18 19:21:34 +08:00
feat(numeric-input): create number input control value accessor
This commit is contained in:
@ -0,0 +1,62 @@
|
|||||||
|
import { Directive, ElementRef, HostListener, Renderer2 } from '@angular/core';
|
||||||
|
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
|
||||||
|
|
||||||
|
@Directive({
|
||||||
|
/* tslint:disable-next-line:directive-selector */
|
||||||
|
selector: 'ion-input[type=number]',
|
||||||
|
providers: [
|
||||||
|
{
|
||||||
|
provide: NG_VALUE_ACCESSOR,
|
||||||
|
useExisting: NumericValueAccessor,
|
||||||
|
multi: true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class NumericValueAccessor implements ControlValueAccessor {
|
||||||
|
constructor(private element: ElementRef, private renderer: Renderer2) {
|
||||||
|
this.onChange = () => {};
|
||||||
|
this.onTouched = () => {};
|
||||||
|
}
|
||||||
|
|
||||||
|
onChange: (value: any) => void;
|
||||||
|
onTouched: () => void;
|
||||||
|
|
||||||
|
writeValue(value: any): void {
|
||||||
|
// The value needs to be normalized for IE9, otherwise it is set to 'null' when null
|
||||||
|
// Probably not an issue for us, but it doesn't really cost anything either
|
||||||
|
const normalizedValue = value == null ? '' : value;
|
||||||
|
this.renderer.setProperty(
|
||||||
|
this.element.nativeElement,
|
||||||
|
'value',
|
||||||
|
normalizedValue
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@HostListener('input', ['$event.target.value'])
|
||||||
|
_handleInputEvent(value: any): void {
|
||||||
|
this.onChange(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@HostListener('ionBlur')
|
||||||
|
_handleBlurEvent(): void {
|
||||||
|
this.onTouched();
|
||||||
|
}
|
||||||
|
|
||||||
|
registerOnChange(fn: (_: number | null) => void): void {
|
||||||
|
this.onChange = value => {
|
||||||
|
fn(value == '' ? null : parseFloat(value));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
registerOnTouched(fn: () => void): void {
|
||||||
|
this.onTouched = fn;
|
||||||
|
}
|
||||||
|
|
||||||
|
setDisabledState(isDisabled: boolean): void {
|
||||||
|
this.renderer.setProperty(
|
||||||
|
this.element.nativeElement,
|
||||||
|
'disabled',
|
||||||
|
isDisabled
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -1,11 +1,9 @@
|
|||||||
import { Directive, ElementRef, HostListener, Renderer2 } from '@angular/core';
|
import { Directive, ElementRef, HostListener, Renderer2 } from '@angular/core';
|
||||||
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
|
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
|
||||||
|
|
||||||
// NOTE: May need to look at this to see if we need anything else:
|
|
||||||
// https://github.com/angular/angular/blob/5.0.1/packages/forms/src/directives/default_value_accessor.ts#L33-L101
|
|
||||||
@Directive({
|
@Directive({
|
||||||
/* tslint:disable-next-line:directive-selector */
|
/* tslint:disable-next-line:directive-selector */
|
||||||
selector: 'ion-input,ion-textarea',
|
selector: 'ion-input:not([type=number]),ion-textarea',
|
||||||
providers: [
|
providers: [
|
||||||
{
|
{
|
||||||
provide: NG_VALUE_ACCESSOR,
|
provide: NG_VALUE_ACCESSOR,
|
||||||
@ -44,4 +42,12 @@ export class TextValueAccessor implements ControlValueAccessor {
|
|||||||
registerOnTouched(fn: () => void) {
|
registerOnTouched(fn: () => void) {
|
||||||
this.onTouched = fn;
|
this.onTouched = fn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setDisabledState(isDisabled: boolean): void {
|
||||||
|
this.renderer.setProperty(
|
||||||
|
this.element.nativeElement,
|
||||||
|
'disabled',
|
||||||
|
isDisabled
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import {
|
|||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
|
|
||||||
import { BooleanValueAccessor } from './control-value-accessors/boolean-value-accessor';
|
import { BooleanValueAccessor } from './control-value-accessors/boolean-value-accessor';
|
||||||
|
import { NumericValueAccessor } from './control-value-accessors/numeric-value-accesssor';
|
||||||
import { RadioValueAccessor } from './control-value-accessors/radio-value-accessor';
|
import { RadioValueAccessor } from './control-value-accessors/radio-value-accessor';
|
||||||
import { SelectValueAccessor } from './control-value-accessors/select-value-accessor';
|
import { SelectValueAccessor } from './control-value-accessors/select-value-accessor';
|
||||||
import { TextValueAccessor } from './control-value-accessors/text-value-accessor';
|
import { TextValueAccessor } from './control-value-accessors/text-value-accessor';
|
||||||
@ -23,6 +24,7 @@ import { ToastController } from './providers/toast-controller';
|
|||||||
declarations: [
|
declarations: [
|
||||||
BooleanValueAccessor,
|
BooleanValueAccessor,
|
||||||
IonNavDelegate,
|
IonNavDelegate,
|
||||||
|
NumericValueAccessor,
|
||||||
RadioValueAccessor,
|
RadioValueAccessor,
|
||||||
SelectValueAccessor,
|
SelectValueAccessor,
|
||||||
TextValueAccessor
|
TextValueAccessor
|
||||||
@ -30,6 +32,7 @@ import { ToastController } from './providers/toast-controller';
|
|||||||
exports: [
|
exports: [
|
||||||
BooleanValueAccessor,
|
BooleanValueAccessor,
|
||||||
IonNavDelegate,
|
IonNavDelegate,
|
||||||
|
NumericValueAccessor,
|
||||||
RadioValueAccessor,
|
RadioValueAccessor,
|
||||||
SelectValueAccessor,
|
SelectValueAccessor,
|
||||||
TextValueAccessor
|
TextValueAccessor
|
||||||
|
@ -30,6 +30,30 @@
|
|||||||
</ion-col>
|
</ion-col>
|
||||||
</ion-row>
|
</ion-row>
|
||||||
|
|
||||||
|
<ion-row>
|
||||||
|
<ion-col>
|
||||||
|
<h2>Numeric Input</h2>
|
||||||
|
</ion-col>
|
||||||
|
</ion-row>
|
||||||
|
<ion-row>
|
||||||
|
<ion-col>
|
||||||
|
<ion-item>
|
||||||
|
<ion-label>Ionic Numeric Input</ion-label>
|
||||||
|
<ion-input type="number" id="ionNumberInput" name="ionNumberInput" [(ngModel)]="numberValue"></ion-input>
|
||||||
|
</ion-item>
|
||||||
|
</ion-col>
|
||||||
|
<ion-col>
|
||||||
|
<div>
|
||||||
|
Value:
|
||||||
|
<span id="numberOutput">{{numberValue}}</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
Type:
|
||||||
|
<span id="numberOutputType">{{typeOf(numberValue)}}</span>
|
||||||
|
</div>
|
||||||
|
</ion-col>
|
||||||
|
</ion-row>
|
||||||
|
|
||||||
<ion-row>
|
<ion-row>
|
||||||
<ion-col>
|
<ion-col>
|
||||||
<h2>Textarea Input</h2>
|
<h2>Textarea Input</h2>
|
||||||
@ -127,7 +151,8 @@
|
|||||||
<ion-col>
|
<ion-col>
|
||||||
<ion-item>
|
<ion-item>
|
||||||
<ion-label>Ionic Date</ion-label>
|
<ion-label>Ionic Date</ion-label>
|
||||||
<ion-datetime id="ionDatetimeInput" pickerFormat="YYYY-MM-DD HH:mm:ss" displayFormat="MM/DD/YYYY HH:mm:ss" name="ionDatetimeInput" [(ngModel)]="datetimeValue"></ion-datetime>
|
<ion-datetime id="ionDatetimeInput" pickerFormat="YYYY-MM-DD HH:mm:ss" displayFormat="MM/DD/YYYY HH:mm:ss" name="ionDatetimeInput"
|
||||||
|
[(ngModel)]="datetimeValue"></ion-datetime>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
</ion-col>
|
</ion-col>
|
||||||
<ion-col>
|
<ion-col>
|
||||||
|
@ -10,6 +10,7 @@ export class BasicInputsPageComponent implements OnInit {
|
|||||||
datetimeValue = '2017-11-18T14:17:45-06:00';
|
datetimeValue = '2017-11-18T14:17:45-06:00';
|
||||||
textareaValue = 'This is the Textarea Input';
|
textareaValue = 'This is the Textarea Input';
|
||||||
textValue = 'This is the Text Input';
|
textValue = 'This is the Text Input';
|
||||||
|
numberValue = 1138;
|
||||||
|
|
||||||
checkboxValue = true;
|
checkboxValue = true;
|
||||||
toggleValue = false;
|
toggleValue = false;
|
||||||
@ -17,4 +18,8 @@ export class BasicInputsPageComponent implements OnInit {
|
|||||||
constructor() {}
|
constructor() {}
|
||||||
|
|
||||||
ngOnInit() {}
|
ngOnInit() {}
|
||||||
|
|
||||||
|
typeOf(v: any): string {
|
||||||
|
return typeof v;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user