Una delle soluzioni può essere quella di creare una direttiva che gestisca l'operazione ricorsiva a qualsiasi limite.
Nota: Questa soluzione è una stampante JSON generica + redattore per angolare che ho creato per una delle mie applicazioni
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 #ddd;"><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'
}
}]);
Esempio di configurazione:
{"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}}}}
Nota: Questa configurazione di esempio si prende cura dei campi aggiuntivi che si desidera aggiungere per esistere ing json + se si vogliono nascondere alcuni campi in modo specifico + mantenere alcuni campi disabilitati come campi di input.
Eventuali duplicati di [usando ng-repeat all'interno di un altro ng-repeat] (http://stackoverflow.com/questions/31484686/using-ng-repeat -inside-another-ng-repeat) –