Home > database >  Overriding angularjs directive at runtime
Overriding angularjs directive at runtime

Time:10-02

I want to override angularjs directive at runtime in my single page application. Is it possible? This is my first page js:

appGML.directive('singleSelectKeyUp', function ($resource, $compile, $parse, $timeout, $http, $document,$q) {
return {
    restrict: 'A',
    require: 'ngModel',
    scope: {
        singleSelectKeyUp: '='
    },
    link: function (scope, element, attr, ngModel) {
        return scope.$watch(function () {

            return ngModel.$modelValue;
        }, function (name) {
             console.log('first page');
        });
    };
});
appGML.controller("Pay_tra_advertisementController", function ($sce, $compile, $timeout, $scope, $uibModal, $parse, $http, Upload, $mdBottomSheet, $q) {//
});

This is my secondpage js:

appGML.directive('singleSelectKeyUp', function ($resource, $compile, $parse, $timeout, $http, $document,$q) {
return {
    restrict: 'A',
    require: 'ngModel',
    link: function (scope, element, attr, ngModel) {
        return scope.$watch(function () {

            return ngModel.$modelValue;
        }, function (name) {
             console.log('second page');
        });
    };
});
appGML.controller("Pro_tra_boqController", function ($q, $compile, $scope, $http, $parse, $uibModal, Upload, $timeout){//
});

but while routing by ngRoute, I opened two pages one by one, Both directives are in appGML._invokeQueue, and only first directive is executed.

appGML.config(function ($provide,$routeProvider, $ocLazyLoadProvider, $locationProvider, $controllerProvider, $compileProvider/*, $urlMatcherFactoryProvider, $stateProvider*//*, $urlRouterProvider*/) {
    appGML.controller = $controllerProvider.register;
    appGML.directive = $compileProvider.directive;
    function loadScript(path) {
    var result = $.Deferred(),
        script = document.createElement("script");
    script.async = "async";
    script.type = "text/javascript";
    script.src = path;
    script.onload = script.onreadystatechange = function (_, isAbort) {
        if (!script.readyState || /loaded|complete/.test(script.readyState)) {
            if (isAbort)
                result.reject();
            else
                result.resolve();
        }
    };
    script.onerror = function () { result.reject(); };
    document.querySelector("head").appendChild(script);
    return result.promise();
    }
    function loader(arrayName) {

    return {
        load: function ($q) {
            var deferred = $q.defer(),
                map = arrayName.map(function (name) {
                    return loadScript('/JSController'   name   ".js");
                });
            $provide.decorator('singleSelectKeyUpDirective', ['$delegate', function ($delegate) {
                //$delegate is array of all ng-click directive
                //in this case first one is angular buildin ng-click
                //so we remove it.
                console.log('load:sskuL', $delegate);
                //$delegate.shift();
                return $delegate;
            }]);
            $q.all(map).then(function (r) {
                deferred.resolve();
            });

            return deferred.promise;
        }
    };
}
    $routeProvider.when('/PayModule/Pay_tra_advertisement', {
        templateUrl: '/PayModule/Pay_tra_advertisement',
        controller: 'Pay_tra_advertisementController',
        resolve: loader(['/PayModule/Pay_tra_advertisement'])
    })
        .when('/ProModule/Pro_tra_boq', {
        templateUrl: '/ProModule/Pro_tra_boq',
        controller: 'Pro_tra_boqController',
        resolve: loader(['/ProModule/Pro_tra_boq'])
     })
});

Output is

first page

Is it feasible to disable first directive and override it with new directive? Thanks in advance

CodePudding user response:

Thanks for spending your valuable time for my question mates. I overcome this by adding nested directives

appGML.config(function ($provide, $routeProvider, $ocLazyLoadProvider, $locationProvider, $controllerProvider, $compileProvider/*, $urlMatcherFactoryProvider, $stateProvider*//*, $urlRouterProvider*/) {
$provide.decorator('$controller', [
    '$delegate',
    function ($delegate) {
        return function (constructor, locals) {
            if (typeof constructor == "string") {
                locals.$scope.controllerName = constructor;
            }

            return $delegate.apply(this, [].slice.call(arguments));
        }
    }]);
//.... other routing codes
});

and this is my nesting directive

appGML.directive('containerDirective', function ($compile,$location) {
return {
    restrict: 'AE',
    link: function (scope, elem, attrs, ctrl) {
        //if (elem.closest('form').attr('id') == 'Advertisementfrm') {
        //    elem.attr('single-select-key-up-adv', '');
        //}
        //if (elem.closest('form').attr('id') == 'Boqdiv') {
        //    elem.attr('single-select-key-up-boq', '');
        //}
        if (scope.$parent.$parent.$parent.controllerName == 'Pay_tra_advertisementController') {
            elem.attr('single-select-key-up-adv', '');
        }
        if (scope.$parent.$parent.$parent.controllerName == 'Pro_tra_boqController') {
            elem.attr('single-select-key-up-boq', '');
        }
        elem.removeAttr('container-directive');
        $compile(elem)(scope);
    }

}
})

Then I renamed my nested directives

appGML.directive('singleSelectKeyUpAdv', function ($resource, $compile, $parse, $timeout, $http, $document, $q){
//old code
});

and

appGML.directive('singleSelectKeyUpBoq', function ($resource, $compile, $parse, $timeout, $http, $document) {   
//old code
});
  • Related