Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I make recursive templates in AngularJS when using nested objects?

I'm trying to build a form dynamically from a JSON object, which contains nested groups of form elements:

  $scope.formData = [   {label:'First Name', type:'text', required:'true'},   {label:'Last Name', type:'text', required:'true'},   {label:'Coffee Preference', type:'dropdown', options: ["HiTest", "Dunkin", "Decaf"]},   {label: 'Address', type:'group', "Fields":[       {label:'Street1', type:'text', required:'true'},       {label:'Street2', type:'text', required:'true'},       {label:'State', type:'dropdown',  options: ["California", "New York", "Florida"]}     ]},   ]; 

I've been using ng-switch blocks, but it becomes untenable with nested items, like in the Address object above.

Here's the fiddle: http://jsfiddle.net/hairgamiMaster/dZ4Rg/

Any ideas on how to best approach this nested problem? Many thanks!

like image 578
Hairgami_Master Avatar asked Mar 27 '13 14:03

Hairgami_Master


2 Answers

I think that this could help you. It is from an answer I found on a Google Group about recursive elements in a tree.

The suggestion is from Brendan Owen: http://jsfiddle.net/brendanowen/uXbn6/8/

<script type="text/ng-template" id="field_renderer.html">     {{data.label}}     <ul>         <li ng-repeat="field in data.fields" ng-include="'field_renderer.html'"></li>     </ul> </script>  <ul ng-controller="NestedFormCtrl">     <li ng-repeat="field in formData" ng-include="'field_renderer.html'"></li> </ul> 

The proposed solution is about using a template that uses the ng-include directive to call itself if the current element has children.

In your case, I would try to create a template with the ng-switch directive (one case per type of label like you did) and add the ng-include at the end if there are any child labels.

like image 155
jpmorin Avatar answered Nov 16 '22 06:11

jpmorin


Combining what @jpmorin and @Ketan suggested (slight change on @jpmorin's answer since it doesn't actually work as is)...there's an ng-if to prevent "leaf children" from generating unnecessary ng-repeat directives:

<script type="text/ng-template" id="field_renderer.html">   {{field.label}}   <ul ng-if="field.Fields">       <li ng-repeat="field in field.Fields"           ng-include="'field_renderer.html'">       </li>   </ul> </script> <ul>   <li ng-repeat="field in formData" ng-include="'field_renderer.html'"></li> </ul> 

here's the working version in Plunker

like image 41
Dexter Legaspi Avatar answered Nov 16 '22 07:11

Dexter Legaspi