2

my question is: Is possible to change the component template when the value of a variable changes in the parent controller? Here there are two ways that I tried to follow:

var topBarTemplateWithButton = [
'<section id="filters">',
'<div class="pull-left">',
'<h1>{{$ctrl.step}}</h1>',
'<div class="pull-left pageActionContainer">',
'<ng-transclude></ng-transclude>',
'</div>',
'</div>',
'</section>'].join(' ')

var topBarTemplateWithoutButton = [
    '<section id="filters">',
    '<div class="pull-left">',
    '<h1>{{$ctrl.step}}</h1>',
    '</div>',
    '</section>'].join(' ')

myApp.component('topBar', {
    bindings: {
        step: '<'
    },
    template: this.templateToUse,
    transclude: true,
    controller: function() {
        var me = this;

        me.$onInit = function() {
            this.templateToUse = topBarTemplateWithButton;
        }

        me.$onChanges = function(changes) {
            if(changes.step.currentValue != "Projects") {
                this.templateToUse = this.topBarTemplateWithoutButton;
            }else {

                this.templateToUse = topBarTemplateWithButton;

            }
        }
    }
});

and

var topBarTemplateWithButton = [
    '<section id="filters">',
    '<div class="pull-left">',
    '<h1>{{$ctrl.step}}</h1>',
    '<div class="pull-left pageActionContainer">',
    '<ng-transclude></ng-transclude>',
    '</div>',
    '</div>',
    '</section>'].join(' ')

var topBarTemplateWithoutButton = [
    '<section id="filters">',
    '<div class="pull-left">',
    '<h1>{{$ctrl.step}}</h1>',
    '</div>',
    '</section>'].join(' ')

myApp.component('topBar', {
    bindings: {
        step: '<'
    },
    template: '<div ng-include="$ctrl.templateToUse"/>,
    transclude: true,
    controller: function() {
        var me = this;

        me.$onInit = function() {
            this.templateToUse = topBarTemplateWithButton;
        }

        me.$onChanges = function(changes) {
            if(changes.step.currentValue != "Projects") {;
                this.templateToUse = this.topBarTemplateWithoutButton;
            }else {
                this.templateToUse = topBarTemplateWithButton;
            }
        }
    }
});

Both these two examples don't work. So it's possible to change the template of this component when the value of step changes? Thank you for your help.

4
  • 1
    You would need to have the parent controller pass the value into the component, and I would just use template directives like ng-if, ng-show, ng-hide, etc. to alter the component Commented Dec 29, 2016 at 21:32
  • 1
    The ng-if directive is the best example on how to do it. To change HTML on the fly, watchers need to be de-registered, scope need to be destroyed, new HTML needs a new scope, and directives need to be compiled and linked. To see how it is done: ng-if source code. Or just use the ng-if directive. Commented Dec 29, 2016 at 23:06
  • @theaccordance thank you for your answer Commented Jan 3, 2017 at 9:06
  • @georgeawg thank you too Commented Jan 3, 2017 at 9:07

2 Answers 2

3

the Template field can be a function that returns a template, and it takes attrs as an injectable. Here's an example that might accomplish what you're looking for.

template: function(attrs) {
    "ngInject";
    // check for custom attribute and return different template if it's there
},

Important point, however, is that these are uncompiled attributes at this point, because the template hasn't been compiled. It can't be compiled, in fact, until the template is determined. So them attribute you inspect can only be a string literal..

Sign up to request clarification or add additional context in comments.

Comments

1

I think this is not the best practice to use two different templates for one component. The main rule is to use one controller with one view. So from this perspective it's better to achieve this behavior is to use ng-switch or ng-if inside component template or even to make two different dumb components - topBarWithButton and topBarWithoutButton. In these both cases you interact with component via bindings. I think this is a bit hacky to use attrs instead of using bindings. Components is not directves so you have to think in terms of components when you build component-based app. I think there are a lot of reasons why you shouldn't use attrs:

  1. You can't change template after it was compiled.
  2. You can't change state of your component.
  3. You keep state in html template.
  4. It's not easy to test this approach.

Comments

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.