AngularJS:在组成韩文字符时触发ng-change,ng-keyup或$ scope.$ watch

mig*_*igu 7 javascript angularjs

我正在建立一个韩语词汇训练师,我想比较人们输入的用户输入.

在韩语和其他一些亚洲语言中,您可以使用多个键盘事件撰写字母.在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>
Run Code Online (Sandbox Code Playgroud)

控制器:

.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);        

  };     
]);        
Run Code Online (Sandbox Code Playgroud)

例:

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: ?                  
Run Code Online (Sandbox Code Playgroud)

mig*_*igu 4

正如 Angular 团队的一位乐于助人的成员所解释的那样,在编写角色时,所有触发器都被有意抑制。更多详细信息请参见此处

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

指示:

(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();       
        });
      }
    };
  });  
})();
Run Code Online (Sandbox Code Playgroud)

控制器:(按照ippi的建议)

$scope.$watch('quizzesCtrl.answer', function (answer) {
  console.log(answer);
});
Run Code Online (Sandbox Code Playgroud)

HTML:

<form ng-controller="QuizzesController as quizzesCtrl">
  <input cst-input name="answer" id="answer" ng-model="quizzesCtrl.answer" type="text" />
</form>
Run Code Online (Sandbox Code Playgroud)

更新

我必须将代码更改为以下内容才能使其在 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
          });
        });
      }
    };
  });

})();
Run Code Online (Sandbox Code Playgroud)

控制器:

this.checkAnswer = function (answer) {        
  if (answer === this.quiz.answer) {        
    this.isCorrect = true; 
  }
};
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)