Does Angular have syntax for property alias in div?

This is a rather strange question, but here is the idea:

Say I have a complex JSON object coming back from an HTTP call and attached to $scope . Something like that:

 $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 the purchase history in the Angular part, 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 in this format (although not too obvious here with so many details) is that the described purchase is called p alias. I do not need to do obj.purchase_hist[0].item_id , I just can do p.item_id .

But what about when I will show the user's home address? Should I really 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> 

This is really verbosity. I would rather use something similar 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 can’t really use plugins in my environment, so I'm specifically looking for the part of the Angular kernel that will work this way.

Thanks!

+8
javascript angularjs alias
source share
7 answers

I wrote this little directive that allows you to do what you want:

NgAlias ​​directive

 (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 the 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> 
+7
source share

@PaulBoutes provided me with an answer, and he should get a loan; I just wanted to add a version of the directive that I settled on based on his answer.

 app.directive('alias', function() { return { restrict: 'A', link: function(scope, element, attrs) { var splits = attrs['alias'].trim().split(/\s+as\s+/); scope.$watch(splits[0], function(val) { scope.$eval(splits[1]+'=('+splits[0]+')'); }); } }; }); 

The same basic idea as Paul’s just cleaned up a bit and made a little more flexible in terms of spaces, etc.

Usage example:

 <div data-alias="obj.user.contact.home as uhome"> <p>{{uhome.street}}</p> <p>{{uhome.city}}</p> <p>{{uhome.state}}</p> <p>{{uhome.zip}}</p> </div> 
+5
source share

Of course, there is no shortage of workable solutions, but there should be no harm when adding another.

I put it together the other day to save myself typing and make my html more readable. It creates a new child region, so it does not pollute the existing region with these aliases. It just works by associating the property of the parent scope with the new child scope with whatever name you specify.

 app.directive('with', function() { return { restrict: 'A', scope: true, link: function(scope, element, attrs) { if (attrs.as) { scope[attrs.as] = scope.$eval(attrs.with); } else { angular.extend(scope, scope.$eval(attrs.with)); } } }; }); 

So instead:

 <div>{{some.deeply.nested.model.id}} - {{some.deeply.nested.model.name}}</div> 

Do it:

 <div with="some.deeply.nested.model" as="t">{{t.id}} - {{t.name}}</div> 

Or, do this without using as :

 <div with="some.deeply.nested.model">{{id}} - {{name}}</div> 
+4
source share
 <div ng-init="uhome = obj.user.contact.home"> <p>{{uhome.street}}</p> <p>{{uhome.city}}</p> <p>{{uhome.state}}</p> <p>{{uhome.zip}}</p> </div> 

https://code.angularjs.org/1.3.16/docs/api/ng/directive/ngInit

+1
source share

As far as I know, there is nothing very simple. There are some hacks. You can reassign an object to a new area using the new controller

 <div ng-controller="Ctrl as c" ng-init="c.makeAlias(obj.user.contact.home)"> <p>{{c.home}}</p> </div> 

where Ctrl simply saves the makeAlias argument in its scope as home

 this.makeAlias(home) { this.home = home; } 

Another solution is to use $scope.$watch and reassign the object to a more convenient one.

0
source share

I don't think Angular provides out-of-the-box support for such things. But you can definitely create a domain object. Convert your HTTP response to a domain object. Within the domain object, you may have a helper method for obtaining the required information. For example, in your case, you might have a Domain object like this

  factory('User', function () { return function (id,name, contact, purchase_hist) { this.id = id; this.name = name; this.contact = contact; this.purchase_hist = purchase_hist; this.getContact = function(){ return this.contact.home; }; }; }) 

you can use this domain object in your controller

 $scope.user = // domain object return from your service 

in html you can use

 {{user.getContact().street}} 

You can redefine your domain to simplify the task. Perhaps this is an extra job. But when you have to do the same thing over and over again. One can enjoy writing code this way.

0
source share

I came across this just now and tested the ngAlias ​​directive, which may or may not work fine, I don’t know, because I had problems with it, possibly due to some other unrelated error, and I decided about it easier method:

 <div ng-repeat="uhome in [obj.user.contact.home]"> <p>{{uhome.street}}</p> <p>{{uhome.city}}</p> <p>{{uhome.state}}</p> <p>{{uhome.zip}}</p> </div> 

TA-dah! "obj.user.contact.home" is now an alias for "uhome". I believe that this solution is actually exactly what you wanted when you asked this question, because it literally uses ng-repeat and therefore has all the advantages of the built-in ng-repeat alias mechanism.

0
source share

All Articles