10

What I am trying to do is have three different <select> menus which will be all be tied into the same data. Changing the first select menu, will change menus 2 and 3's data.

This is the inside of my Controller:

$scope.data = [
        {
            "id" : "0",
            "site" : "Brands Hatch",
            "buildings" : [
                { "building" : "Building #1" },
                { "building" : "Building #2" },
                { "building" : "Building #3" }
            ],
            "floors" : [
                { "floor" : "Floor #1" },
                { "floor" : "Floor #2" },
                { "floor" : "Floor #3" }
            ]
        },{
            "id" : "1",
            "site" : "Silverstone",
            "buildings" : [
                { "building" : "Building #4" },
                { "building" : "Building #5" },
                { "building" : "Building #6" }
            ],
            "floors" : [
                { "floor" : "Floor #4" },
                { "floor" : "Floor #5" },
                { "floor" : "Floor #6" }
            ]
        }
    ];

Here's what I have tried from a reference so far, which uses the same idea I need: http://codepen.io/adnan-i/pen/gLtap

When I select either 'Brands Hatch' or 'Silverstone' from the first select menu, the other two menus will have their data change/update to correspond with the correct data. I am using $watch to listen for changes, which I've taken from the above CodePen link.

Here's the watching script (unmodified and obviously not working):

$scope.$watch('selected.id', function(id){
        delete $scope.selected.value;
        angular.forEach($scope.data, function(attr){
            if(attr.id === id){
                $scope.selectedAttr = attr;
            }
        });
    });

As far as I know, this deletes the current data on change, then loops through $scope.data and if the attr.id matches the id passed into the function, it pushes the data back to the scope which updates the views. I am just really stuck on structuring this and would appreciate some guidance and help as I am really new to AngularJS. Thank you! :)

jsFiddle for the full workings if anyone can help out: http://jsfiddle.net/sgdea/

Stephen Jenkins
  • 1,776
  • 3
  • 24
  • 39

1 Answers1

17

Check out what I've done here: http://jsfiddle.net/sgdea/2/

You don't need to use $watch at all -- you just need to make the inputs for each dependent select reference the selection in the parent.

Note how the ng-options for the second and third select reference selected.site, which is set by the first select:

<div ng-app="myApp" ng-controller="BookingCtrl">
    <select ng-model="selected.site"
            ng-options="s.site for s in data">
        <option value="">-- Site --</option>
    </select>
    <select ng-model="selected.building"
            ng-options="b.building for b in selected.site.buildings">
        <option value="">-- Building --</option>
    </select>
    <select ng-model="selected.floor"
            ng-options="f.floor for f in selected.site.floors">
        <option value="">-- Floor --</option>
    </select>
</div>

All I did in the javascript was remove your $watch:

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

myApp.controller( 'BookingCtrl', ['$scope', '$location', function ( $scope, $location ) {

    $scope.selected = {};

    $scope.data = [
        {
            "id" : "0",
            "site" : "Brands Hatch",
            "buildings" : [
                { "building" : "Building #1" },
                { "building" : "Building #2" },
                { "building" : "Building #3" }
            ],
            "floors" : [
                { "floor" : "Floor #1" },
                { "floor" : "Floor #2" },
                { "floor" : "Floor #3" }
            ]
        },{
            "id" : "1",
            "site" : "Silverstone",
            "buildings" : [
                { "building" : "Building #4" },
                { "building" : "Building #5" },
                { "building" : "Building #6" }
            ],
            "floors" : [
                { "floor" : "Floor #4" },
                { "floor" : "Floor #5" },
                { "floor" : "Floor #6" }
            ]
        }
    ];
}]);
John Ledbetter
  • 13,557
  • 1
  • 61
  • 80
  • What if I just want to use default select options? That is, I never want to see a "blank option". What if I also want the ability to dynamically update `select-1` and `select-2` in the controller through a function. How would I go about handling those two senarios? Here's a fork of the problem: http://jsfiddle.net/7Kzgr/ – Dan Kanze Aug 02 '13 at 16:55
  • I've also added a question: http://stackoverflow.com/questions/18022682/default-ngoptions-on-parent-child-models-angularjs – Dan Kanze Aug 02 '13 at 17:20
  • This is a very cool solution, @JohnLedbetter , is there a way to generate the selects with ng-repeat? – SoluableNonagon May 16 '14 at 18:02