Angular Example
Russian Dolls Boxes
by Keval Bhatt
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(d,$index);" style="background-color:lightgreen;" ng-repeat="d in defaultOptions">
<td>{{d.id}}</td>
<td>{{d.type}}</td>
<td>{{d.containsBox}}
<!--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"
}];
function checkInnerObject(obj) {
var i = 0;
var arg = Array.prototype.slice.call(arguments, 1);
start: while (obj) {
console.log(i);
if (obj.hasOwnProperty(arg)) {
obj = obj[arg];
i = i + 1;
continue start;
}
}
return i - 1;
}
$scope.setCurrentBox = function(obj,i) {
BoxService.getBoxItem(obj, function(back) {
var coun =checkInnerObject(back[0], 'box')
if(coun > 0){
$scope.defaultOptions[i]['containsBox'] = coun;
}else{
$scope.defaultOptions[i]['containsBox'] = 0;
}
//back['containsBox'] = containsBox
BoxService.getBoxesAsTab(back, function(data) {
$scope.currentSelection = data;
$scope.currentOptions = [];
//$scope.containsBox = checkInnerObject(data,'box');
//console.log(checkInnerObject(data,box));
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...