在运行时覆盖 angularjs 指令

Posted

技术标签:

【中文标题】在运行时覆盖 angularjs 指令【英文标题】:Overriding angularjs directive at runtime 【发布时间】:2021-11-21 00:08:10 【问题描述】:

我想在我的单页应用程序中。可能吗? 这是我的第一页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) //
);

这是我的第二页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)//
);

但是通过ngRoute路由时,我一个一个打开了两个页面,两个指令都在appGML._invokeQueue中,只执行了第一个指令。

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'])
     )
);

输出是

first page

禁用第一个指令并用新指令覆盖它是否可行? 提前致谢

【问题讨论】:

【参考方案1】:

感谢您为我的问题伙伴花费宝贵的时间。 我通过添加嵌套指令来克服这个问题

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

这是我的嵌套指令

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


)

然后我重命名了我的嵌套指令

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

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

【讨论】:

以上是关于在运行时覆盖 angularjs 指令的主要内容,如果未能解决你的问题,请参考以下文章

AngularJS指令客户端运行不正常

在运行时更改AngularJs中背景图像的最佳方法

AngularJS:不要在 DOM 更改时运行 ng-repeat

AngularJs 指令

Dockerfile 指令

AngularJS 指令链接功能在 Jasmine 测试中不运行