I nearly struggled as much naming this question as I am with the actual problem! I have two selects:
Select 1:
<select ng-change="bankSelected()" ng-model="user.bankName">
<option selected value="">Select</option>
<option ng-repeat="bank in banks" value="{{bank.name}}">{{bank.name}}</option>
</select>
Select 2:
<select ng-model="user.branch">
<option selected value="">Select</option>
<option ng-repeat="// what to do??"></option>
</select>
The 'bankSelected()' function in my controller:
$scope.bankSelected = function () {
console.log('Bank selected: ' + $scope.user.bankName);
}
I have a JSON file that I import all the bank objects from, here's an example:
{
"banks" : [
{
"name" : "Bank A",
"branches" : [
{
"name" : "Branch 1",
"code" : "1"
},
{
"name" : "Branch 2",
"code" : "2"
}
]
},
{
"name" : "Bank B",
"branches" : [
{
"name" : "Branch 3",
"code" : "3"
},
{
"name" : "Branch 4",
"code" : "4"
},
{
"name" : "Branch 5",
"code" : "5"
}
]
}
]
}
The JSON that I'm actually using though is about 1000 lines long. So my problem, is that if the user selects 'Bank A' in the first select box, I want the second select box to display 'Branch 1' and 'Branch 2'. Likewise if the user selects 'Bank B', I want to display 'Branch 3', 'Branch 4', and 'Branch 5'. If the user has not selected anything in the first select (e.g. no Bank selected), then the second select (branches) shouldn't contain anything. I'm sure you understand what I'm getting at?
How can I make this happen in AngularJS?
bank ng-repeat
<select ng-model="user.bankName">
<option selected value="">Select</option>
<option ng-repeat="bank in banks" value="{{bank.name}}">{{bank.name}}</option>
</select>
branch ng-repeat
<select ng-model="user.branch" ng-show="user.bankName">
<option selected value="">Select</option>
<option ng-repeat="branch in getBranches(user.bankName)" value="{{branch.code}}">{{ branch.name }}</option>
</select>
source of the branch repeat is assign to getBranches() function in the scope and here we pass the bank name which selected before.
in that function
$scope.getBranches = function(selectedBank) {
// get the selected bank object from the banks array
var filteredBank = $filter('filter')($scope.banks, selectedBank);
// return the branches of the selected bank
return filteredBank[0].branches;
};
don't forget to inject the $filter service as below
app.controller('CtrlName', function($scope, $filter) {...
here is the DEMO
If you can change your select to something like below it will be more cleaner :)
this will select the whole object of the selected option.
<select ng-model="user.bankName" ng-options="bank.name for bank in banks">
</select>
here we can use selected bank object to get the branches as user.bankName.branches.
<select ng-model="user.branch" ng-if="user.bankName" ng-options="branch.code as branch.name for branch in user.bankName.branches">
</select>
so we can get rid of the getBranches().
here is the DEMO
Related
I'm trying to change content based on a select field change.
"Monthly" will be the default option on page load. If the user changes the select value to "yearly", I want to replace regularPrice with the yearly one (based on the selected amount of users).
Is there some way I can dynamically change the pricingOption? For example, from {{pricingOptions.monthly.regularPrice}} to {{pricingOptions.yearly.regularPrice}} and also show the correct price based on the selected amount of users?
Is this possible with handlebars.js?
Thanks!
<select>
<option>Pricing</option>
<option value="monthly">Monthly</option>
<option value="yearly">Yearly</option>
</select>
<select>
<option>Number of users</option>
{{#each pricingOptions.monthly}}
<option value="{{id}}">{{optionLabel}}</option>
{{/each}}
</select>
<span>{{pricingOptions.monthly.regularPrice}}</span>
var productList = {
pricingOptions: {
monthly: [
{
id: 1,
optionLabel: "1 user",
regularPrice: 10.00
},
{
id: 2,
optionLabel: "2 users",
regularPrice: 20.00
}
],
yearly: [
{
id: 1,
optionLabel: "1 user",
regularPrice: 100.00
},
{
id: 2,
optionLabel: "2 users",
regularPrice: 200.00
}
]
}
}
I have my object selected via a selection box printed out on the page as the user selects the option.
However it currently prints the parent object and all other objects nested within the parent object.
A example of my array
$scope.productsandformats = [
{
"Pname": "parent",
"format": [
{"Fname": "child", "id": "4"},
{"Fname": "second child", "id": "5"}
]
}
];
My angular and html selection box
<select ng-model="formData.ProductType"
ng-options="product.Pname for product in productsandformats">
<option value="">- Please Choose -</option>
</select>
<pre class="col-sm-12 ng-binding">
{{ formData }}
</pre>
so currently when I select parent I get
{"ProductType":{"Pname":"parent","format":[{"Fname":"child","id":"4"},{"Fname":"second child","id":"5"}]}}
What I expect to see
{"ProductType":{"Pname":"parent"}}
What I need
I just want to see the Pname so the top level objects eg parent, parent2, parent3 so on not the children objects.
How can I alter this to just show the top level object?
#George answer almost works
difficulty my second drop down should be populated with the child objects of the selected parent and the final string should read as following if select parent from first option then second child from second option.
ProductType: Pname: parent, formatType: Fname: child
**Angular code for both boxes, second populated with children of the selected parent **
<select ng-model="formData.ProductType"
ng-options="product.Pname for product in productsandformats">
<option value="">- Please Choose -</option>
</select>
<select ng-model="formData.formatType"
ng-options="format.Fname for format in formData.ProductType.format"
ng-if="formData.ProductType">
<option value="">- Please Choose -</option>
</select>
If you read the documentation on ngOptions you can use select as to specify was object gets set on the ngModel
For the second select I suggest having an ng-change on the first select to store that object in another variable on the scope that you can use for the second select.
var myApp = angular.module('myApp', []);
function MyCtrl($scope) {
$scope.productsandformats = [{
"Pname": "parent",
"format": [{
"Fname": "child",
"id": "4"
}, {
"Fname": "second child",
"id": "5"
}]
}];
$scope.formats = [];
$scope.productTypeChange = function() {
$scope.formats = $scope.productsandformats.find(ps => ps.Pname == $scope.formData.ProductType.Pname);
}
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp">
<div ng-controller="MyCtrl">
<select ng-model="formData.ProductType.Pname" ng-change="productTypeChange()" ng-options="product.Pname as product.Pname for product in productsandformats">
<option value="">- Please Choose -</option>
</select>
<select ng-model="formData.formatType" ng-options="format.Fname for format in formats.format" ng-if="formData.ProductType.Pname">
<option value="">- Please Choose -</option>
</select>
<pre class="col-sm-12 ng-binding">
{{ formData }}
</pre>
</div>
</div>
You can access first level object like this
<div ng-repeat='p in formData.productType'>
{{p.pname}}
</div>
Trying to figure out why the model does not update when the bound selected option no longer exists. I would expect the model's property to update to undefined/null/empty string.
Situation: One select drives another select using filter. After selections are made, go to the original select and choose another option. Filter will remove the second select option as expected, but the model property on the second select will be unchanged.
Problem: When you go to pass the model, it will be populated with bad/previous values. In addition, using Angular validation, the select being required...the form is technically "valid" because the model has a value (the previous value) for the property.
HTML:
<select name="Category" ng-model="selectedCategory"
ng-options="item.name as item.name for item in categories">
<option value="">All Categories</option>
</select>
<select name="SubCategory" ng-model="selectedSubCategory"
ng-options="item.name as item.subCategory for item in categories | filter:selectedCategory">
<option value="">All SubCategories</option>
</select>
Model:
app.controller('MainCtrl', function($scope) {
$scope.categories = [{
"id": "1",
"name": "Truck",
"subCategory": "Telescope"
}, {
"id": "2",
"name": "Truck",
"subCategory": "Hazmat"
}, {
"id": "3",
"name": "Van",
"subCategory": "Mini"
}];
});
I'm fairly certain I could tie an ng-change function to the first to force it to update the model, but is there a better way?
Example Plunker demonstrating the problem
Try this way:
$scope.$watch('selectedCategory', function(selectedCategory){
$scope.selectedSubCategory = null;
});
i want to filter my output based on the selected value in a component:
<select ng-model="showGroup.group">
<option value="A">A</option>
<option value="B">B</option>
</select>
My Data which i want to show:
{
"name" : "Steve",
"group" : "A"
},
{
"name" : "Bob",
"group" : "B"
},
{
"name" : "Peter",
"group" : "B"
},
If a "A" is selected then i should show only Steve and if "B" is selected it should show Bob and Peter!
My Outputcode:
<table>
<tr ng-repeat="person in persons">
<td>{{person.name | filter:showGroup}}</td>
</tr>
</table>
The Controller only gets the data from a JSON file.
Why this is not working?
With an <input> element it works fine?!
Do I need to write my own filter? How do i do that?
Your filter is not correct. Please view this Plunkr.
I have 2 select boxes, one to choose the user type (e.g. groups or individual) and the 2nd to the out put of the 1st one to display the options to choose the user/group.
is there anyway that in my expressions for ng-options I could pass it a function instead of a variable like so :
ng-options="user.id as user.description for user in getUserList(userType)"
where userType is the ng-model of the first select box
I'm under the impression from my own trials that this is not possible (seem's to crash the the current tab in chrome and the entire application in firefox).
what would be the best approach to this. I have a lot of selects that use this kind of 2 select box setup so it would be nice If I could avoid copying and pasting.
Rather than using a function in ng-options try this;
In your first select box use ng-change directive like this;
<select ng-options="user.id as user.description for user in firstSelect" ng-model="firstSelectBox" ng-change="change();"></select>
In your controller;
$scope.firstSelect=[{values of first select box}]
$scope.change = function(){
$value = $scope.firstSelectBox;
$http.get('API url').success(function (data) {
$scope.secondSelect = data;
});
}
Change your second select box as;
<select ng-options="user.id as user.description for user in secondSelect" ng-model="secondSelectBox"></select>
Hope it helps.
depending on your data, it could be as simple as:
<select ng-model="type" ng-options="type for type in types"></select>
<select ng-model="user" ng-options="user.name for user in users[type]" ng-if="type != 'skipped'"></select>
with:
app.controller('AppCtrl', ['$scope', function($scope) {
$scope.types = ['group', 'individual', 'skipped'];
$scope.type = $scope.types[0];
$scope.users = {
group: [
{ id: 1, name: 'foo' },
{ id: 2, name: 'bar' }
],
individual: [
{ id: 3, name: 'foobar' },
{ id: 4, name: 'barfoo' }
]
};
}]);
demo: http://jsbin.com/EyuQ/2/
You can do this as below:
HTML
<div ng-app="myApp" ng-controller="BookingCtrl">
<select ng-model="selected.Type" ng-options="s.Type for s in data">
<option value="">-- Type --</option>
</select>
<select ng-model="selected.Books" ng-options="b.Books for b in selected.Type.Books">
<option value="">-- Books --</option>
</select>
<select ng-model="selected.c" ng-options="f.c for f in selected.Type.cat">
<option value="">-- Category --</option>
</select>
</div>
JS
var myApp = angular.module( 'myApp', [] );
myApp.controller( 'BookingCtrl', ['$scope', '$location', function ( $scope, $location ) {
$scope.selected = {};
$scope.data = [
{
"id" : "0",
"Type" : "Study",
"Books" : [
{ "Books" : "Study Book 1" },
{ "Books" : "Study Book 2" },
{ "Books" : "Study Book 3" }
],
"cat" : [
{ "c" : "#1" },
{ "c" : "#2" },
{ "c" : "#3" }
]
},{
"id" : "1",
"Type" : "General",
"Books" : [
{ "Books" : "Book14" },
{ "Books" : "Book15" },
{ "Books" : "Book16" }
],
"cat" : [
{ "c" : "#4" },
{ "c" : "#5" },
{ "c" : "#6" }
]
}
];
}]);
check out this fiddle,
http://jsfiddle.net/PXwrf/2/