2

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
  • Well, inject the constant in your child controller: function childController(config) { Commented Sep 19, 2017 at 15:41

2 Answers 2

0

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: "<"
        }
    };
Sign up to request clarification or add additional context in comments.

2 Comments

It seems to work. Thank you. I don't understand how the child component can recognize "vm" and interpret template: '<ng-include src="vm.getTemplateUrl()"/>' correctly, even before the controller and "vm" are defined after that? However, when I tried "templateUrl: vm.getTemplateUrl + 'child.html'" it says "vm is not defined" (which makes more sense to me).
I see. Thank you, @Maxim Shoustin
0

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

1 Comment

Thank you. I will try this also.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.