11

Here is my problem. For example, we have the following directive, which uses some jQuery widget behind the scenes :

module.directive('myWidget', [function() {
    return {
        require: "ngModel",
        restrict: "A",
        replace: true,
        templateUrl: "templates/myWidget.html",
        link: function(scope, element, attrs, ctrl) {
            element.widget_name().on('value_updated', function(event) {
                scope.$apply(function() {
                    var newModelValue = event.some_value;
                    ctrl.$setViewValue(newModelValue);
                });
            });

            scope.$watch(attrs["ngModel"], function(value){
                element.widget_name('set_value', value);
            });
        }
    };
}]);

So, if model's value changes, then the handler which is registered using $watch to listen for changes in model will be executed, and, consequently, widget's 'set_value' method will be executed too. This means that 'value_updated' event will be triggered.

My question is: what is the best practice to implement similar behavior in directives to avoid extra calls of DOM event handlers and watchers?

1 Answer 1

4

Instead of scope.$watch(), I suggest implementing ctrl.$render(). $render should only be called if something inside Angular changes the model. Fiddle example.

This solves a problem you did not mention. Unfortunately, it does not solve the problem you did mention. In the fiddle, a blur event is bound, rather than some widget.on() event. Maybe that would work for you – i.e., only update the model on blur, rather than every keystroke (this assumes your widget is accepting keystrokes, however).

Maybe you could also ask the widget author to provide a "set" method that does not trigger an event. Then that could be used in the $render() method.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks Mark, your solution is perfectly solves my problem. But could you please tell - when that is appropriate to use watchers and when $render implementation?
@oaleynik, $render() should be implemented whenever you want to do something because an ng-model value was changed inside Angular. ng-model automatically sets up the watch for us, and $render() is called if it notices a change. So normally, with ng-model, you want to implement $render instead of using your own $watch.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.