Chrome OS 上的屏幕键盘未更新 ng-model

ng-model not updating with on-screen keyboard on Chrome OS

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

在我的 angular 组件中,我有一个 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 屏幕键盘有些不同:

当我通过键盘输入 '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;
     // ...
  }

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

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

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


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

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.