Javascript Angular 6 event.stopPropagation()不在指令中工作(模板驱动的表单已获取event.data)
我正在尝试制作一个用于表单的citizenNumber组件。它实现了ngModel的ControlValueAccessorJavascript Angular 6 event.stopPropagation()不在指令中工作(模板驱动的表单已获取event.data),javascript,angular,html,typescript,Javascript,Angular,Html,Typescript,我正在尝试制作一个用于表单的citizenNumber组件。它实现了ngModel的ControlValueAccessor 导出类CitizenNumberComponent实现ControlValueAccessor{ 私有_值:字符串; @Input()占位符=“”; @Input()required=true; 获取值():字符串{ 返回此值; } 设置值(值:字符串){ 此值为._值=值; 这是一个变化(值); } //进行更改时将触发的寄存器“fn” //这就是我们将更改发送回表单的
导出类CitizenNumberComponent实现ControlValueAccessor{
私有_值:字符串;
@Input()占位符=“”;
@Input()required=true;
获取值():字符串{
返回此值;
}
设置值(值:字符串){
此值为._值=值;
这是一个变化(值);
}
//进行更改时将触发的寄存器“fn”
//这就是我们将更改发送回表单的方式
注册变更(fn:任何):无效{
这一变化=fn;
}
//未使用,用于触摸输入
注册表(fn:any):void{}
//这是为组件设置的初始值
writeValue(值:字符串):无效{
如果(值){
此值为._值=值;
}
}
//registerOnChange中设置的将更改发送回表单的方法
传播变化=((uu0:any)=>{};
}
我做了一个数字指令来限制输入,除了0-9位
在numberDirective中,我使用了“输入”事件,因为按键、向下键和向上键在android chrome中不起作用
@Directive({
selector: 'input[jhiNumbersOnly]'
})
export class NumberDirective {
private specialKeys: Array<string> = ['Backspace', 'Delete', 'Insert', 'Tab', 'End', 'Home', 'ArrowRight', 'ArrowLeft'];
@HostListener('input', ['$event']) onInput(event) {
const key = event['data'];
// Allow Backspace, tab, end, and home keys
if (this.specialKeys.indexOf(key) !== -1) {
return;
}
const initalValue = event.target['value'];
event.target['value'] = initalValue.replace(/[^0-9]*/g, '');
if (initalValue !== event.target['value']) {
event.stopPropagation();
}
}
}
@指令({
选择器:“输入[jhiNumbersOnly]”
})
导出类编号指示{
private specialKeys:Array=[“退格”、“删除”、“插入”、“制表”、“结束”、“主页”、“箭头右”、“箭头左”];
@HostListener('input',['$event'])onInput(event){
常量键=事件['data'];
//允许使用退格键、制表符键、结束键和主控键
if(此.specialKeys.indexOf(键)!=-1){
返回;
}
常量initalValue=event.target['value'];
event.target['value']=initalValue.replace(/[^0-9]*/g');
if(initalValue!==event.target['value']){
event.stopPropagation();
}
}
}
最后,一切正常,但尽管事件已停止,模型仍将获取值。
例如,我的输入maxlength为11。输入10个数字后,如果输入了某些键(0-9除外),则表单将被验证
查看组件
你能帮我解决我的问题吗?你应该用
键控处理程序替换输入处理程序。然后,如果钥匙是好的,什么也不做,否则,阻止事件发生
问题是,如果您收听输入事件,则为时已晚,ngModel
将被更新,因此您必须收听keydown
事件并对其进行适当过滤
@HostListener('keydown', ['$event']) onKeyDown(e: KeyboardEvent) {
if (this.specialKeys.indexOf(e.key) !== -1 || new RegExp(/[0-9]/g).test(e.key)) {
return;
}
e.preventDefault();
}
我在你的stackblitz演示中测试了这段代码,效果很好
编辑:您提到您不能使用按键处理程序,对不起
我设法让它与
元素上的oninput
处理程序一起工作,并删除了您对输入的指令:
<div class = "form-group">
<label class = "form-control-label label-color" for = "citizenNumber">Citizen Number
</label>
<input type = "text"
class = "form-control input-css"
name = "citizenNumber"
id = "citizenNumber"
#citizenNumber="ngModel"
oninput="this.value = this.value.replace(/[^0-9]/g, '');"
[(ngModel)] = "value"
[placeholder] = "placeholder"
minlength = "11"
maxlength = "11"
[required] = "required">
<div *ngIf = "citizenNumber.invalid && (citizenNumber.dirty || citizenNumber.touched)"
class = "form-text text-danger">
<small *ngIf = "citizenNumber.errors.required">This field is required.</small>
<small *ngIf = "citizenNumber.errors.minlength">This field must be 11 characters.</small>
<small *ngIf = "citizenNumber.errors.invalidTc">This is not a citizen number</small>
</div>
</div>
公民号
此字段必填。
此字段必须为11个字符。
这不是公民号码
这里是一个更新的
希望有帮助 谢谢你的回答。我也试过按键,我知道它是有效的。我的问题是,keydown和keyup在android chrome上不起作用。由于它是一个网站,通常在mobileOk上使用。我会看一看,通过在您的值设置程序中进行一些筛选,它似乎在您的stackblitzString.replace中运行良好。因此,多次按将输入的值。我不明白您的意思,通过这样的过滤,我无法输入任何字母string。每次调用setter时都会调用replace,也就是说,每次输入字母时,如果您在其中粘贴包含字母的字符串,它也会起作用。我添加了一个更新的stackblitz,你有错误吗?问题是我使用公民号组件的形式。如果您查看app.component html,则当您在输入10个数字后输入字符串值时,父窗体将有效,尽管ngModel不会更改。