问题
I have an Angular4 app that captures data from a form and stores in DynamoDB. It uses ngModel to support two-way data binding and on the display all looks good. Issue comes into play because of an input field typed as 'text' bound to Typescript 'number' field. Seems to be changing the type of the object value to 'string'. I would simply change the HTML Input type to 'number' except for the unnecessary and undesirable increment/decrement decorators on the form field (and hiding them seems to have limited support). So I was curious if there is another way to keep the data structure typed as desired... if this is a bug in ngModel... or if the input type just simply needs to be 'number'.
The structure in my sample.component.ts file looks like this:
export class Course {
Id: number;
Name: string;
}
...
courseInstance: Course;
saveCourse() {
JSON.stringify(this.courseInstance);
}
My sample.component.html file looks like this:
<div>
<label for="courseid">Course ID: </label>
<input type="text" class="form-control"[(ngModel)]="courseInstance.Id" name="courseid">
</div>
<div>
<label for="courseName">Course Name: </label>
<input type="text" class="form-control"[(ngModel)]="courseInstance.Name" name="courseName">
</div>
<div>
<button type="button" class="btn btn-info btn-lg" (click)="saveCourse()">Save</button>
</div>
Output of JSON.stringify(this.courseInstance) results in something like
{"Id":"100","Name":"Test course"}
Notice the value 100 represented as a string.
If I don't use the form, but simply create an instance such as
courseInstance: Course = {
Id: 100,
Name: 'Test course'
};
Then when outputing result of JSON.stringify(courseInstance); I get
{"Id":100,"Name":"Test course"}
If I try to use PutItem to store object in DynamoDB, the Id value fails type check when data comes from HTML form.
I would have thought that the typing in Typescript would have held precedence over the HTML 'text' input type.
回答1:
Change the type text
to the number
to make the type number
and don't let to write letters.
<input type="number" class="form-control"[(ngModel)]="courseInstance.Id" name="courseid">
回答2:
Angular currently doesn't support type checking in the property binding and event binding. As you can see here, there is an open issue in their github: https://github.com/angular/angular/issues/16952
What I suggest you to do is to change your input to type number and add this css in your component:
input[type=number]::-webkit-inner-spin-button,
input[type=number]::-webkit-outer-spin-button {
-webkit-appearance: none;
margin: 0;
}
EDIT: adding an application in the Stackblitz: https://stackblitz.com/edit/angular4-ngmodel-changes-type-of-data-from-number-to-string
回答3:
The [(ngModel)]
syntax can only set a data-bound property. If you need to do something more or something different, you can write the expanded form.
<div>
<label for="courseid">Course ID: </label>
<input type="text" #ref class="form-control" [ngModel]="courseInstance.Id" (ngModelChange)="onDataChange(ref.value)"name="courseid">
</div>
The ngModel
data property sets the element's value property and the ngModelChange
event property listens for changes to the element's value.use parseInt to get the desired result.ngModelChange
will be fired on every keystroke you need to debounce value else event will be emitted for every keystroke and To debounce values you can use a Subject
with debounceTime()
operator.A subject
is both an observable
and an observer
. This means you can treat it as an observable and pass values to it as well. Apart from this use Template reference variable
In your component
import { Subject } from 'rxjs/Subject';
import {debounceTime } from 'rxjs/operators
debouncer= new Subject();
constructor() {
this.debouncer
.debounceTime(1000)
.subscribe((val) =>{
console.log(val);
this.courseInstance.id=ParseInt(val,10);
});
}
onDataChange(value) {
this.debouncer.next(value);
}
来源:https://stackoverflow.com/questions/49863373/angular4-ngmodel-changes-type-of-data-from-number-to-string