Angular Example
Russian Dolls Boxes
HTML
<div ng-app="myApp" ng-controller="BoxController">
<span style="font-size:x-small;">Click on the table row (green line) to set "pre-defined" (hardcoded) data</span>
<h5>
EXPLANATION :
</h5>
<span style="font-size:x-small;">Objective here is to make some kind of "dynamic selects list" with a model that could look like the "Russian Dolls", meaning that an object (a box) can contain another one. And next one too, and so on... When user selects a box from a "top" choice, lower choices should change considering the select option he chose.<br/><br/>
<b>Restrictions : </b><br/>
- yellow box can NOT contain any box<br/>
- red box can contain green and yellow box<br/>
- black box can only contain blue, green and red box<br/>
- blue and green boxes can contain a box of any type<br/>
(These restrictions will come from a $http query, here in my example I hardcoded the possible options and return them as an array)<br/><br/>
The select boxes come from a directive (ng-repeat) and should trigger an update on change. <br/>
I actually worked on it with arrays, but I'm sure this is not a solution. Meaning that, instead of working on an object, containing another one, and another one and... I managed to retrieve the items as an array, so I know that first (top) choice is array[0] item, ... But sure this is not a good solution and there should be another way to do the job... </span><br/><br/>
<table class='table'>
<thead>
<tr style="border:1px solid black;">
<td style="border:1px solid black;">id</td>
<td style="border:1px solid black;">type</td>
<td style="border:1px solid black;">contains</td>
</tr>
</thead>
<tbody>
<tr ng-click="setCurrentBox('1');" style="background-color:lightgreen;">
<td>1</td>
<td>Black</td>
<td>2 <!--I don't know how to get this value--></td>
</tr>
...
JavaScript
var app = angular.module('myApp', []);
app.controller('BoxController',['$scope','BoxService',function ($scope,BoxService) {
$scope.currentBox = {};
$scope.currentSelection = [];
$scope.currentOptions = [];
$scope.defaultOptions = [{"id":1,"type":"black"},{"id":8,"type":"red"},{"id":15,"type":"green"},{"id":10,"type":"yellow"},{"id":3,"type":"blue"}];
$scope.setCurrentBox = function(id){
BoxService.getBoxItem(id,function(back){
$scope.currentBox = back;
BoxService.getBoxesAsTab(back,function(data){
$scope.currentSelection = data;
$scope.currentOptions = [];
angular.forEach(data,function(val,count){
BoxService.getBoxOptions(val.type,function(back1){
$scope.currentOptions[count] = back1;
});
});
});
});
};
}]);
app.directive('editForm',function(){
return {
restrict : 'E',
template : '1st choice : <select ng-model="currentSelection[0].id" ng-options="obj.id as obj.type for obj in defaultOptions"></select>'
+'<div class="editor" ng-repeat="item in currentSelection">'
+'<br/><br/>Choice {{$index}} : '
+'<div> Id : <label>{{item.id}}</label></div>'
+'<div> Type : <label>{{item.type}}</label></div>'
+'<div id="boxes" style="border:1px solid red;">'
+'Box : '
+' <select ng-model="item.box.id" ng-options="obj.id as obj.type for obj in currentOptions[{{$index}}]"></select>'
+'</div>'
+'</div>'
};
});
//This is the http service supposed to retrieve boxes data. HARDCODED for the example
app.factory('BoxService',['$http',function($http){
return {
getBoxItem : function(id,callback){
$http({
method : 'POST',
url : '/echo/json/',
data : {'id':id}
})
.success(function(data){
callback({"id":1,"type":"black","box":{"id":8,"type":"red","box":{"id":15,"type":"green","box":null}}});
})
.error(function(err){
callback(err);
});
...