0

I would like to use a custom directive that binds to an object, but I would like to specify the field used in the template. Previously, I was using {{item.Name}} but I would like to bind to any object, specifying the display field.

This is what I have

var foo = function () {
    return {
        restrict: 'E',
        scope: {
            items: '='
        },
        template:
        "<div class='holder'>"
          + "<a data-ng-repeat='item in items' data-ng-click='myClick(item)'><i class='fa fa-times'/>{{item.Name}}</a>"
          + "</div>",


        controller: function ($scope) {......}
      }
}

I'd like to do this:

var foo = function () {
    return {
        restrict: 'E',
        scope: {
            items: '=',
            display_field: 'Name',
            icon_field: 'fa fa-times',
        },
        template:
        "<div class='holder'>"
          + "<a data-ng-repeat='item in items' data-ng-click='myClick(item)'><i data-ng-class='{{item.icon_field}}'/>{{item.display_field}}</a>"
          + "</div>",


        controller: function ($scope) {......}
      }
}

Where the display_field and icon can be specified like this:

<foo items="myItems" display_field="OtherProperty" icon-field="iconProperty" />

fiddle: http://jsfiddle.net/1L7tdd1p/

NetHawk
  • 1,392
  • 1
  • 15
  • 33

1 Answers1

1

You are close. Remember angular expressions are subsets of Javascript expressions. To access a property using a dynamic property name use bracket notation:

{{ item[display_field] }}

Any value can be a key for an object, not just strings. Bracket notation allows you to access a property of an object by using any expression as a key:

var obj = {};
obj[1] = 'a';
obj.asdf = 'b';
obj[{}] = 'c';
console.log(obj[1], obj['asdf'], obj[{}]);

Additionally, I think you misunderstood the purpose of the scope option. The scope option let's you specify a set of bindings your directive will pick up from the element you use it on, and the type of this bindings. You can't set default values with it. Have a look at Use of symbols '@', '&', '=' and '>' in custom directive's scope binding: AngularJS.

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

//myApp.directive('myDirective', function() {});
//myApp.factory('myService', function() {});

function MyCtrl($scope) {
  $scope.name = 'Superhero';
}

myApp.directive('foo', function() {
  return {
    restrict: 'E',
    scope: {
      items: '=',
      prop: '@' // this declared a
    },
    template: " <a data-ng-repeat='item in items'><br/>{{item[prop]}}</a>",

    controller: function($scope) {}
  }

});

myApp.controller("appController", function($scope) {
  $scope.Items = [{
    "id": 1,
    "name": "aaaa"
  }, {
    "id": 2,
    "name": "bbbb"
  }]
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.5/angular.min.js"></script>
<div ng-app='myApp' ng-controller="appController">
  <foo items="Items" prop='name'></foo>
</div>
ichigolas
  • 7,595
  • 27
  • 50
  • Thanks for your quick help. For some reason that just doesn't work. It just shows blank. Even if I have a literal field called display_field. I tried to get it working in a fiddle http://jsfiddle.net/1L7tdd1p/ – NetHawk Oct 18 '17 at 01:49
  • Thanks! I guess I was close. My problem in the last bit was that I needed to use an @ instead of an =. – NetHawk Oct 18 '17 at 23:59