【问题标题】:AngularJS: trigger ng-change, ng-keyup or $scope.$watch while composing Korean charactersAngularJS:在编写韩文字符时触发 ng-change、ng-keyup 或 $scope.$watch
【发布时间】:2014-12-26 23:55:35
【问题描述】:

我正在构建一个韩语词汇训练器,我想比较用户输入作为人们输入的内容。

在韩语和其他一些亚洲语言中,您可以使用多个键位事件来编写字母。在 Chrome 中,$scope.$watch、ng-keyup 和 ng-change 仅在字母完全组成并且输入新字母或空格后才会触发。我不介意 AngularJS 在最后一个字母完全组成之前不会触发任何东西,但是一旦字母完成,它应该触发而无需添加空格或开始下一个单词。

HTML:

<form name="forms.vocabularyForm">
  <input name="answer" id="answer" ng-model="vocabularyCtrl.answer" ng-change="vocabularyCtrl.checkChange()" ng-keyup="vocabularyCtrl.checkKeyUp($event)" type="text" />
</form>

控制器:

.controller('VocabularyCtrl', [
  '$scope',
  '$location',
  function($scope, $location) {

    this.checkChange = function () {
      console.log("answer change: " + this.answer); 
    };

    this.checkKeyUp = function ($event) {
      console.log("answer keyUp: " + this.answer);
    };

    $scope.$watch('vocabularyCtrl.answer', function (answerNew, answerOld) {        
      console.log('answerOld: ' + answerOld + ', answerNew: ' + answerNew);         
    }, true);        

  };     
]);        

例子:

Input: ㄱ 
Console:
answerOld: , answerNew:
answer keyUp:

Input: 가
Console:
answerOld: , answerNew:    
answer keyUp:

Input: 감 (character is now fully composed)
Console:
answerOld: , answerNew:    
answer keyUp:

Input: 감ㅅ (starting the next character, same behaviour with space bar)
Console:
answerOld: 감, answerNew:
answer change: 감
answer keyUp: 감                  

【问题讨论】:

  • 是否可以在 key up 上运行?
  • Keyup 触发,但在字母形成之前返回一个空字符串
  • 使用ng-keyup会使chrome捕捉所有变化,但firefox和IE拒绝播放。

标签: javascript angularjs


【解决方案1】:

正如 Angular 团队的一位乐于助人的成员所解释的,在编写角色时,所有触发器都会被有意抑制。更多详情here.

按照建议,我创建了一个自定义指令,可以在编写字符时手动更新模型:

指令:

(function() {
  'use strict';

  angular.module('myApp', [])

  // Angular's ng-change, ng-keyup and $scope.$watch don't get triggered
  // while composing (e.g. when writing Korean syllables).
  // See: https://github.com/angular/angular.js/issues/10588  
  // This custom directive uses element.on('input') instead, which gets
  // triggered while composing.
  .directive('cstInput', function() {
    return {
      restrict: 'A',
      require: '^ngModel',
      scope: {
        ngModel: '=', // sync model
      },      
      link: function (scope, element, attrs, ngModel) {
        element.on('input', function() {          
          scope.ngModel = element.val();       
        });
      }
    };
  });  
})();

控制器:(由 ippi 建议)

$scope.$watch('quizzesCtrl.answer', function (answer) {
  console.log(answer);
});

HTML:

<form ng-controller="QuizzesController as quizzesCtrl">
  <input cst-input name="answer" id="answer" ng-model="quizzesCtrl.answer" type="text" />
</form>

更新

我必须将代码更改为以下代码才能使其在 FireFox 中运行(Chrome 和 Safari 可以正常使用上面的代码)。

指令:

(function() {
  'use strict';

  angular.module('myApp', [])

  // Angular's ng-change, ng-keyup and $scope.$watch don't get triggered
  // while composing (e.g. when writing Korean syllables).
  // See: https://github.com/angular/angular.js/issues/10588  
  // This custom directive uses element.on('input') instead, which gets
  // triggered while composing.
  .directive('cstInput', function() {
    return {
      restrict: 'A',
      require: '^ngModel',    
      link: function (scope, element, attrs, ngModel) {
        element.on('input', function() {                  
          scope.$apply(function(){            
            scope.ngModel = element.val();
            scope.$eval(attrs.cstInput, {'answer': scope.ngModel}); // only works if no scope has been defined in directive
          });
        });
      }
    };
  });

})();

控制器:

this.checkAnswer = function (answer) {        
  if (answer === this.quiz.answer) {        
    this.isCorrect = true; 
  }
};

HTML(注意任何传入的参数都需要在 cst-input-callback 中列出):

<form ng-controller="QuizzesController as quizzesCtrl">
  <input cst-input="quizzesCtrl.checkAnswer(answer)" ng-model="quizzesCtrl.answer" name="answer" id="answer" type="text" />
</form>

【讨论】:

    【解决方案2】:

    我在 Angular.js 1.2.27 中发现了这个错误,我尝试了其他版本但我找不到任何问题。但我找到了解决方案,这将解决您的问题。

    看看这个解决方案 https://github.com/mbenford/ngTagsInput/issues/303

    angular.module('angularApp')
    .directive('ignoreCompositionEvent', function () {
        return {
            restrict: 'A',
            link: function postLink(scope, element) {
                //element.val('this is the ignoreCompositionEvent directive');
                element.off('compositionstart').off('compositionend');
            }
        };
    });
    

    这是一个 example 。只需打开您的控制台并在 Input 中输入 한글。

    【讨论】:

    • 我想给你+100!这是适用于任何地方的完美解决方案!
    【解决方案3】:

    使用$watch,您将能够捕获模型的所有更新:

    工作示例 (jsfiddle):

    HTML:

    <div ng-app ng-controller="myctrl">
        <input type="text" ng-model="answer" />
    </div>
    

    JS:

    function myctrl($scope) {
        $scope.$watch('answer',function(oldVal,newVal){
            console.log(oldVal,newVal);
        });
    }
    

    作为参考,看起来可以使用ng-model-options 并将compositionupdate-事件分配给updateOn。我没有运气,而是使用了 $watch。

    【讨论】:

    猜你喜欢
    • 2015-03-08
    • 2015-04-03
    • 2016-12-09
    • 1970-01-01
    • 1970-01-01
    • 2018-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多