Search code examples
angularjsangularjs-ng-repeathtml-select

Angular - how to make a an option field (with ng-repeat) depend on previously chosen value in option field?


I have 3 fields. 1st - option field / ng-repeat over available dates 2nd - option field / based on the date chosen by user, I do ng-repeat over quantity. I have tried all different ways but I can't make it depend on the first option field or other things don't work. Any help would be great! Thanks !!

html:

<div class="containerDiv">
        <div>
            <select ng-model='date'>
                <option ng-repeat="availableDateProduct in product " value='{{i}}'>{{availableDateProduct.dateOfActivity}}
                </option>
            </select>
        </div>

        <div ng-repeat="availableDateProduct in product ">
            <select>
                <option ng-repeat='i in quantityLister(availableDateProduct.quantity)' value='{{i}}'>
                    {{i}}
                </option>
            </select>
        </div>
        <div>
            <button>Book</button>
        </div>
    </div>

js:

    app.controller('ProductCtrl', function($scope, ProductsFactory, $stateParams) {

        ProductsFactory.fetchByTitle($stateParams.title)
            .then(function(product) {
                $scope.product = product;
            })
        $scope.quantityLister = function(num) {
            var array = [];
            for (var i = 1; i <= num; i++) {
                array.push(i)
            }
            return array;
        }
    })

data:

var products = [
  {
    title:'Bowling',
    description:'Its fun!',
    photoUrl:'https://www.1.jpg',
    quantity:12,
    price:9,
    dateOfActivity: '2017-13-07'
  },
...
]

Thanks!!


Solution

  • Angular has a directive built specifically to accomplish this task; ng-options.

    First, we define an object in the controller that will hold the values selected from the dropdown:

    $scope.reservation = {};
    

    Next, we use ng-options on our dropdowns, and use the ng-model property to accept the value selected. In the first dropdown, we take the array of products, display the dateOfActivity for each product, and save the product object to ng-model when selected. (work from right to left in the ng-options definition).

    ng-model="reservation.selectedProduct"  
    ng-options="product as product.dateOfActivity for product in products"
    

    In our second dropdown, you have defined a function to take a number and spread it into an array. We call this function from reservation.selectedProduct.quantity, and then use this array as the basis for the ng-options:

    ng-model="reservation.selectedQuantity" 
    ng-options="num for num in quantityLister(reservation.selectedProduct.quantity)"
    

    Now we have an object which has the selected values for both dropdowns, we just need to change the quantity in the original array on button press. we also want to clear the selections afterwords, to ensure that the user can't accidentally make a duplicate reservation.

    $scope.reserve = function (){
      $scope.reservation.selectedProduct.quantity -= $scope.reservation.selectedQuantity;
      $scope.reservation = {};
    };
    

    Here we use the shorthand -= to subtract the selectedQuantity from the selectedProduct.quantity. since selectedProduct is two way bound, the change to selectedProduct is reflected in the original object in the product array as well. However, The quantityLister function isn't dynamic; if we don't reset $scope.reservation, the second dropdown would hold a now invalid number of available reservations.