如何区分日期输入中的鼠标选择和键盘事件

Ris*_*cie 2 html javascript angular

我试图在日期类型的输入中区分鼠标和键盘输入:

模板

<input type="date" (change)="onChange($event)">
Run Code Online (Sandbox Code Playgroud)

控制器

import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {

  onChange(event) {
    // How to check if user used the mouse to select a date
    // or if he typed a date
    console.log(event);
  }
}

Run Code Online (Sandbox Code Playgroud)

最简单的 stackblitz:https ://stackblitz.com/edit/angular-zz2nbl

是否可以?我需要订阅多个不同的事件吗?

Man*_*ish 5

首先是MDN 中的事件click定义change

点击事件

当指针位于元素内部时按下并释放定点设备按钮(例如鼠标的主鼠标按钮)时,元素会接收单击事件。

变更事件

当用户提交对元素值的更改时,将针对<input><select>和元素触发更改事件。<textarea>与输入事件不同,更改事件不一定会针对元素值的每次更改而触发。

现在,如果您看到单击事件适用于所有元素,但更改仅适用于input , select and textarea. 从定义中也可以清楚地看出,当元素的值发生更改/改变时,后者会被触发。

因此,为了捕获这两个事件,是的,您必须分别捕获这两个事件,如下所示。

<input type="date" #input [ngModel]="myInput" (change)="onChange($event)" (click)="onClick($event)" (keydown)="onKeydown($event)" >


export class AppComponent {
  isKeyboardChange: boolean;
  isDatepickerChange: boolean;

  onChange(event) {
    // How to check if user used the mouse to select a date
    // or if he typed a date
    console.log(event.type);
    if (this.isKeyboardChange) {
      console.log("Was changes using Keyboard");
    }

    if (this.isDatepickerChange) {
      console.log("Was changes using date picker");
    }
  }

  onClick(event) {
    this.isKeyboardChange = false;
    this.isDatepickerChange = true;
  }

  onKeydown(event) {
    this.isDatepickerChange = false;
    this.isKeyboardChange = true;
  }
}
Run Code Online (Sandbox Code Playgroud)

通过上面的代码你也会看到。当用户单击输入(无论是日期还是箭头)时,控制台上记录的值将是 bee click,当他选择与当前值不同的值时,记录的值将是change

input此外,如果您使用选项卡在元素之间移动,click则事件不会触发,在这种情况下focus将被触发。

Javascript 事件:这是所有 HTML 元素可用的事件列表。这不包括更改事件,因为它仅适用于inputselecttextarea

因此,对您问题的简短回答是,您想要捕获的每种类型的事件都必须有一个相应的eventListener/ eventHandler

更新:在这种情况下,您可能想要使用keydown每当按下键盘键时触发的事件。因此,在这种情况下,当用户使用键盘更改值时,keydown将在更改事件之前触发一个事件,并且每当焦点位于输入上时按下一个键,否则如果用户使用日期选择器,click将在更改之前触发该事件。此外,当用户选择日期时,不会触发任何点击,只有当用户单击文本框打开选择器时才会触发。因此,使用这些您将能够弄清楚该值是如何更改的。

UPDATE2:编辑为使用keydown事件而不是keypress因为按键不捕获箭头键,并且date也可以使用箭头键更改输入类型。

更新3:

浏览器兼容性:

  1. 铬:好的
  2. 火狐浏览器:好的
  3. Safari:不支持日期选择器
  4. IE:不支持日期选择器
  5. Edge:仅支持日期选择器。但是当日期选择器打开时,允许箭头键更改日期(这种特定情况需要单独处理,因为用户实际上正在使用日期选择器,但箭头键可能会给人一种错误的印象)

下面是一个相同的小演示(不是角度),但其行为与角度完全相同。原理完全相同。已更新 stackblitz 演示,它记录了用户用于更改值(即键盘或日期选择器)的方式。

Stackblitz 演示

<input type="date" #input [ngModel]="myInput" (change)="onChange($event)" (click)="onClick($event)" (keydown)="onKeydown($event)" >


export class AppComponent {
  isKeyboardChange: boolean;
  isDatepickerChange: boolean;

  onChange(event) {
    // How to check if user used the mouse to select a date
    // or if he typed a date
    console.log(event.type);
    if (this.isKeyboardChange) {
      console.log("Was changes using Keyboard");
    }

    if (this.isDatepickerChange) {
      console.log("Was changes using date picker");
    }
  }

  onClick(event) {
    this.isKeyboardChange = false;
    this.isDatepickerChange = true;
  }

  onKeydown(event) {
    this.isDatepickerChange = false;
    this.isKeyboardChange = true;
  }
}
Run Code Online (Sandbox Code Playgroud)
function onChange(event) {
  console.log(event.type)
}

function onClick(event) {
  console.log(event.type)
}

function onFocus(event) {
  console.log(event.type)
}


function onKeypress(event) {
  console.log(event.type)
}
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助 :)