angularjsangularjs-ng-transclude

How to avoid `require` and Access the controller of the parent component in transclusion


I'm trying to build a form component that receives an object as input and use the template defined into the object to ng-include the right template to render the form defined in the model.

The problem I have is the object might be defined in the above component. For example this:

   <somecomponent>
     <formx object="$ctrl.settings"></formx>
   </somecomponent>

Unfortunately, it doesn't seem to work. From what I read the transcluded block should be using the scope of the above controller. Is there a way to access the scope of the component somecomponent?

By the way, what I'm looking for is to do the same as:

 <div ng-controller="SomeController as ctrl">
   <formx object="ctrl.settings"></formx>
 </div>

But instead of using a plain controller I'd like to use a component without using an explicit require as the parent component might be different from time to time.


Solution

  • With components the ng-include directive adds a child scope to the isolate scope. Transcluded components need to reference $parent:

    <somecomponent settings="'ss'">
        ̶<̶f̶o̶r̶m̶x̶ ̶o̶b̶j̶e̶c̶t̶=̶"̶$̶c̶t̶r̶l̶.̶s̶e̶t̶t̶i̶n̶g̶s̶"̶>̶<̶/̶f̶o̶r̶m̶x̶>̶
        <formx object="$parent.$ctrl.settings"></formx>
    </somecomponent>
    

    The DEMO

    angular.module("app",[])
    .component("somecomponent",{
      transclude: true,
      bindings: {settings:"<"},
      template: `
        <fieldset>
           somecomponent scope-{{$id}}
         <ng-transclude>
         </ng-transclude>
        </fieldset>
      `
    })
    .component("formx",{
      bindings: {object:"<"},
      template: `
         <fieldset>
           formx scope-{{$id}}<br>
           object={{$ctrl.object}}
         </fieldset>
      `
    })
    <script src="//unpkg.com/angular/angular.js"></script>
      <body ng-app="app">
       <somecomponent settings="'ss'">
         <formx object="$parent.$ctrl.settings"></formx>
       </somecomponent>
      </body>