Rate the string in dotted notation to get the corresponding value from the object in the view

In fact, I hope someone can help me with a problem that I had a couple of times recently.

Let's say I have two objects in AngularJS.

$scope.fields = ['info.name', 'info.category', 'rate.health'] $scope.rows = [{ info: { name: "Apple", category: "Fruit"}, rate: { health: 100, ignored: true} },{ info: { name: "Orange", category: "Fruit"}, rate: { health: 100, ignored: true} },{ info: { name: "Snickers", category: "Sweet"}, rate: { health: 0, ignored: true} }] 

I would like to display a table in a view that only displays fields in $scope.fields . It would be very simple if the table were flat, and I know that I can smooth it out using JavaScript, but there must be a way to do this by converting the dot notation to a path.

I added JSFiddle to demonstrate the problem I am facing:

JSFiddle : http://jsfiddle.net/7dyqw4ve/1/

I also tried to do something as suggested below, but the problem is its terrible practice of using functions in a view: Converting a JavaScript string in dotted notation to an object reference

If anyone has any ideas, I would really appreciate it.

+6
source share
2 answers

In this case, you can use the built-in angular evaluator, opened through the $eval property in the scope ( not vanilla eval ), to evaluate any angular expression (not for evaluating javascript as eval). angular internally uses this to evaluate an expression in scope when resolving bindings.

Example: -

 {{$eval(field, row)}} 

You can do: -

  <th ng-repeat="field in fields">{{$eval(field, row)}}</th> 

or wrap the logic in the controller and expose it using the method in the field.

  <th ng-repeat="field in fields">{{getValue(field, row)}}</th> 

and

 $scope.getValue = function(exp, row){ return $scope.$eval(exp, row); } 

Demo

You can also use the $parse (enter $parse ) service.

 $scope.getValue = function(exp, row){ return $parse(exp)(row); } 

and

 <th ng-repeat="field in fields">{{getValue(field, row)}}</th> 

Demo

+5
source

A slight deviation from the PSL response , which also works:

 <th ng-repeat="field in fields">{{$eval('row.'+field)}}</th> 

First, $eval('row.'+field) leads to row.info.name for fields[0] . And then the binding {{row.info.name}} leads to Apple .

JSFiddle: http://jsfiddle.net/tbmpls/xhon86p7/8/

Nice, simple and straightforward, I think.

It seems that performance should be roughly equivalent to direct binding {{row.info.name}} , because creating a string should be incredibly fast, but is interested in comments on this.

(Btw, this also works inside ng-repeat, where your list is nested in an object, for example:

 <span ng-repeat="val in $eval('myobj.'+myPathInDotNotation) track by $index"> 

but, as with all ng-repeat things, you will definitely want to check the performance on this)

0
source

Source: https://habr.com/ru/post/983620/


All Articles