简体   繁体   English

AngularJS动态表单生成

[英]AngularJS dynamic form generation

Im having some troubles with angular. 我在角度上有些麻烦。

I need to generate a form using a JSON Spec built by a foreign system (the source is trustable). 我需要使用由外部系统构建的JSON Spec生成表单(源是可信任的)。

First I got a problem with FormController because it didn't detect the elements that I was generating through a directive, then I did a workaround by generating the form and fields at the same time into the directive The problem is that its quite messy as you can see in this JSFiddle . 首先,我遇到了FormController的问题,因为它没有检测到我通过指令生成的元素,然后我通过同时在指令中生成表单和字段来解决了该问题,问题在于它与您一样相当混乱可以在此JSFiddle中看到。

var $form = $('<form/>', {
    name: formName,
    id: formName,
    novalidate: true,
    "ng-submit": 'daForm.validate($event, ' + formName + ')'
});

var idx = 1;

for (var fieldName in spec.fieldset) {
    var $wrapper = $('<div/>', {
        id: fieldName + '-col'
    }).addClass('col-xs-12 col-md-6').appendTo($form);

    var $formGroup = $('<div/>', {
        id: fieldName + '-group'
    }).addClass('form-group').appendTo($wrapper)

    $('<label/>', {
        'for': fieldName,
        id: fieldName + '-label'
    }).addClass('control-label').text("{{'" + fieldName + "' }}").appendTo($formGroup);

    var fieldSpec = spec.fieldset[fieldName];
    var control;

    switch (fieldSpec.control) {
        case 'passwordbox':
            control = 'input';
            fieldSpec.attrs.type = "password"
            break;
        case 'number':
            control = 'input';
            fieldSpec.attrs.type = "numberbox"
            break;
        case 'email':
            control = 'input';
            control = 'input';
            fieldSpec.attrs.type = "emailbox"
            break;
        case 'select':
            control = 'select';
            break;
        case 'textarea':
            control = 'multitextbox';
            break;
        case 'textbox':
            $('<da-textbox/>').attr('defined-by', fieldName).appendTo($formGroup)
            continue;
            break;
        default:
            control = 'input';
            fieldSpec.attrs.type = "text"
            break;
    }

    var $control = $('<' + control + '/>', fieldSpec.attrs).attr('ng-model', 'model.' + fieldName).addClass('form-control').appendTo($formGroup);

    for (var rule in fieldSpec.validation) {
        $control.attr(rule, fieldSpec.validation[rule])
    }

    if (control == 'select') {
        for (var val in fieldSpec.options) {
            $('<option/>').val(val).text(fieldSpec.options[val]).appendTo($control);
        }
    }

    if (idx % 2 == 0)
        $wrapper.parent().append($('<div/>').addClass('clearfix'))
    idx++;
}

$form.append($('<div/>').addClass('clearfix'))

var $lastRow = $('<div/>').addClass('col-xs-12 col-md-12').appendTo($form);
var $submit = $('<button/>').attr('type', 'submit').addClass('btn btn-primary').appendTo(
$lastRow).text('Submit')

$form.append($('<div/>').addClass('clearfix'))
console.log(scope)

$compile($form)(scope);

element.append($form);

Notice that the case textbox is where my code fails, for everyother field I generate a plain input/select/textarea field and push it to the container. 请注意,案例文本框是我的代码失败的地方,对于其他每个字段,我都会生成一个普通的input / select / textarea字段并将其推送到容器中。 In textbox case I try to push a new directive in order to tidy up this mess a little bit, but the FormController doesn't recognize it as the other plain items. 文本框的情况下,我尝试推送一个新指令,以使此混乱情况更整齐,但FormController不会将其识别为其他普通项。

Any ideas on how can I make angular recognize the field generated by my new directive? 关于如何使角度识别由新指令生成的场的任何想法?

Addenda 附加物

1.- ngModel works fine, it updates correctly. 1.- ngModel运行正常,可以正确更新。
2.- Updated JSFiddle 2.-更新了JSFiddle

OK, got it. 好的,我知道了。 You are mixing jQuery and AngularJS which often leads to some wonkiness, so it took me a minute to get what was happening. 您正在混合使用jQuery和AngularJS,这通常会带来一些不确定性,因此花了我一分钟时间才能了解正在发生的事情。 So, I was right, the daTextbox element wasn't being bound to the $scope (you can tell by looking at the class list, if it doesn't contain .ng-scope, something is wrong). 所以,我是对的,daTextbox元素没有绑定到$ scope(可以通过查看类列表来判断,如果它不包含.ng-scope,那是错误的)。

Any way, the first think you want to do is make sure the daTextbox will be compiled earlier than ngModel (so any priority greater than 0, I chose 1000). 无论如何,首先要确定的是确保daTextbox的编译时间比ngModel早(因此,任何大于0的优先级,我都选择1000)。 Then, instead of creating the input with jQuery, it is much easier and more efficient to use angular.element . 然后,与其使用jQuery创建输入, 不如使用angular.element更加轻松有效。

What you will want to do is to create the input, compile it, then append it to your directive element. 您将要做的是创建输入,对其进行编译,然后将其附加到指令元素中。 Here's a working example: 这是一个工作示例:

app.directive('daTextbox', ['$compile', function($compile) {
    return {
       restrict: 'E',
       scope: true,
       priority: 1000,
        controller: function($scope, $attrs) {
            this.identifier = $attrs.definedBy
            this.definition = $scope.spec.fieldset[this.identifier]
        },
        link: function(scope, element, attrs, controller) {
            var input = angular.element('<input/>')
                .addClass('form-control')
                .attr('ng-model', 'model.' + attrs.definedBy);

            input = $compile(input)(scope);
            element.append(input);
        }
    };
}]);

Doing it this way, I'm guessing your controller isn't necessary, but it might still be. 这样,我猜您的控制器不是必需的,但可能仍然是。 At any rate, you can see this is working on plnkr . 无论如何,您可以看到它正在plnkr上运行

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM