Dipak chavda Dipak chavda - 4 months ago 26
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

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.