0

我正在尝试在 AngularJS 中创建一个表单构建器。整个表单结构在 JSON 对象中定义,如下所示:

form = {
  "title": "Some form title",          // Title of the field
  "fieldsets": [                       // Each form is composed of several fieldsets 
    {
      "title": "First fieldset",       // Title of the fieldset
      "fields": [                      // Each fieldset is composed of several fields
        {
          "title": "First field",      // Title of the field, displayed in a label
          "type": "text"               // Type of the field which determines which partial to load
        },
        {
          "title": "Second field",
          "type": "date"
        },
      ]
    },
    {
      "title": "Second fieldset",
      "fields": [
        {
          "title": "First field",
          "type": "text"
        },
        {
          "title": "Second field",
          "type": "date"
        },
      ]
    }     
   ]
}

我得到一个像上面这样的 JSON 对象,然后在这样的页面中呈现它(玉模板):

h5 {{ form.title }}
div(ng-repeat="fs in form.fieldsets")
  fieldset
    legend {{ fs.title }}
    div(ng-repeat="field in fs.fields")
      myfield(field="field")

myfield是一个自定义指令,它解析每个字段并根据类型呈现不同的部分。这是代码:

var appFilters = angular.module('appComponents', []);
appFilters.directive('myfield', ['$compile', '$http', '$templateCache', function($compile, $http, $templateCache){
  var getTemplate = function(contentType) {
    return $http.get('partials/' + contentType + '_field', {cache: $templateCache});
    // I get the partials here, for example for a field of type text, I load text_field.jade
  };

  var linker = function(scope, element, attrs){

    scope.edit_field = function(field) {
      field.type = "template";
    };

    var loader = getTemplate(scope.field.type);

    var promise = loader.success(function(html) {
      element.html(html);
    }).then(function(response) {
      element.replaceWith($compile(element.html())(scope));
    });
  };

  return {
    restrict: 'E',
    scope: {
      field:'='
    },
    link: linker
  };
}]);

我有几个部分。它们都继承自一个名为field.jade. 这是基本模板和另一个继承自它的模板:

field.jade:(其他部分的基本模板):

div
  block _title

div
  div
    block _label
      label {{ field.title }}:
  div
    block _field
  div
    block _controls
      a.control(ng-click="edit_field(field)") Edit

text_field.jade:(部分用于文本类型的字段)

extend field

block _field
  input(type="text")

template_field.jade:(部分字段,当它们处于编辑模式时)

extend field

block _label
  input(type="text", ng-model="field.title")
  // The user can edit the field label here

block _field
  select
  // Here the user can select from several different field types

现在,当用户单击Edit按钮时,field.type更改为template并且我希望 AngularJS 加载template_field.jade视图而不是主视图(如text_field.jade)。

有谁知道如何告诉 AngularJS 重新加载templated_field.jade部分内容?

PS:我想为此创建一个小提琴,但由于它太复杂并且我必须导入几个不同的文件才能运行,所以我放弃了创建小提琴。

4

1 回答 1

1

我找到了解决方法。它工作正常,但我不确定这是否是最好的方法。在我的edit_field函数中,我需要linker手动调用该函数。

scope.edit_field = function(field) {
  field.type = "template";
  linker(scope, element, attrs);
};

而且,我不得不将调用替换为replaceWith()html()因为,我不知道为什么,但replaceWith()仅在第一次调用时才有效。
所以,这一行:

element.replaceWith($compile(element.html())(scope));

应该替换为:

element.html($compile(element.html())(scope));

最后的代码是:

var appFilters = angular.module('appComponents', []);
appFilters.directive('myfield', ['$compile', '$http', '$templateCache', function($compile, $http, $templateCache){
  var getTemplate = function(contentType) {
    return $http.get('partials/' + contentType + '_field', {cache: $templateCache});
    // I get the partials here, for example for a field of type text, I load text_field.jade
  };

  var linker = function(scope, element, attrs){

    scope.edit_field = function(field) {
      field.type = "template";
      linker(scope, element, attrs);
    };

    var loader = getTemplate(scope.field.type);

    var promise = loader.success(function(html) {
      element.html(html);
    }).then(function(response) {
      element.html($compile(element.html())(scope));
    });
  };

  return {
    restrict: 'E',
    scope: {
      field:'='
    },
    link: linker
  };
}]);

如果我在这里犯了任何错误,请纠正我。

于 2013-11-04T23:03:34.760 回答