2013-11-04 63 views
0

我正嘗試在AngularJS中創建表單構建器。整個形態結構在一個JSON對象,定義如下:在AngularJS中動態更改視圖

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 
    }; 
}]); 

我有幾個partials。它們都從一個基本模板繼承,名爲field.jade。這裏是基本模板和另一個從它繼承:

field.jade:(對於其他的partials基本模板):

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 

現在,當用戶點擊按鈕Editfield.type被改變爲template,我想AngularJS到代替加載主視圖(如text_field.jade)的template_field.jade視圖。

有沒有人有任何想法如何告訴AngularJS重新加載templated_field.jade部分呢? P:我想爲此創建一個小提琴,但由於它太複雜了,我不得不導入幾個不同的文件來運行它,所以我放棄了創作小提琴。

+0

認爲您需要在此處添加更多代碼。也許是一個小提琴? –

+0

@Baszz我在這裏增加了更多細節。 –

回答

1

我找到了解決辦法。它工作正常,但我不確定這是否是最好的方式。在我的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 
    }; 
}]); 

請糾正我,如果我在這裏犯錯誤。