在AngularJS中动态更改视图

Change view dynamically in AngularJS

本文关键字:视图 动态 AngularJS      更新时间:2023-09-26

我正在尝试用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对象,然后在一个像这样的页面中呈现它(jade模板(:

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的基本模板。这是基础模板和另一个从中继承的模板:

字段。翡翠:(其他部分的基础模板(:

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:(部分用于text类型的字段(

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部分吗?

p.S:我想为此创建一个fiddle,但由于它太复杂了,而且我必须导入几个不同的文件才能运行,所以我放弃了创建fiddle。

我找到了一种方法。它运行良好,但我不确定这是否是最好的方法。在我的edit_field函数中,我需要手动调用linker函数。

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

而且,我不得不用html()替换对replaceWith()的调用,因为,我不知道为什么,但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
  };
}]);

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