2014-09-20 47 views
0

我有幾分這裏複雜的需求(一個真正的頭餅刷)...和我不知道的最佳方式進行:AngularJS:如何從任意類型獲取屬性?

要求:

建立管理頁面小部件(CMS內容塊)MVC5使用AngularJS作爲前端(根據管理UI的其餘部分)。問題是每個小部件都有自己特定的一組屬性。他們都有着像TitleIsEnabled等一些特性。但一個HTML控件,例如將有一個的BodyContent場和一個滑塊控件將有圖像等的集合..

我首先想到的是用[UIHint]Html.EditorFor這樣每個控件類型都會有自己的標記。我認爲這很簡單,但是我們怎麼能從任何這樣的任意小部件中獲取屬性到AngularJS模型中?

示例控制器

widgetsApp.controller('widgetController', function ($scope, $http) { 
    $scope.emptyGuid = '00000000-0000-0000-0000-000000000000'; 

    $scope.id = $scope.emptyGuid; 
    $scope.title = ''; 
    $scope.order = 0; 
    $scope.enabled = false; 
    $scope.widgetType = ''; 
    $scope.zoneId = $scope.emptyGuid; 
    // etc 
    // how to get properties of ANY widget type? 

這甚至可能嗎?有更好的解決方案嗎?請注意,如果它可以支持我的要求,我可能會考慮將代碼更改爲使用Knockout或其他此類框架。

編輯

注意的問題是,由於需要對再通過這樣的模式返回到服務器,並與它打交道存在的事實進一步複雜化。在常規的MVC控制器中,我可以使用Request.Form來檢查其他值,但我使用的是Web API,並且不確定這是否可能。

編輯2

好了,所以我覺得我在正確的軌道上,但仍然有問題。首先,這裏是我的進步:

我發現了.factory,並提出了測試頁是這樣的:

<div ng-app="myApp"> 
    <div ng-controller="controller1"> 
     <button class="btn btn-primary" ng-click="showAllInfo()">Show Info</button> 
    </div> 
    <div ng-controller="controller2"> 
    </div> 
</div>  

<script type="text/javascript"> 
     var myApp = angular.module('myApp', []); 

     myApp.factory('widgetModel', function() { 
      return { 
       id: '00000000-0000-0000-0000-000000000000', 
       title: '', 
       order: 0, 
       enabled: false, 
       widgetName: '', 
       widgetType: '', 
       zoneId: '00000000-0000-0000-0000-000000000000', 
       displayCondition: '', 
       widgetValues: '', 
       pageId: null, 
       cultureCode: '', 
       refId: null, 
      }; 
     }); 

     // This is representative of the main controller 
     myApp.controller('controller1', function ($scope, widgetModel) { 
      $scope.emptyGuid = '00000000-0000-0000-0000-000000000000'; 
      $scope.model = widgetModel; 
      $scope.model.id = $scope.emptyGuid; 

      $scope.showAllInfo = function() { 
       alert("id: " + $scope.model.id + ", New Property: " + $scope.model.myNewProperty); 
      }; 
     }); 

     // This is representative of the details controller (to add properties specific to that particular widget type) 
     myApp.controller('controller2', function ($scope, widgetModel) { 
      $scope.model = widgetModel; 
      $scope.model.myNewProperty = "My Awesome Widget"; 
     }); 
    </script> 

上述測試工作很漂亮。但是,當我使用這種代碼在我的實際應用它不能工作,我相信原因是因爲第二控制器注入DOM後來..這裏發生的事情:

我有一個div如下

<div ng-bind-html="widgetDetails"></div>

和加載等細節後,我加載HTML該這樣:

$http.get("/admin/widgets/get-editor-ui/" + $scope.model.id).success(function (json) { 
    $scope.widgetDetails = $sce.trustAsHtml(json.Content); 
}); 

這工作。我可以看到我的HTML控件爲我的新特性有..下面的代碼片段是HTML將其注入到上述div

<div ng-controller="widgetDetailsController"> 
    <div class="col-sm-12 col-md-12"> 
     <div class="form-group"> 
      @Html.Label("BodyContent", "Body Content", new { @class = "control-label" }) 
      @Html.TextArea("BodyContent", null, new { @class = "form-control", ng_model = "model.bodyContent", ui_tinymce = "tinyMCEOptions_BodyContent" }) 
     </div> 
    </div> 
    <button class="btn" ng-click="test()">Test</button> 
</div> 
<script type="text/javascript"> 
    widgetsApp.controller('widgetDetailsController', function ($scope, $http, widgetModel) { 
     $scope.model = widgetModel; 
     $scope.json = angular.fromJson($scope.model.widgetValues); 
     $scope.model.bodyContent = $scope.json.bodyContent || ""; 

     $scope.test = function() { 
      alert($scope.model.bodyContent); 
     }; 
    }); 
</script> 

當我點擊,「測試」按鈕,沒有任何反應...

我試圖通過這個鏈接中列出的方法動態加載控制器:http://www.bennadel.com/blog/2553-loading-angularjs-components-after-your-application-has-been-bootstrapped.htm

它不工作。說實話,我是AngularJS的新手,並沒有真正瞭解所有的缺陷。任何幫助都會很棒。

+0

大量的編輯...你可能會得到更好的答案分裂在兩個問題。 – 2014-09-20 15:57:43

+0

該html仍包含服務器端標記。這是行不通的。 – Chandermani 2014-09-21 03:30:52

回答

0

我最終變成了KnockoutJS,部分原因是AngularJS最終對我的需求有點矯枉過正,但也因爲它不能很好地處理這種情況(或者至少沒有明顯的和乾淨的方式來做到這一點)。我KnockoutJS的解決方案是下面:在我的劇本

<div id="widget-content" class="col-sm-12 col-md-12"> 
    <div class="form-group"> 
     @Html.Label("BodyContent", "Body Content", new { @class = "control-label" }) 
     @Html.TextArea("BodyContent", null, new { @class = "form-control", data_bind = "wysiwyg: bodyContent, wysiwygConfig: tinyMCEConfig" }) 
    </div> 
</div> 

<script type="text/javascript"> 
    function updateModel() { 
     var data = ko.mapping.fromJSON(viewModel.widgetValues()); 

     viewModel.bodyContent = ko.observable(""); 

     if (data && data.BodyContent) { 
      viewModel.bodyContent(data.BodyContent()); 
     } 

     viewModel.tinyMCEConfig = { 
      theme: "modern", 
      plugins: [ 
       "advlist autolink lists link image charmap print preview hr anchor pagebreak", 
       "searchreplace wordcount visualblocks visualchars code fullscreen", 
       "insertdatetime media nonbreaking save table contextmenu directionality", 
       "emoticons template paste textcolor" 
      ], 
      toolbar1: "insertfile undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image", 
      toolbar2: "print preview media | forecolor backcolor emoticons", 
      image_advtab: true, 
      templates: [ 
       { title: 'Test template 1', content: 'Test 1' }, 
       { title: 'Test template 2', content: 'Test 2' } 
      ], 
      content_css: tinyMCEContentCss 
     }; 
    }; 
    function onBeforeSave() { 
     var data = { 
      BodyContent: viewModel.bodyContent() 
     }; 

     viewModel.widgetValues(ko.mapping.toJSON(data)); 
    }; 
</script> 

然後:

在主網頁,我想補充一個HTML元素:

<fieldset id="widget-details"></fieldset>

被注入任意HTML的例子對於主頁,我使用以下內容:

$.ajax({ 
    url: "/admin/widgets/get-editor-ui/" + self.id(), 
    type: "GET", 
    dataType: "json", 
    async: false 
}) 
.done(function (json) { 
    var result = $(json.Content); 

    var content = $(result.filter('#widget-content')[0]); 
    var details = $('<div>').append(content.clone()).html(); 
    $("#widget-details").html(details); 

    var scripts = result.filter('script'); 
    scripts.appendTo('body'); 

    // ensure the function exists before calling it... 
    if (typeof updateModel == 'function') { 
     updateModel(); 
     var elementToBind = $("#widget-details")[0]; 
     ko.cleanNode(elementToBind); 
     ko.applyBindings(viewModel, elementToBind); 
    } 
}) 
.fail(function() { 
    $.notify("There was an error when retrieving the record.", "error"); 
}); 

a第二,當我保存,我把這個代碼:

// ensure the function exists before calling it... 
if (typeof onBeforeSave == 'function') { 
    onBeforeSave(); 
} 

的作品真的很好。

0

如果您只是想獲取屬性及其值,那麼在AngularJS或Javascript端,您可以遍歷對象屬性以獲取定義在該對象上的所有屬性。

for(var key in obj){ 
     $scope[key]=obj[key]; 
} 

一旦在範圍內,您可以使用ng-model將其綁定到視圖。 這種方法會爲你提供數據,但是有關數據的元數據(如控制渲染用於屬性需求)將無法工作。

對於高級場景,您應該嘗試發送有助於在視圖上呈現它的每個屬性的元數據。

如果ng-model設置正確,所有數據都會發送到服務器。

在服務器上,您可以使用動態關鍵字作爲webapi方法的輸入參數,並且應該有類似的方法來使用鍵值對遍歷有效負載。

+0

感謝您的回覆,但我發現我認爲這是一個更乾淨的方式來做到這一點。但是,我仍然有問題。請參閱我上面的編輯。 – Matt 2014-09-20 06:08:25

相關問題