2013-08-28 38 views
0

我對AngularJS非常陌生,在觀看一些複合視頻後,我決定使用它創建一個簡單的網頁。與父親兒童組合的動態表單

頁面最初應該加載一個由ajax請求(包含所有數據)填充的選擇框。然後,根據所選的值,可能需要創建一個包含子數據的新選擇元素。這將繼續發生,直到選擇沒有孩子ID的選項。我從api獲取的數據格式如下。

[ { "ChildIds" : [ ], 
    "Id" : "1", 
    "Name" : "Top Level", 
    "ParentId" : null 
    }, 
    { "ChildIds" : [ "51" ], 
    "Id" : "22", 
    "Name" : "LevelA - 1", 
    "ParentId" : "1" 
    }, 
    { "ChildIds" : [ "38", 
     "26" 
     ], 
    "Id" : "24", 
    "Name" : "LevelA - 2", 
    "ParentId" : "1" 
    }, 
    { "ChildIds" : [ ], 
    "Id" : "38", 
    "Name" : "LevelB - 1", 
    "ParentId" : "24" 
    }, 
    { "ChildIds" : [ ], 
    "Id" : "26", 
    "Name" : "LevelB - 2", 
    "ParentId" : "24" 
    }, 
    { "ChildIds" : [ ], 
    "Id" : "51", 
    "Name" : "LevelB - 3", 
    "ParentId" : "22" 
    }, 
    { "ChildIds" : [ "43", 
     "21" 
     ], 
    "Id" : "36", 
    "Name" : "LevelC - 1", 
    "ParentId" : "26" 
    }, 
    { "ChildIds" : [ ], 
    "Id" : "43", 
    "Name" : "LevelD - 1", 
    "ParentId" : "36" 
    }, 
    { "ChildIds" : [ ], 
    "Id" : "21", 
    "Name" : "LevelD -2", 
    "ParentId" : "36" 
    } 
] 

我設法用硬編碼選擇元素得到這個工作,但要使這個充滿活力。

的Html

<div class="container"> 
     <div ng-controller="organisationalUnitCtrl"> 
      <select class="form-control" ng-model="root" ng-options="ou.Name for ou in ous | filter:{ParentId:'!'}"> 
       <option value="">-- choose organisation unit --</option> 
      </select> 
      <select class="form-control" ng-model="child" ng-options="ou.Name for ou in ous | filter:{ParentId:root.Id}"> 
       <option value="">-- choose organisation unit --</option> 
      </select> 
      <select class="form-control" ng-model="child2" ng-options="ou.Name for ou in ous | filter:{ParentId:child.Id}"> 
       <option value="">-- choose organisation unit --</option> 
      </select> 
      <select class="form-control" ng-model="child3" ng-options="ou.Name for ou in ous | filter:{ParentId:child2.Id}"> 
       <option value="">-- choose organisation unit --</option> 
      </select> 
     </div> 
    </div> 

控制器

bristowRiskApp.controller('organisationalUnitCtrl', 
    function organisationalUnitCtrl($scope, organisationalUnitData) { 
     $scope.ous = organisationalUnitData.getOrganisationalUnit(); 
    } 
); 

服務

bristowRiskApp.factory('organisationalUnitData', function ($http, $q) { 
    return { 
     getOrganisationalUnit: function() { 
      var deferred = $q.defer(); 

      $http({ method: 'GET', url: 'http://localhost:53995/api/organisationalunit' }). 
       success(function (data, status, headers, config) { 
        deferred.resolve(data); 
       }). 
       error(function (data, status, headers, config) { 
        deferred.reject(status); 
       }); 

      return deferred.promise; 
     } 
    } 
}); 

我已閱讀,你應該不是人在控制器中使用DOM。所以,我猜測我應該爲我的select元素創建一個指令來監聽onChange事件並創建新的select元素?我該怎麼做呢?我能從中學到什麼樣的例子嗎?

我在硬編碼示例中遇到的另一個問題是,更改select中的值只會漣漪到下一個組合。例如,如果在所有四個選擇框中選擇了值,則更改第二個框中的值將正確地重置第三個框,但第四個框仍將包含所選的選項。我認爲這種變化會一路波瀾起伏。

感謝

史蒂芬

+0

是的,你需要一個指令。實際上,我之前寫過一個懶惰裝載的樹 - 但它是我公司的財產,因爲我在他們的硬幣上做了它,所以我不能只提供源代碼。如果您閱讀有關指令並回答具體問題,我可以提供幫助。雖然可能不是最有效的方式,你可能需要請求'$ compile'服務並在''link''函數中使用它。我通過google瞭解了指令和角度(還有很多SO),試驗和錯誤。我不知道有一個專門瞭解指令的好地方。 –

+0

瞭解:指令,隔離範圍,'=','&','@'用於在隔離範圍內進行通信,'$ compile'服務,'angular.element'用於創建遞歸元素,使用'link'屬性指令。這可能是你需要的一切。另一個建議的話:讓這個可重用的指令接受'&'爲了點擊什麼和在哪裏獲得文本顯示(與硬編碼'.text'屬性訪問器相反)。 –

+1

謝謝Jared。我最近沒有太多時間來研究它,但研究了隔離範圍和與我的指令溝通的方法。 我已經設法至少使用指令創建組合,並傳遞必要的參數。我只是沒有得到的部分是在哪裏捕捉組合中的變化。我創建了一個可以觸發的element.on方法。但是,我似乎無法訪問我需要的數據。我已經創建了一個基於我迄今爲止所做的小提琴。正確的方向? http://jsfiddle.net/stevendwebster/E5ss4/7/ –

回答

1

讓我知道如果/爲什麼這不工作,我會相應地解決它。我認爲關鍵的事實是在選項中繼器中,您沒有使用語法來指定選項的ID - 您只是在做它的標籤。

http://jsfiddle.net/KVdqb/

HTML

<div ng-app="bristowRiskApp" ng-controller="organisationalUnitCtrl"> 
    $scope.selections: <pre>{{ selections | json }}</pre> 
    <div ng-repeat="i in range(selections.length - 1)"> 
     <cascade-select data="data" parent-id="selections[i]" selected-id="selections[i + 1]"></cascade-select> 
    </div> 
</div> 

的Javascript

var bristowRiskApp = angular.module('bristowRiskApp', []); 

bristowRiskApp.controller('organisationalUnitCtrl', 

function organisationalUnitCtrl($scope) { 
    $scope.data = [ /* ... */ ]; 

    $scope.selections = [ null, null ]; 

    $scope.$watch('selections', function (value) { 
     if (value[value.length - 1] !== null || value.length < 2) { 
      value.push(null); 
     } else { 
      var index = value.indexOf(null, 1); 
      if (0 < index && index < value.length - 1) { 
       $scope.selections = value.slice(0, index); 
      } 
     } 

    }, true); 

    // Helper function.  
    $scope.range = function (n) { 
     var result = []; 

     for (var i = 0 ; i <n; i++) { 
      result.push(i); 
     } 

     return result; 
    }; 
}); 

bristowRiskApp.directive('cascadeSelect', function() { 
    return { 
     restrict: 'E', 
     replace: true, 
     scope: { 
      parentId: '&', 
      selectedId: '=', 
      data: '=' 
     }, 
     template: '<select ng-show="(data | filter:byId).length > 0" ng-model="selectedId" ng-options="d.Id as d.Name for d in data | filter:byId"><option value="">-- choose organisation unit --</option></select>', 
     link: function (scope, element, attrs) { 
      scope.byId = function (d) { 
       return d.ParentId === scope.parentId(); 
      }; 
     } 
    } 
}); 
+1

非常感謝Jared。這正是我正在尋找的,我找不到任何問題。我想更仔細地研究你的代碼,並嘗試學習你所使用的技術。 –

+0

:)讓我知道你是否有任何東西會讓你痛苦。 –

+0

嗨Jared,「byId」函數難倒了我一段時間,但後來在文檔中閱讀,你可以傳遞一個函數作爲比較器。我確實需要添加的一件事是處理更高級別的組合的代碼。例如,如果4個組合有值,我改變了第2個,它將清除第3個和awaute選擇,但是第4個不會被刪除。 –