Ben Taliadoros
Ben Taliadoros

Reputation: 9331

Angular component won't display

I have piece of html I want to show as a component, as I'm not manipulating the DOM.

As a directive it works fine, but as a component it doesn't. I have made components before with no problem, just can't see what the issue is here. If I comment in the component code, and the directive out, it doesn't work.

Any idea what I've done wrong?

(function() {
"use strict";

angular
    .module('x.y.z')


    // .component('triangularStatus', {
    //     bindings: {
    //         value: '=',
    //         dimension: '=?'
    //     },
    //     templateUrl: '/path/to/triangular-status.html',
    //     controller: TriangularStatusController,
    //     controllerAs: 'vm'
    // });


    .directive('triangularStatus', triangularStatus);

    function triangularStatus() {
        var directive = {
            scope: {
                value: '=',
                dimension: '=?'
            },
            replace: true,
            templateUrl: '/path/to/triangular-status.html',
            controller: TriangularStatusController,
            controllerAs: 'vm',
        };
        return directive;
    }



    TriangularStatusController.$inject = [];
    function TriangularStatusController() {
        var vm = this;
    }
})();

Upvotes: 6

Views: 9543

Answers (3)

JcT
JcT

Reputation: 3569

The definition of your component, using bindings, is not directly equivalent to the definition of your directive, using scope, even though both are defined to use controllerAs. This is because your component will be binding directly to the controller, and your directive will be binding to $scope (by default).

I've used your code in the snippet below, slightly modified to allow the component and directive(s) to be used together. I've also added an additional directive that makes use of bindToController:true to demonstrate a directive that behaves a little more like a component in binding its attribute values directly to the controller, rather than to $scope.

I've also used a very basic shared template that attempts to show the bound attribute values by looking for them on $scope, followed by looking for them on vm (the ControllerAs).

(function() {
  "use strict";

  var templateBody = '<h2>$scope</h2>' +
    '<p>value: {{value}}</p><p>dimension: {{dimension}}</p>' +
    '<h2>vm</h2>' +
    '<p>vm.value: {{vm.value}}</p><p>vm.dimension: {{vm.dimension}}</p>';

  angular
    .module('x.y.z', [])


  .component('triangularStatusComponent', {
    bindings: {
      value: '=',
      dimension: '=?'
    },
    template: '<div><h1>Triangular Status Component</h1>' + templateBody + '</div>',
    controller: TriangularStatusController,
    controllerAs: 'vm'
  })


  .directive('triangularStatusDirective', triangularStatusDirective)
  .directive('triangularStatusDirectiveBound', triangularStatusDirectiveBound);

  function triangularStatusDirective() {
    var directive = {
      scope: {
        value: '=',
        dimension: '=?'
      },
      replace: true,
      template: '<div><h1>Triangular Status Directive</h1>' + templateBody + '</div>',
      controller: TriangularStatusController,
      controllerAs: 'vm',
    };
    return directive;
  }

  function triangularStatusDirectiveBound() {
    //https://docs.angularjs.org/api/ng/service/$compile#-bindtocontroller-
    var directive = {
      scope: {
        value: '=',
        dimension: '=?'
      },
      bindToController: true,
      replace: true,
      template: '<div><h1>Triangular Status Directive Bound</h1>' + templateBody + '</div>',
      controller: TriangularStatusController,
      controllerAs: 'vm',
    };
    return directive;
  }

  TriangularStatusController.$inject = [];

  function TriangularStatusController() {
    var vm = this;
  }
})();
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
<div ng-app="x.y.z">
  <triangular-status-component value="'componentValue'" dimension="'componentDimension'">
  </triangular-status-component>
  <hr>
  <triangular-status-directive value="'directiveValue'" dimension="'directiveDimension'">
  </triangular-status-directive>
  <hr>
  <triangular-status-directive-bound value="'directiveValueBound'" dimension="'directiveDimensionBound'">
  </triangular-status-directive-bound>
</div>

If you're finding that your code works as a directive, where your values are bound to $scope, but not as a component, where your values are bound to the controller, I would assume either your template html (most likely?) or your controller function are relying on trying to access your values as though they were on $scope. To confirm this, you may notice there are errors being logged to your javascript console that will help you zero in.

Upvotes: 1

Martin Kukan
Martin Kukan

Reputation: 161

I think the only problem is, that your missing the brackets: angular.module('x.y.z') change to angular.module('x.y.z', [])

https://docs.angularjs.org/api/ng/function/angular.module

As was mentioned in the comment, I need to clarify, the problem can be how are your JS files ordered or bundled, some other JS file executed later can overwrite this module and therefor you will not see any tag rendered.

Upvotes: 0

Kumar Nitesh
Kumar Nitesh

Reputation: 1652

Here is the working code, most probably you are not using vm.values to access data.

Just be sure you are using right version of angular js ~1.5

(function(angular) {
angular.module('x.y.z', [])
    .component('triangularStatus', {
        bindings: {
            value: '=',
            dimensions:'=?'
        },
         template: '{{vm.value}} <br/> {{vm.dimensions}}' ,
        controller: TriangularStatusController,
        controllerAs: 'vm'
     });
   TriangularStatusController.$inject = [];
    function TriangularStatusController() {
       
    }
})(window.angular);
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.js"></script>
<div ng-app = "x.y.z"> 
<triangular-status  value="24" dimensions="348"></triangular-status>
</div>

Upvotes: 3

Related Questions