angularjs - ng-model 未使用 Chrome 操作系统上的屏幕键盘更新

标签 angularjs google-chrome-os

当您选择输入时,ChromeOS 设备会显示一个虚拟键盘。

在我的 Angular 组件中,我有一个绑定(bind)到属性的 input 控件:

<input type="text" ng-model="$ctrl.searchText" />

我希望它通过触摸屏工作。 如果我在控件中单击,则会出现触摸屏键盘。

我按下触摸键,字母出现在输入中,但是 set searchText 方法在文本框失去焦点之前不会被调用。

如果我插入 USB 键盘并输入文本,set searchText 方法会针对每个新字符调用。它只是在屏幕触摸键盘上失败了。

我尝试使用 ngModelOptions 设置不同的选项:

<input type="text" ng-model="$ctrl.searchText" ng-model-options="{updateOn: 'keyup keydown default blur click touch touchup touchdown'}" /> 

这不会改变行为。


我已经创建了我可以使用 Plunker 的最简单的示例。果然,如果我在 Chrome 设备上浏览该站点并使用触摸键盘,则该值不会在您添加文本时更新。但如果我使用 USB 键盘,它会更新。

http://embed.plnkr.co/bIwMp88BB8gNHFenayfz/


我找到了 this Keyboard Event Viewer utility它打印出键盘相关事件的确切顺序。

我注意到 chrome 屏幕键盘有些不同:

  • keyup 事件触发,key 值设置为未识别。
  • 屏幕键盘会触发额外的事件:compositionstartcompositionupdate,但在 compositionend 事件周围似乎不稳定。

当我通过键盘输入“a”键时,将触发以下事件:

| Event type        | data | Input Field |
|-------------------|------|-------------|
| keydown           |      | ''          |
| keypress          |      | ''          |
| beforeinput       | 'a'  | ''          |
| input             | 'a'  | 'a'         |
| keyup             |      | 'a'         |

当我使用触摸屏输入“a”键时,将触发以下事件。这些是相同的事件,但添加了 compositionstartcompositionupdate 事件。

| Event type        | data | Input Field |
|-------------------|------|-------------|
| keydown           |      | ''          |
| compositionstart  |      | ''          |
| beforeinput       | 'a'  | ''          |
| compositionupdate | 'a'  | ''          |
| input             | 'a'  | 'a'         |
| keyup             |      | 'a'         |

它需要触发 compositionend 事件。但事实并非如此!

composition 事件在 Angular 代码中非常重要。 relevant code在 input.js 中,它将任何处理推迟到 compositionend 事件:

   // In composition mode, users are still inputting intermediate text buffer,
  // hold the listener until composition is done.
  // More about composition events: https://developer.mozilla.org/en-US/docs/Web/API/CompositionEvent
  if (!$sniffer.android) {
    var composing = false;

    element.on('compositionstart', function() {
      composing = true;
    });

    // Support: IE9+
    element.on('compositionupdate', function(ev) {
      // End composition when ev.data is empty string on 'compositionupdate' event.
      // When the input de-focusses (e.g. by clicking away), IE triggers 'compositionupdate'
      // instead of 'compositionend'.
      if (isUndefined(ev.data) || ev.data === '') {
        composing = false;
      }
    });

    element.on('compositionend', function() {
      composing = false;
      listener();
    });
  }

  //....

  var listener = function(ev) {
     // ...
     if (composing) return;
     // ...
  }

我已将此作为缺陷提交给谷歌:

Entering character with on-screen keyboard fails to trigger 'compositionend' event

最佳答案

快速回答:将属性 autocorrect='off' 添加到输入元素。


我在 chrome bug 跟踪论坛上发布了我的体验视频。

https://bugs.chromium.org/p/chromium/issues/detail?id=818881

以下是 chrome 开发团队的回复:

This is by design. Same behavior on Android with Android keyboard apps. The composition text in the case in the video recording is "a" with the underline effect. "compositionend" event will appear after the underlined text is committed by, e.g. SPACE key.

In your application, if you don't want IME/VK to set composition text in your input field, please set the attribute "autocorrect=false" [sic] to the input element or content editable element.

关于angularjs - ng-model 未使用 Chrome 操作系统上的屏幕键盘更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49103988/

相关文章:

angularjs - ngModel : constexpr error in my angularjs app, 但 jsfiddle 上的相同代码很好

javascript - AngularJS - 条件逻辑不会在链接单击时重新显示原始数据

javascript - 使用 AngularJS 自定义过滤器根据另一个集合过滤一个集合

javascript - 500 错误状态 : using angular js and codeigniter 2. 2

android - 如何找到运行 Android 应用程序的 ChromeOS 版本?

android - 在 Chrome 操作系统中部署 APK。有可能的?

linux - 删除 Google Cloud 项目中对密码 key 的需求

javascript - fromJson() 中的 AngularJS 意外标记

virtualbox - 如何在 VM (virtualbox) 中运行的 Chromium OS 上启用开发人员模式

javascript - 删除全屏窗口装饰/边框 Chrome OS 应用程序/信息亭模式