Reputation: 165
I have some data that consists of various brands, and each brand has a nested array (of strings) containing range names:
[
{
"brandName" : "Brand 1",
"ranges" : [
"Range A1",
"Range A2",
"Range A3"
]
},
{
"brand" : "Brand 2",
"ranges" : [
"Range B1",
"Range B2",
"Range B3"
]
},
]
What I am trying to do is display a select element with a list of options containing range names as their values and innerHTML, based on the previously selected brand in a separate select element.
I'm not sure how to go about targeting the selected brand object in order to gain access to the nested array, as I'm trying to do it 'the Angular way'.
Currently, I've been trying with ngRepeat, but can't get it to work.
In the controller:
$scope.formData = {
brandData : [
{
"brandName" : "Brand 1",
"ranges" : [
"Range A1",
"Range A2",
"Range A3"
]
},
{
"brandName" : "Brand 2",
"ranges" : [
"Range B1",
"Range B2",
"Range B3"
]
},
],
currentBrand : undefined,
currentRange : undefined
};
And the simplified markup:
<select name="currentBrand" ng-model="formData.currentBrand">
<option value="" disabled>Select a brand</option>
<option value="none" selected>None</option>
<option ng-repeat="brand in formData.brandData" value="{{brand.brandName}}">{{brand.brandName}}</option>
</select>
<select name="currentRange" ng-model="formData.currentRange">
<option value="" disabled>Select a range</option>
<option value="none" selected>None</option>
<option ng-repeat="how do I show each range name in the 'ranges' array of the selected brand ????? value="{{rangeName}}">{{rangeName}}</option>
</select>
There are some similar questions floating around, but I couldn't find any specific to the data structure that I have.
Thanks in advance!
UPDATE
Thanks to Rohan, I have now achieved my original goal. However, I also wanted the value of each option
element to get set to the same value as its innerHTML. To do this I used the track by...
feature of ngOptions:
<select name="currentBrand" ng-model="formData.currentBrand" ng-options="brandOption as brandOption.brandName for brandOption in brandOptions track by brandOption.brandName">
<option value="" disabled>Select a brand</option>
</select>
<select name="currentRange" ng-model="formData.currentRange" ng-options="rangeOption for rangeOption in formData.currentBrand.ranges track by rangeOption">
<option value="" disabled>Select a range</option>
</select>
For a working example, I have forked and updated Rohan's jsfiddle: http://jsfiddle.net/munkychop/hgzdannz/1/
Upvotes: 4
Views: 391
Reputation: 7976
Use ng-options for this: https://docs.angularjs.org/api/ng/directive/select
You need to set your selected brand as an object, then use that brand to repeat over your ranges in your next ng-options select.
<div>
<select name="currentBrand" ng-model="currentBrand"
ng-options="brandOption as brandOption.brandName for brandOption in brandOptions">
<option value="" disabled>Select a brand</option>
</select>
</div>
<span>Selected brand: {{currentBrand}}</span>
<div>
<select name="currentRange" ng-model="currentRange"
ng-options="rangeOption for rangeOption in currentBrand.ranges">
<option value="" disabled>Select a range</option>
</select>
</div>
<span>Selected Range: {{currentRange}}</span>
</div>
Here's your working snippet of code:
Upvotes: 5
Reputation: 2905
What you need is an index to your selected element in the brand array, so that you can use it in ng-repeat like this:
<option ng-repeat="range in formData.brandData[currentBrand].ranges" value="{{rangeName}}">{{rangeName}}</option>
You can have a variable on your scope to store this, or you can do it more easily by using the index as the value of your options:
<option ng-repeat="brand in formData.brandData" value="{{$index}}">{{brand.brandName}}</option>
Since curretBrand is the model for your select, 2-way data binding will update your brand selector when it changes without the need for any more code on your controller.
Here is a fiddle to demonstrate.
Upvotes: 2
Reputation: 5246
You could take the approach of defining an method in the controller to get you the range corresponding to the currently selected brand. This may be an approximation to get you going in the right direction:
$scope.getCurrentBrandRanges = function() {
for (var i=0;i < $scope.formData.brandData.length;i++) {
if ($scope.formData.brandData[i].brandName == $scope.formData.currentBrand)
return $scope.formData.brandData[i].ranges;
}
return []; // In case nothing matches for some reason.
}
And for the ng-repeat
directive you can specify something like:
ng-repeat="range in getCurrentBrandRanges()"
Upvotes: 0