Lekhnath
Lekhnath

Reputation: 4625

How to get data attributes value from child elements in angular controllers

Yesterday I start learning AngularJs online. I decided to create some useful stuffs for my new project using Angular. Below is some portion of my hard work :

The HTML Part

<div data-ng-controller="DataGrid_Controller">
    <table class="table table-stripped">
        <thead>
            <tr>
                <th data-field="fname"> First Name </th>
                <th data-field="lname"> Last Name </th>
                <th data-field="email"> Email </th>
            </tr>
        </thead>
        <tbody>

        </tbody>
    </table>
</div>

The Angular Part

<script type="text/javascript">
var app = angular.module('TestApp',[]);

app.controller('DataGrid_Controller', function($scope){
    //var fields = ['fname', 'lname', 'email']; 
    //How can I get the value of data-field attributes in my 'Controller' so that I could use them 
})
</script>

How can I get the value of data-attributes from child elements (I don't know either the term element exists or not in angular?) in my controller.

I am 1 day old baby for AngularJs so please show me the right way if you think I am catching the wrong way of doing it. I have used jQuery for years so I am thinking a controller as plugin. Please help me solving the problem.

Upvotes: 3

Views: 4749

Answers (1)

madhead
madhead

Reputation: 33442

In Angular, you need to think in terms of model, not the resulted DOM. The model is the only source of truth. So, you need to put your headers somewhere in your model. Then you make a loop through you data, and for each item you iterate over headers and create a table. You'll need a directive to work woth DOM, a controller to contain the data and a simple template:

The DOM:

<div data-ng-controller="DataGrid">
  <table class="table table-striped">
    <thead>
      <tr>
        <th data-header="firstName" data-headers="headers">
          First name
        </th>
        <th data-header="lastName" data-headers="headers">
          Last name
        </th>
      </tr>
    </thead>
    <tbody>
      <tr data-ng-repeat="character in characters">
        <td data-ng-repeat="header in headers">
          {{character[header]}}
        </td>
      </tr>
    </tbody>
  </table>
</div>

Angular application:

'use strict';

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

Datagrid controller:

'use strict';

DataAttributes.controller('DataGrid', ['$scope', function($scope){
    // let this data came from server
    $scope.characters = [
        {
            'firstName' : 'Anakin',
            'lastName' : 'Skywalker',
            'email' : '[email protected]',
            'age' : 9
        },
        {
            'firstName' : 'Kos',
            'lastName' : 'Palpatine',
            'email' : '[email protected]',
            'age' : 60
        },
        {
            'firstName' : 'Jar',
            'lastName' : 'Jar',
            'email' : '[email protected]',
            'age' : 23
        }
    ];

    $scope.headers = [];
}]);

And a directive:

'use strict';

DataAttributes.directive('header', [function(){
    return {
        'restrict' : 'A',
        'scope' : {
            'headers' : '='
        },
        'link' : function(scope, iElement, iAttrs){
            scope.headers.push(iAttrs['header']);
        }
    };
}]);

I've created a plunkr, so you can play with it.

Let's see what is under the hood. Suppose you've already got your data (characters) somewhere else. Now you want to dynamically build a table with some fields from it. You create a directive to capture field name (header). It need to put header names in the controllers's scope. So, you need to bind a model from parent scope, to directive's. This is achieved with 'headers' : '=' line, which tells Angular to

set up bi-directional binding between a local scope property and the parent scope property of name defined via the value of the attr attribute. If no attr name is specified then the attribute name is assumed to be the same as the local name.

The directive simply pushes field names to parent scope. Now, ngRepeat can be used to iterate through them and render a row for each element from characters. That's it!

Upvotes: 4

Related Questions