Dipak chavda Dipak chavda - 1 year ago 68
AngularJS Question

AngularJS directive calls multiple time rather than to call a single time

I have created a directive for textarea which allows to edit data manipulation. In a form there are multiple textarea which as same directive. And when I trigger any event it traverse all elements which has assign directive.

Eg.There are 10 textarea fields and having directive "HzAutosave". Then when I trigger click on particular textarea it returns particular textarea's value, but it triggers socket io event to send data to server 10 times, whether there is only changes in a single field.


Directive


.directive("hzAutoSaveTextarea", ['$timeout', '$interval', 'HzSocket', function ($timeout, $interval, HzSocket) {
var currentElement = null;
return {
restrict: "E",
replace: true,
require: "ngModel",
scope: {},
template: "<textarea></textarea>",
compile: function (scope, element) {
return {
pre: function (scope, element, attrs) {
element.on("click", function (e) {
e.preventDefault();
currentElement = attrs.id;
console.log("focused element:" + currentElement);
angular.element(".autosave").removeClass("active-element");
element.addClass("active-element");
});
},
post: function (scope, element, attrs) {
var currentVal = null, previousVal = null;
$interval(function () {
currentVal = angular.element(".active-element").val();
if (null !== currentVal && undefined !== currentVal && "" !== currentVal) {
console.log("value::" + angular.element(".active-element").val());
if (previousVal !== currentVal) {
console.log("save data to console");
previousVal = currentVal;
var socket = io();
var data = {module: "photo", element: currentElement, value: currentVal};
HzSocket.emit('autosave', data);
}
}
}, 3000);

}
}
},
link: function (scope, element, attrs, ngModel) {

}
}
}]);



HTML


<hz-auto-save-textarea ng-model="asContainer" placeholder="Description" id="{{result.photo_id}}" class="album_commentarea margin_top5 autosave"></hz-auto-save-textarea>


I don't know how to prevent triggering multiple time socket request and other qualified events of JavaScript.

Answer Source

Move the autosave logic to the directive factory function which is executed only once:

.directive("hzAutoSaveTextarea", ['$timeout', '$interval', 'HzSocket', function ($timeout, $interval, HzSocket) {
    var currentElement = null;

    var currentVal = null, previousVal = null;
    $interval(function () {
        currentVal = angular.element(".active-element").val();
        if (null !== currentVal && undefined !== currentVal && "" !== currentVal) {
            console.log("value::" + angular.element(".active-element").val());
            if (previousVal !== currentVal) {
                console.log("save data to console");
                previousVal = currentVal;
                var socket = io();
                var data = {module: "photo", element: currentElement, value: currentVal};
                HzSocket.emit('autosave', data);
            }
        }
    }, 3000);

    return {
        restrict: "E",
        replace: true,
        require: "ngModel",
        scope: {},
        template: "<textarea></textarea>",
        compile: function (scope, element) {
            return {
                pre: function (scope, element, attrs) {
                    element.on("click", function (e) {
                        e.preventDefault();
                        currentElement = attrs.id;
                        console.log("focused element:" + currentElement);
                        angular.element(".autosave").removeClass("active-element");
                        element.addClass("active-element");
                    });
                },
                post: function (scope, element, attrs) {
                }
            }
        }
    }
}]);

This way only one $interval will be setup which is what you need.