简体   繁体   中英

How to pass value back from angularjs directive scope with javascript event

What I m trying to accomplish: I have jQuery plugin that I want to wrap to be an angular directive. And to do this i need to pass params to it, and the plugin have it own m trying to accomplish: I have jQuery plugin that I want to wrap to be an angular directive. And to do this i need to pass params to it, and the plugin have it own onchange` even where I'm trying to change passed values so it will be reflected in the original scope. And I get some really unexpected and strange results. Here is fiddle number one:

http://jsfiddle.net/q1915b38/2/

Here I tried to simulate minimal example of what i want to accomplish. But as you see it just does not work at all. Value in the original controller scope doesn't change. But in real world example it act a bit differently. And here goes fiddle number 2.

http://jsfiddle.net/ne5hbgxp/

The only thing i changed from first one is template from template:

template: "<input type='text' id='blah' />",

to

template: "<input type='text' id='blah' ng-model='abc' />",

Basically i added to template an ng-model attribute which I don't use anywhere at all. But it just goes from totally not working to working with glitches. Now when change trigger first time nothing happens. But when it triggers second time - value from previous change got passed into original scope. When I change 3 time value - the value from second time goes to controller. And so on. So basically it have a delay with one step back for unknown for me reason. And this is exact behavior that I face in my real world example, although there no ng-model at all and all content generate via jQuery plugin.

So basically my questions are following:

1) Why its not working in first example

2) Why its working in second example with this strange behavior with one step delay? What the logic on this behavior?

3) What is a correct way to solve this ?

Since you're using jQuery to update something in your directive, a call to $apply() is needed to trigger an angular digest cycle

link: function(scope, iElement, iAttrs, controller) {
    $('#blah').change(function() {
        scope.value = $(this).val();
        scope.$apply();
    });
}

JSFiddle Link

However looking at this a bit closer, is there a reason why you prefer jQuery .change() in this example? Angular offers ngChange , which may be just what you are looking for, since you will be alleviated from explicitly calling a digest cycle since we're in Angular world and not battling jQuery so to speak. An example may include...

<input type='text' id='blah' ng-model='abc' ng-change='update()'/>

scope.update = function() {
    scope.value = scope.abc;
}

JSFiddle Link with ng-change

Issue is pretty simple... events that change scope that are outside of angular's core directives aren't visible to angular so you you need to notify angular to perform a digest so the view can be updated.

This is done with $apply() or can use $timeout() to prevent calling $apply() while another digest cycle is in progress

    link: function (scope, iElement, iAttrs, controller) {
        $('#blah').change(function () {
            var $el =$(this);
            scope.$apply(function () {
                scope.value = $el.val();
            })
        });
    }

I would suggest taking advantage of the iElement being exposed in the directive. This is a jQuery object when jQuery is included in page prior to angular

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM