AngularJS: trigger ng-change, ng-keyup or $ scope. $ Watch when composing Korean characters

I am creating a Korean vocabulary textbook and I want to compare user input with people type.

In Korean and some other Asian languages, you create letters with several keyboard events. In Chrome, $ scope. $ Watch, ng-keyup and ng-change work only after the letter is completely composed and a new letter or space is entered. I do not mind that AngularJS does not start anything until the last letter is fully composed, but as soon as the letter is completed, it should be launched without the need to add a space or start the next word.

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:

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

Example:

 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: 감 
+5
source share
3 answers

As explained by a helpful member of the Angular team, all triggers are intentionally suppressed when composing characters. More details here .

As suggested, I created a custom directive that manually updates the model when composing characters:

Directive

 (function() { 'use strict'; angular.module('myApp', []) // Angular ng-change, ng-keyup and $scope.$watch don't get triggered // while composing (eg 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(); }); } }; }); })(); 

Controller: (as suggested by 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> 

Update

I had to change the code to the following to work in FireFox (Chrome and Safari work fine with the code above).

Directive

 (function() { 'use strict'; angular.module('myApp', []) // Angular ng-change, ng-keyup and $scope.$watch don't get triggered // while composing (eg 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 }); }); } }; }); })(); 

Controller:

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

HTML (note that any argument passed must be specified in 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> 
+3
source

I found this error in Angular.js 1.2.27, I tried other versions, but I did not have any problems. But I found a solution, and that will solve your problem.

Take a look at this solution 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'); } }; }); 

This is an example . Just open the console and enter 한글 in the input field.

+2
source

Using $watch , you can catch all model updates:

Working example ( 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); }); } 

And for reference, it seems you could use ng-model-options and assign compositionupdate -event updateOn . I had no luck with this and instead resorted to the $ clock.

+1
source

Source: https://habr.com/ru/post/1209942/


All Articles