ng-model无法使用Chrome OS上的屏幕键盘进行更新

时间:2018-03-05 05:29:39

标签: angularjs google-chrome-os

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

在我的角度组件中,我有一个绑定到属性的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事件在角度代码中非常重要。 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

1 个答案:

答案 0 :(得分:1)

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

<小时/> 我在chrome bug跟踪论坛上发布了一段我的经验视频。

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

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

  

这是设计的。 Android键盘应用在Android上的行为相同。   视频录制中的合成文本是&#34; a&#34;具有下划线效果。 &#34; compositionend&#34;事件将在带下划线的文本被提交之后出现,例如SPACE键。

     

在您的应用程序中,如果您不希望IME / VK在输入字段中设置合成文本,请设置属性&#34; autocorrect = false&#34; [sic]到输入元素或内容可编辑元素。