0

I am trying to create a grid component in AngularJS that has it's grid items provided at runtime. (think render props pattern in React).

I am trying to build this using the "new" AngularJS components API along with transclusion.

<grid-items>
   <grid-item-type-1></grid-item-type-1>
</grid-items>


<grid-items>
   <grid-item-type-2></grid-item-type-2>
</grid-items>

Any of these should be valid. <grid-items> should take care of the data and the <grod-item-type-x> should take care of how each individual item is going to be dislpayed.

2 Answers2

0

After researching I have found out two ways to do this. One of them is to require the parent controller in the child component and use it's data, or by using the link function along with compile (this doesn't work using the components API), something like this:

link: function(scope, element) {
      scope.items.forEach((item) => {
        const tpl = "<" + item.type + " item=" + item + " ></grid-item>"
        const child = $compile(tpl)(item)
        element.append(child);
      });
    }

The above approach doesn't use transclusion but you can still use whatever child component is provided to the parent at runtime.

0

Well, if I got it correctly there are some ways to do this. When defining your component, like this:

{
  restrict: 'E',
  bindings: {
    myProp: '@',
  },
  transclude: {
    'myTransclude': 'myTransclude',
  },
  template,
  controller,
  controllerAs: 'ctrl',
}

whatever you pass to bindings can be accessed from your component. So in the example above if you did something like this: <my-component my-prop="hey" /> you can as well access ctrl.myProp an get your hey value.

In more complex ways you can use the transclusion item, that insides your myComponent template you'll have something like this:

  <div ng-transclude="myTransclude"></div>

and everytime you'll use it'll be like this:

<my-component>
    <my-transclude>
        <!-- whatever you wan to go inside your component  -->
    </my-transclude>
</my-component>

And, of course, you can have a HTML compile directive (I recommend searching for existing ones) where you could have your template and just use it

    <div html-compile-directive="ctrl.myTemplate"></div>