I have a JSON object having nested nodes, which can go on for any number of level. I need to display the content of a node on click of it\'s parent\'s node. It would look so
Try This
var jimApp = angular.module("mainApp", []);
jimApp.controller('mainCtrl', function($scope){
$scope.nodes = [
{
"id": "id of the concept model",
"name": "Curcumin",
"type": "conceptmodel",
"node": [
{
"id": "group1",
"name": "Node 01",
"weight": "70",
"type": "text",
"node": [
{
"id": "group11",
"name": "Node 02",
"weight": "70",
"type": "structure",
"node": []
}
]
}
]
},
{
"id": "id of the concept model",
"name": "Abuse Resistent Technology",
"type": "conceptmodel",
"node": [
{
"id": "group1",
"name": "Category 01",
"weight": "70",
"type": "text",
"node": []
}
]
},
{
"id": "id of the concept model",
"name": "PC in Aviation",
"type": "conceptmodel",
"node": [
{
"id": "group1",
"name": "Industry",
"weight": "70",
"type": "text",
"node": [
{
"id": "group1",
"name": "Node 01",
"weight": "70",
"type": "text",
"node": []
}
]
}
]
}
];
});
li{
list-style: none;
background-color:#334559;
color:#FFF;
padding:2px;
cursor: pointer;
}
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.6.2/css/font-awesome.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="mainApp" ng-controller="mainCtrl">
<script type="text/ng-template" id="treeNodes.html">
<ul>
<li ng-repeat="node in nodes" >
<div ng-click="node.expand = (node.expand?false:true);" ><i class="fa" ng-class="{'fa-caret-right':(node.node.length && !node.expand), 'fa-caret-down':(node.node.length && node.expand)}"></i> {{node.name}}</div>
<div ng-show="node.node.length && node.expand" ng-include=" 'treeNodes.html' " onload="nodes = node.node"></div>
</li>
</ul>
</script>
<div ng-include=" 'treeNodes.html'" style="overflow-y: auto;height: 55%;width: 300px;"></div>
</div>
One of the solution can be to create a directive that takes care of recursive operation to any limit.
Note : This solution is a generic json printer + editor for angular that i created for one of my applications
JsonApp.directive('renderInput',['$compile','NODE_RELATION_CONFIG',function($compile){
var getTemplate = function(inputKey,inputValue,inputParent,inputConfig,inputDisabled,inputHidden){
var template = '';
var disabled = (inputDisabled || (inputConfig && inputConfig["disabled"])) ? true : false;
var hidden = (inputHidden || (inputConfig && inputConfig["hidden"])) ? true : false;
if(typeof(inputConfig)=="undefined")
inputConfig ={}
for(var key in inputParent)
{
if(typeof(inputConfig[key])=="undefined")
inputConfig[key] = {};
}
if(typeof(inputValue)=="object")
{
//template = '<div ng-hide="'+hidden+'" style="padding-left:7%;border:1px solid #ffffd;"><div class="pheading">{[{ inputKey }]}</div><div id="render-123" ng-repeat="(key,value) in inputValue" render-input input-key="{[{ key}]}" input-parent="inputValue" input-value="value" input-config="inputConfig[key]" input-disabled="'+disabled+'" input-hidden="'+hidden+'"></div></div>';
template = '<div ng-hide="'+hidden+'"><div id="render-123" ng-repeat="(key,value) in inputValue" render-input input-key="{[{ key}]}" input-parent="inputValue" input-value="value" input-config="inputConfig[key]" input-disabled="'+disabled+'" input-hidden="'+hidden+'"></div></div>';
}
else
{
var fieldHeading = (inputConfig && inputConfig["mapped_name"]) ? inputConfig["mapped_name"]: inputKey;
if(typeof(inputValue)!="string" || inputValue.length < 200)
{
//small fields use input type text
template = '<div ng-hide="'+hidden+'"><h3 class="gi-orange dy-field-title">'+fieldHeading+'</h3><input class="dy-id-input" type="text" value="{[{ inputValue }]}" ng-disabled="'+disabled+'" /></div>';
}
else
{
template = '<div ng-hide="'+hidden+'"><h3 class="gi-orange dy-field-title">'+fieldHeading+'</h3><textarea class="dy-id-textarea" type="text" ng-disabled="'+disabled+'">{[{ inputValue }]}</textarea></div>';
}
}
return template
}
return{
scope:{
inputKey:"@",
inputValue:"=",
inputParent:"=",
inputConfig:"=",
inputDisabled:"=",
inputHidden: "="
},
link : function(scope, element, attrs) {
element.html(getTemplate(scope.inputKey,scope.inputValue,scope.inputParent,scope.inputConfig,scope.inputDisabled,scope.inputHidden)).show();
$compile(element.contents())(scope);
$(element).on('change','input,textarea',function(e){
if(!scope.$$phase)
scope.inputParent[scope.inputKey]=$(this).val();
if(!scope.$$phase)
scope.$apply();
e.stopImmediatePropagation();
})
},
restrict: 'AE'
}
}]);
Sample Config :
{"flight_sector": {"additional_fields": ["at.scdl_pg.content", "at.scdl_pg.meta.keywords", "at.scdl_pg.meta.title", "at.scdl_pg.meta.desc"], "fields_mapped_names": {"at|scdl_pg|meta|desc": "Flight Sector Page : Meta Description", "at|scdl_pg|meta|keywords": "Flight Sector Page : Meta Keywords", "at|score|flier": "Flight Sector Flier Score", "at|scdl_pg|content": "Flight Sector Page : Content Html", "at|scdl_pg|meta|title": "Flight Sector Page : Meta Title", "at|type": "Flight Sector Type"}, "disabled_fields": ["at.score.flier", "at.type"], "hidden_fields": ["at.airlines", "_id", "s", "e", "sn", "en", "st", "t"], "settings": {"en": {"hidden": 1}, "e": {"hidden": 1}, "st": {"hidden": 1}, "s": {"hidden": 1}, "at": {"scdl_pg": {"content": {"mapped_name": "Flight Sector Page : Content Html"}, "meta": {"keywords": {"mapped_name": "Flight Sector Page : Meta Keywords"}, "title": {"mapped_name": "Flight Sector Page : Meta Title"}, "desc": {"mapped_name": "Flight Sector Page : Meta Description"}}}, "score": {"flier": {"disabled": 1, "mapped_name": "Flight Sector Flier Score"}}, "type": {"disabled": 1, "mapped_name": "Flight Sector Type"}, "airlines": {"hidden": 1}}, "t": {"hidden": 1}, "_id": {"hidden": 1}, "sn": {"hidden": 1}}}, "routes_map": {"additional_fields": ["at.rpr_pg.desc"], "fields_mapped_names": {"at|rpr_pg|desc": "Routeplanner Page Write-Up"}, "hidden_fields": ["routes", "t", "s", "e", "sn", "en", "_id"], "settings": {"en": {"hidden": 1}, "e": {"hidden": 1}, "s": {"hidden": 1}, "t": {"hidden": 1}, "routes": {"hidden": 1}, "_id": {"hidden": 1}, "at": {"rpr_pg": {"desc": {"mapped_name": "Routeplanner Page Write-Up"}}}, "sn": {"hidden": 1}}}}
Note: This sample config takes care of the additional fields you want to add to existing json + if you want to hide few fields specifically + keep some fields disabled as input fields.