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...