Angular 1.6 & multiple modules: sharing global variable between modules & components

你说的曾经没有我的故事 提交于 2019-12-11 11:34:05

问题


I'm using Angular 1.6.7. I have created multiple modules in my app. How can I pass a constant (e.g. "rootURL") defined in a parent module (myApp) to a child module (childApp)? More specifically, I need to assign the value of "rootURL" to the templateUrl of childApp's component so we don't have to hard code the root directory for every module. I think I know how to share variables inside a controller, but don't know how to do that inside the definition of a component.

Here's a Plunker to demo. In app.module.js I defined a constant "config". What can I do so that when I define the component for "child" (components/child.component.js), instead of templateUrl: "components/child.html", I can say something like "config.rootURL + child.html"? We do not have to use constant.

Thank you in advance.

// app.module.js
(function(){
    "use strict";

    var myApp = angular
        .module("myApp", ["child"]);

    myApp.constant("config", {
        rootURL: "components/"
        , version: "myApp1.0.0"
    })
})();

// app.component.js
(function(){

    "use strict";

    // Define controller
    function mainController(){
        this.$onInit = function() {
            var mainVM = this;

            mainVM.parent = {
                "lastName": "Smith"
                , "firstName": "Jordan"
            };
        };

    }

    // Define component
    var mainComponent = {
        controller: mainController
        , controllerAs: "mainVM"
    };

    // Register controller and component
    angular.module("myApp")
        .controller("mainController", mainController)
        .component("mainComponent", mainComponent);

})();


// components/child.module.js
(function(){
    "use strict";

    var child = angular.module("child", []);

})();


// components/child.component.js
(function(){
    "use strict";

    // Define controller
    function childController() {
        this.$onInit = function() {
            var vm = this;
            vm.child = {
              "firstName": "Jack"
            }
        };
        // end of $onInit()
    }

    // Define component
    var child = {
        templateUrl: "components/child.html"
        , controller: childController
        , controllerAs: "vm"
        , bindings: {
            parent: "<"
        }
    };


    // Register controller and component
    angular.module("child")
        .controller("childController", childController)
        .component("child", child);

})();
<!DOCTYPE html>
<html>

  <head>
    <script src="//code.angularjs.org/snapshot/angular.js"></script>
    <link rel="stylesheet" href="style.css">
    <script src="app.module.js"></script>
    <script src="app.component.js"></script>
    <script src="components/child.module.js"></script>
    <script src="components/child.component.js"></script>
  </head>

  <body ng-app="myApp" ng-controller="mainController as mainVM">
    Parent: {{mainVM.parent.firstName}} {{mainVM.parent.lastName}}<br>
    <child parent="mainVM.parent"></child>
  </body>

</html>

<!-- components/child.html -->
Child: {{vm.child.firstName}} {{vm.parent.lastName}}

回答1:


instead of templateUrl: "components/child.html", I can say something like "config.rootURL + child.html"?

Instead templateUrl you can write template with ng-include:

template: '<ng-include src="getTemplateUrl()"/>', 

and:

 scope.getTemplateUrl = function () {
    return config.rootURL + 'child.html';
 };

Demo Plunker


Code example:

function childController(config) {

        this.getTemplateUrl = function(){
          return config.rootURL + 'child.html';
        };

        this.$onInit = function() {
            var vm = this;
            vm.child = {
              "firstName": "Jack"
            }
        };
        // end of $onInit()
    }

    // Define component
    var child = {
        //templateUrl: "components/child.html"
        template: '<ng-include src="vm.getTemplateUrl()"/>'
        , controller: childController
        , controllerAs: "vm"
        , bindings: {
            parent: "<"
        }
    };



回答2:


When you register a constant using myApp.constant() that value becomes inject-able just like any other service. You could inject it into a component's controller and use it, but by then angular has already downloaded (or tried to download) the template. You'd need to modify the URL at component registration time, however, inject-ables are not available yet when you're registering components.

I suggest you instead look into a feature called $http interceptors. You could write an interceptor to look for template requests and modify their url.

https://docs.angularjs.org/api/ng/service/$http

I'd suggest writing template urls with a token, then look for that token in an interceptor. For instance:

templateUrl: '{tplBase}/myTemplate.html'

Then an interceptor that looks for that token and swaps it for the root URL

myApp.config(function($httpProvider) {
    //The interceptor factory is injectable, so inject your config constant here...
    $httpProvider.interceptors.push(function(config) {
        return {
           'request': function(httpConfig) {

                if (httpConfig.url.contains('{tplBase}')) {
                    httpConfig.url = httpConfig.url.replace('{tplBase}', config.rootUrl);
                }
                return httpConfig;
           }
        };
    });
});


来源:https://stackoverflow.com/questions/46304412/angular-1-6-multiple-modules-sharing-global-variable-between-modules-compon

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!