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
});