0

I am trying to make a generic component to display variables and maybe call methods from its scope.

It felt quite natural to write <component config-name></component>, so I got stuck with the idea of filling the generic component's scope with variables from an attribute directive.

This directive would provide variables to display, methods to call, etc.

I ended up with something like this:

var app = angular.module('app', []);

app.component('component', {
  template: '<li>{{data}}</li>'
});

app.directive('dirA', function() {
  return {
    restrict: 'A',
    controller: function($scope) {
      $scope.data = 'First directive!';
    }
  };
});

app.directive('dirB', function() {
  return {
    restrict: 'A',
    controller: function($scope) {
      $scope.data = 'Second directive!';
    }
  };
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.5/angular.min.js"></script>

<h2>Expectations</h2>
<ul>
  <li>First directive!</li>
  <li>Second directive!</li>
</ul>

<h2>Reality</h2>
<ul ng-app="app">
  <component dir-a></component>
  <component dir-b></component>
</ul>

However, the component's scope stays empty. How could I make the directives fill the scope of their component element?

Is this even the AngularJS way of doing things? If not, what would be the best way of doing something similar?

5
  • 1
    Why not drop the component directive and just use dirA and dirB as element directives? Commented Aug 30, 2017 at 12:33
  • It would work if they share the same template, but what if I want to use another template ? E.g. <comp-a dir-a></comp-a> <comp-a dir-b></comp-a> <comp-b dir-a></comp-b> Commented Aug 30, 2017 at 12:34
  • 1
    Do you really want a different template with the same controller? Why not just swap out the ng-controller? Commented Aug 30, 2017 at 12:46
  • I don't know if I really want the same controller, I just want the same scope (I'm a complete beginner so I guess I may be misunderstanding a lot of things). Say I have a list of buttons, each one has data (icon, label) and a method for handling clicks. Reusing the same template is good. Then in some other part of the app I have a menu with some of these same actions but for some reason I need tweaks, like a <li> instead of a <button> and a popup before calling the method. Then I would have to duplicate all of the directives just to change their templateUrl, no? Commented Aug 30, 2017 at 13:08
  • (I didn't understand what you meant by "swap out <stuff>", now I've learned a new word, thank you :) Yeah I guess doing this would work) Commented Aug 30, 2017 at 13:20

1 Answer 1

2

You are doing it wrong, a component is more like a directive but also like a replacement for the directive beginning with angular 1.5.

Note: A component is just an improved version of directive so you don't pass directives into components as attributes. To pass values to a component, use bindings:

angular.module('myApp')
    .component('component', {
        templateUrl: 'component.html',
        controller: function ComponentCtrl(){
            this.innerProp = "inner";  //Tied to controller scope
        },
        controllerAs: 'vm',   // Replaces scope, by default components use `$ctrl`
        bindings: {
           input: '=?'
        }
});

In component.html you can do:

<div>
    {{vm.innerProp}} /*Scope variable from controller*/
    {{vm.input}} /*Attribute from bindings*/
</div>

And in a parent component/template you can do:

<component input="someModel"></component>

The value passed to input in the parent template will be passed to component.html and replace vm.input

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

2 Comments

Then if I want to pass arbitrary objects to a component, the only way is to have them all in the scope of some parent controller before passing them as arguments?
You can have them within the component's controller or within the parent's.

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.