Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Update AngularJS models from a jQuery plugin with a "on change" callback

I'm building a web app for a touch screen computer which needs an on-screen keyboard and am attempting to use this excellent (or the least the only one I was able to find that wasn't terrible) keyboard. https://github.com/Mottie/Keyboard/

The problem is, as you might have guessed already, that the model doesn't get updated when using the on-screen keyboard. This is my code, which sort of works but it all sorts of ugly:

The partitial HTML:

<input type="text" class="keyboard" ng-model="newUser.name">
<input type="text" class="keyboard" ng-model="newUser.email>

Initializing the keyboard, from the partitial page controller:

$('.keyboard')
.keyboard({
    stickyShift: false,
    usePreview: false,
    autoAccept: true,

    change: function(e, kb, el) {
        $scope.newUser.name = el.value;
    }
});

So on change triggered by the jQuery plugin I can run something. Obviously this only works updating a single field/model, the name one (while the email one doesn't work at all and will overwrite the name field), I need any number of fields to be updated when used with the keyboard, and the correct one. How do I solve this in a less terrible, not hardcoded (if possible and not too complex) way?

like image 826
not amused Avatar asked Mar 21 '13 12:03

not amused


2 Answers

The way to write this in Angular is to actually write a directive. You can assosciate a directive with a particular class name.

So, your directive would look something like

app.directive('keyboard',function(){
  return {
    require : '?ngModel',
    restrict : 'C',
    link : function(scope,element,attrs,ngModelCtrl){
      if(!ngModelCtrl){
        return;
      }
      $(element).keyboard({
        stickyShift: false,
        usePreview: false,
        autoAccept: true,

        change: function(e, kb, el) {
            ngModelCtrl.$setViewValue(el.value);
        }
    });
    }
  };
});

Now if any element has both a class of keyboard and ng-Model defined then, your keyboard should pop-up. Hope this helps.

like image 102
ganaraj Avatar answered Oct 14 '22 06:10

ganaraj


I made modification of ganraj directive. Now the model is updating on every click of keyboard button.

app.directive('keyboard',function(){
  return {
    require : '?ngModel',
    restrict : 'C',
    link : function(scope,element,attrs,ngModelCtrl){
      if(!ngModelCtrl){
        return;
      }

      $(element).keyboard({
        stickyShift: false,
        usePreview: false,
        autoAccept: true,

        change: function(e, kb, el) {
            if(!scope.$$phase && !scope.$root.$$phase)
            {
                scope.$apply(function(){
                    ngModelCtrl.$setViewValue(el.value);
                }); 
            }
        }
    });
    }
  };
});
like image 2
Wojtek Avatar answered Oct 14 '22 04:10

Wojtek