在AngularJS中动态更改视图

时间:2013-11-04 15:40:29

标签: javascript forms angularjs

我正在尝试在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视图而不是主视图(例如{ {1}})。

有没有人知道如何告诉AngularJS重新加载text_field.jade部分?

P.S:我想为此创造一个小提琴,但由于它太复杂而我必须导入几个不同的文件才能运行,我放弃了创造小提琴。

1 个答案:

答案 0 :(得分: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
  };
}]);

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