kenbellows kenbellows - 2 months ago 18
AngularJS Question

Does Angular have a syntax to alias a property within a div?

This is kind of a weird question, but here's the idea:

Let's say I have a complex JSON object coming back from an HTTP call and attaching to the

$scope
. Something like this:

$scope.obj = {
user: {
id: 10,
name: { first: 'Joe', last: 'Smith' },
contact: {
home: {
street: '101 First St.',
city: 'Myville',
state: 'Jokelahoma',
zip: '98765'
},
email: 'joeshmoe@gmail.com',
phone: '+12345678901'
}
},
purchase_hist: [
{ item_id: 11004, date: 'Thu, 06 Aug 2015 13:51:17 GMT' },
{ item_id: 97020, date: 'Fri, 31 Jul 2015 18:57:57 GMT' }
]
}


Now, if I wanted to display an overview of purchase history in an Angular partial, I could do something like this:

<table>
<tr ng-repeat="p in obj.purchase_hist">
<td>{{p.item_id}}</td>
<td>{{p.date}}</td>
</tr>
</table>


The really convenient thing about this format (though it's not super evident here with so few props) is that the purchase being described is aliased as
p
. I don't have to do
obj.purchase_hist[0].item_id
, I can just do
p.item_id
.

But what about when I go to show the user's home address? Do I really have to do this?:

<div>
<p>{{obj.user.contact.home.street}}</p>
<p>{{obj.user.contact.home.city}}</p>
<p>{{obj.user.contact.home.state}}</p>
<p>{{obj.user.contact.home.zip}}</p>
</div>


That's really verbose. I would much rather use something akin to the
controller as ...
syntax, something like this:

<div ng-alias="obj.user.contact.home as uhome">
<p>{{uhome.street}}</p>
<p>{{uhome.city}}</p>
<p>{{uhome.state}}</p>
<p>{{uhome.zip}}</p>
</div>


Is there such a thing that exists in angular? Unfortunately I'm not very able to use plugins in my environment, so I'm specifically looking for a part of angular core that will work this way.

Thanks!

Answer

I've written this little directive, which allow you to perform what you want :

Directive ngAlias

(function(){

  function ngAlias($compile) {
    return {
        restrict: "A",
        link: function(scope, element, attrs) {
          var args = attrs.ngAlias.split('as').map(function(elm){return elm.replace(/ /g,'')});

          scope[args[0]] = '';

          var dot = args[1].split('.');

          var object = {};

          dot.forEach(function(value, index){
            index === 0
            ? object = scope[value]
            : object = object[value] === null ? object[value] = {} : object[value];
          });

          console.log(object)

          scope[args[0]] = object;
        }
    };
  }

angular
  .module('app')
  .directive('ngAlias', ngAlias);


})();

For example, set your object in your controller

Controller

(function(){

function Controller($scope) {


  $scope.obj = {
    toto: {
      nom: 'toto',
      prenom: 'tata'
    }
  };

}

angular
.module('app', [])
.controller('ctrl', Controller);

})();

And you can use it :

HTML

  <body ng-app="app" ng-controller="ctrl">

    <div ng-alias="toto as obj.toto">
      {{toto.nom}}
    </div>

  </body>