Search code examples
javascriptangularjsangular-directive

AngularJS Use child directives as directive data


To make it short...i need to read child directive as data in the parent directive i got something like:

<ng-table url="http://api.com/getArchive1" editUrl="http://api.com/editArchive1" etc>
 <header name="id" paramName="user_id"><header/>
 <header name="name" etc></header>
 <header name="age" etc></header>
</ng-table>

So i got something like (WARNING, COFFEESCRIPT :P):

table.directive 'ngTable', (Table) ->
  restrict    : "E"
  templateUrl : "table.html"
  link : (scope, element, attrs) ->
    scope.grid = new Table(attrs) //this is a class
    //other stuff

So how do i create the other directive and get in this link function something like a array of headers??


Solution

  • You can actually deep dive into directive controllers and "transclusions".

    To access parent controller you can use require option.

    .directive 'parent', ->
      controller: ->
        @addHeader = (header) => #do add header
    
    .directive 'child', ->
      require: '^parent'
      link: (scope, el, attr, parent) ->
        parent.addHeader 'from child'
    

    But you need to make sure your child link function actually ran.

    For example (WARNING JAVASCRIPT!!! :) you can use transclude option. Sophisticated Example.

      .directive('myTable', function() {
        return {
          restrict: 'E',
          controller: function() {
            var headers = []
            this.headers = headers
            this.addHeader = headers.push.bind(headers)
          },
          template: `
            <table>
              <thead>
                <tr>
                </tr>
              </thead>
            </table>
          `,
          transclude: {
            // transclude all myHeaders into headers slot
            headers: 'myHeader' // transclude (how this is a real word at all?)
          },
          link: function(scope, el, attrs, ctrl, transclude) {
            var headerRow = el.find('thead').children('tr')
    
            // append all headers into thead wrapping with th
            transclude(function(headers) {
              [].forEach.call(headers, header => {
                var cell = angular.element('<th></th>')
                cell.append(header)
                headerRow.append(cell)
              })
            }, headerRow, 'headers')
    
            console.log(ctrl.headers) // headers were populated here
          }
        }
      })
      .directive('myHeader', function() {
        return {
          restrict: 'E',
          require: '^myTable',
          transclude: true, // ohh more transclusions
          template: '<span ng-transclude></span>', 
          link: function(scope, el, attrs, myTable) {
            myTable.addHeader(attrs.name) // report to myTable
          }
        }
      })
    
    <my-table>
      <my-header name="First"> First Header </my-header>
      <my-header name="Second"> Second <span style="color:red;">Header</span> </my-header>
    </my-table>