br1
br1

Reputation: 377

Angular: Change component template using variables

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.

Upvotes: 2

Views: 3116

Answers (2)

Jake Blues
Jake Blues

Reputation: 1051

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.

Upvotes: 1

Aaron Pool
Aaron Pool

Reputation: 489

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..

Upvotes: 3

Related Questions