使用模板服务在自定义指令中使用Angular解析器时出现问题

时间:2015-05-19 14:34:16

标签: javascript json angularjs nested

长时间潜伏着第一次海报。我对角度很陌生,但我正在构建一个小应用程序,它根据通过票证系统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>

0 个答案:

没有答案