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