Passing a binding to transcluded scope in component Passing a binding to transcluded scope in component angularjs angularjs

Passing a binding to transcluded scope in component


In your parent component my-select keep a variable like "selectedItem"

In your child component my-select-item, require your parent component like below

require: {  mySelect: '^mySelect'}

And in your my-select-item component's controller, to access your parent component

 $onInit = () => {  this.mySelectedItem= this.mySelect.selectedItem; // to use it inside my-select-item component. }; select($item) {   this.mySelect.selectedItem = $item; // to change the selectedItem value stored in parent component }

So that the selected item is now accessible from

<my-select-item>{{selectedItem.id}}: {{selectedItem.name}}</my-select-item>


I ran into this problem as well, and building upon salih's answer, I came up with a solution (disclaimer--see bottom: I don't think this is necessarily the best approach to your problem). it involves creating a stubbed out component for use in the mySelect component, as follows:

.component('item', {    require: { mySelect: '^mySelect' },    bind: { item: '<' }})

then, tweaking your template:

<script id="my-select-template" type="text/ng-template"><ol>  <li ng-transclude="header"> </li>  <li ng-click="$ctrl.select($item)"      ng-repeat"$item in $ctrl.collection">      <item item="$item" ng-transclude="item"></item>  </li></ol></script>

this will mean there's always an item component with the value bound to it. now, you can use it as a require in a custom component:

.component('myItemComponent', {    require: {        itemCtrl: '^item',    }    template: '<span>{{$ctrl.item.id}}: {{$ctrl.item.name}}</span>',    controller: function() {        var ctrl = this;        ctrl.$onInit = function() {            ctrl.item = ctrl.itemCtrl.item;        }    }});

and to use it:

<my-select collection="[{id: 1, name: "John"}, {id: 2, name: "Erik"}, ... ]>   <my-select-head></my-select-head>   <my-select-item>       <my-item-component></my-item-component>   </my-select-item></my-select>

after I implemented this, I actually decided to change my strategy; this might work for you as well. instead of using a transclude, I passed in a formatting function, i.e.:

.component('mySelect', {     bind: {         collection: '<',        customFormat: '&?'    },    transclude:{        header: 'mySelectHeader'    },    templateUrl: 'my-select-template',    controller: function(){        var ctrl = this;        ctrl.format = function(item) {            if(ctrl.customFormat) {                return customFormat({item: item});            } else {                //default                return item;            }        }        .....     }});

then in the template, just use:

<script id="my-select-template" type="text/ng-template"><ol>  <li ng-transclude="header"> </li>  <li ng-click="$ctrl.select($item)"      ng-repeat"$item in $ctrl.collection"      ng-bind="::$ctrl.format($item)">  </li></ol></script>

let me know if you have any feedback or questions!