长时间潜伏着第一次海报。我对角度很陌生,但我正在构建一个小应用程序,它根据通过票证系统API检索的JSON模式动态生成表单。我尝试尽可能避免硬编码,因为如果在故障单系统中添加了自定义字段,架构可能会更改。
到目前为止,应用程序加载架构并构建输入字段并使用" @ data-type"确定要应用的模板类型。
问题在于我正在努力获得我想要的最终输出JSON。
所需的JSON输出
{
"Custom_Field": [
{
"@id": "120207",
"#text": "1234569789"
},
{
"@id": "121264",
"Option": {
"@id": "265946",
"@viewOrder": "1",
"Value": "North America"
}
},
{
"@id": "125734",
"#text": "Legacy Account Number"
}
],
"Account_Name": "Example Account",
"Modified_By": "John Doe"
}
具体而言,我对如何最好地处理嵌套在数组中的嵌套对象有点困惑。例如" Custom_Field"中的每个对象。数组将呈现为输入字段,但仍应在该Custom_Field数组中编入索引。
此外,使用我的模板服务加载模板后,parseCustomField()函数似乎无法正常工作。
无论如何,这是我尝试将可重复使用的代码作为一个菜鸟,但绝对愿意接受有关此处所见的任何建议。
JSON Schema(为简洁起见,删除了一些对象)
{
"?xml": {
"@version": "1.0",
"@encoding": "utf-8"
},
"Account": {
"Account_Name": {
"@display-name": "Account Name",
"@required": "true",
"@editable": "true",
"@field-type": "text",
"@data-type": "string",
"@max-length": "256"
},
"Date_Created": {
"@display-name": "Date Created",
"@required": "false",
"@editable": "false",
"@field-type": "usdate",
"@data-type": "date"
},
"Custom_Field": [
{
"@id": "121264",
"@display-name": "Support Region",
"@required": "true",
"@editable": "true",
"@field-type": "dropdown",
"@data-type": "option",
"@multi-value": "false",
"Option": [
{
"@id": "265946",
"@viewOrder": "1",
"Value": "North America"
},
{
"@id": "265949",
"@viewOrder": "3",
"Value": "Europe"
},
{
"@id": "265953",
"@viewOrder": "2",
"Value": "Asia"
}
]
},
{
"@id": "125734",
"@display-name": "Legacy Account Name",
"@required": "false",
"@editable": "true",
"@field-type": "text",
"@data-type": "string",
"@max-length": "1024"
}
]
}
}
App(捣碎但通常分开)
app.controller('FormController', function($scope, pSchema) {
// Initialize User Input Scope
$scope.userinput = {};
$scope.userinput.Custom_Field = [{}];
// Load Schema
$scope.loadschema = function(schematype) {
pSchema.loadSchema(schematype).success(function(data) {
$scope.schema = data[Object.keys(data)[1]];
});
}
});
app.directive('fieldItem', function ($compile, $parse, TemplateService) {
var linker = function(scope, element, attrs, ngModel) {
if (!angular.isArray(scope.field)) {
templater(scope.field['@data-type']);
parseCustomField();
// Quasi Work Around
// Models the data correctly in the userinput.Custom_Field Array, but original bindings aren't really desired for each Custom_Field item on userinput.
/*
if('id' in attrs) {
scope.$watch(attrs.ngModel, function (oldValue, newValue) {
if (newValue != oldValue) {
var parentNode = scope.$parent.key; //Evaluates to "Custom_Field"
var i = scope.$index;
if (angular.isObject(newValue)){
var newObj = {
'@id' : attrs.id,
'Option' : newValue
};
} else {
var newObj = {
'@id' : attrs.id,
'#text' : newValue
};
}
scope.userinput[parentNode][i] = newObj;
}
});
}
*/
} else {
templater('array');
}
//Helper Functions
//Request Template
function templater(field_type) {
TemplateService.getTemplate(field_type).then(function (response) {
element.html(response.data);
$compile(element.contents())(scope);
});
}
//Parse Data
function parseCustomField(){
var toModel = function (val) {
return {
'@id': attrs.id,
'#text':val
}
};
ngModel.$parsers.unshift(toModel);
}
}
//Directive Configuration
return {
restrict: 'E',
require: '?ngModel',
link: linker
};
});
app.factory('TemplateService', function ($http) {
var getTemplate = function (content) {
if (content != null) {
return $http.get('/js/templates/' + content + '.html');
}
};
return {
getTemplate: getTemplate
};
});
app.factory('pSchema', function($http) {
return {
loadSchema: function(type) {
var url = "/js/models/schema/"+type+".json";
return $http.get(url);
}
};
});
String.html
<div class="form-group">
<label>{{field["@display-name"]}}</label>
<input ng-model="userinput[key]" class="form-control" />
</div>
Array.html(也可以在没有模板的情况下接受有关更好方法的建议)
<field-item ng-model="userinput[key]" ng-repeat="(key,field) in field" id="{{field['@id']}}"></field-item>
的index.html
<form ng-controller="FormController" ng-model="userinput">
<field-item ng-repeat="(key,field) in schema"></field-item>
</form>