How to bind selected elements in SELECT multiple - javascript

I have a select multiple like this
<select
id="countries"
ng-model="country"
ng-options="option.name for option in countryOptions track by option.id"
multiple>
</select>
to populate this select I am doing:
let countries = [];
countries.push({
id: country.id,
name: country.name,
selected: false
});
$scope.countryOptions = countries;
then acting on another element, I loop scope.countryOptions to check if any of its elements are in another array, and in that case I mark them as selected:
$scope.countryOptions.forEach((country, index) => {
$scope.countryOptions[index].selected = activeCountries.indexOf(country.id) !== -1;
});
What should I do to have the selected elements highlighted in the select multiple (in the UI)?

Your data source $scope.countryOptions and the user's selected countries $scope.country are different. Keep your data source pure and track user selections separately.
angular.module('selectExample', [])
.controller('ExampleController', ['$scope', function($scope) {
$scope.countryOptions = [{ id: 1, name: "Brazil" },
{ id: 2, name: "France" },
{ id: 3, name: "Djibouti" }
];
let activeCountries = [1, 3]
// init
$scope.country = $scope.countryOptions.filter(c => activeCountries.indexOf(c.id) > -1)
}]);
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.10/angular.min.js"></script>
<div ng-app="selectExample">
<div ng-controller="ExampleController">
<select id="countries" ng-model="country" ng-options="option.name for option in countryOptions track by option.id" multiple>
</select>
<hr> {{country}}
</div>
</div>

Related

Select does not keep the value chosen by user

I'm new on Angular, and i'm pretty stuck on a simple select problem.
i did a simple select which iterate my scope to populate the select, but after a user click on an option (which are well created), my select becomes blank with no selection inside, and if i click it again there are no options visible.
below is my code:
var app = angular.module("myApp", []);
app.controller("myCtrl", function($scope) {
$scope.searchFilterDispatcher = {};
$scope.searchFilterDispatcher.distributionCode = [{
id: 1,
label: 'dist1'
}, {
id: 2,
label: 'dist2'
}];
});
<script
src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js">
</script>
<select ng-model="searchFilterDispatcher.distributionCode"
ng-options="item as (item.label | uppercase) for item in
searchFilterDispatcher.distributionCode"
class="form-control"
id="distributionCode">
<option >{{'SELECT_A_VALUE' | translate}}</option>
</select>
Any hint?
You should change your ng-model like following. It works in snippet
var app = angular.module("myApp", []);
app.controller("myCtrl", function($scope) {
$scope.searchFilterDispatcher = {};
$scope.searchFilterDispatcher.distributionCode = [{
id: 1,
label: 'dist1'
}, {
id: 2,
label: 'dist2'
}];
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myCtrl">
<select ng-model="val" ng-options="item as (item.label | uppercase) for item in searchFilterDispatcher.distributionCode" class="form-control" id="distributionCode">
</select>
</div>

AngularJS: Call function after user makes selection in dropdown

so I have a dropdown and added some values as shown below.
I want the program to do stuff based on the selected options from drop box.
angular.module('priceCalculator', [])
.controller("mainCtrl", ['$scope', function($scope) {
$scope.data = {
availableOptions: [
{id: 0, name: 'Please Select'},
{id: 1, name: 'PVC Red Extra'},
{id: 2, name: 'Alu Standard'},
{id: 3, name: 'SKS Classic Decor'},
{id: 4, name: 'SKS Aluminiu Alb'}
],
selectedOption: {id: 0, name: 'Please Select'}
};
}]);
I was thinking I could do it with a switch statement
$scope.doStuff = function() {
switch(id from availableOptions) {
case 0:
// do stuff, I want to read file based on inputs I shall also get from user
break;
default:
// do stuff
};
};
How do I need to do this? Sorry if it's easy for everybody, I'm really noob at coding
Here's the html section
<label>Select Shutter Type</label>
<!-- Use ngOption to select shutter type -->
<select ng-options="option.name for option in data.availableOptions track by option.id" ng-model="data.selectedOption">
</select>
If i understand correctly, you would like your doStuff function to be called when the selection changes. You can use ng-change to do that:
<select
ng-options="option.name for option in data.availableOptions track by option.id"
ng-model="data.selectedOption"
ng-change="doStuff(option)">
Then you can declare doStuff like this:
$scope.doStuff = function(selectedOption) {

why isn't my angular options track by id working

I'm sure I must be doing this wrong, but:
I have an object that stores the id of an item. I also have an array of these items. I need to have a 'select' that represents the currently selected item, but that can also change the selected item.
I have set the 'select's model to the object.selectId.
The 'select' ng-options is "option.Text for option in options track by optionId"
Yet the model and 'select' options types don't match
How do I achieve what I need?
Here's a fiddle of what I am doing: https://jsfiddle.net/vb2xe1mc/5/
Code:
<script>
angular.module('myApp', [])
.controller('myctrl', ['$scope', function($scope) {
$scope.item = {
id: 1
};
$scope.options = [
{Text: "zero", Id: 0},
{Text: "one", Id: 1},
{Text: "two", Id: 2},
{Text: "three", Id: 3}
];
$scope.selectChange = function() {
alert($scope.item.id);
};
}]);
</script>
<div ng-app="myApp">
<div ng-controller="myctrl">
<select ng-model="item.id" ng-options="option.Text for option in options track by option.Id" ng-change='selectChange()'>
</select>
</div>
</div>
If you can, please let me know where I have gone wrong or correct the fiddle.
Thanks ^_^
Andy
Clarification:
The model item has id 1 already selected. I need the list to preselect the option with id 1 in this case. Also, When the option is selected it does not set the item.id to an int, rather it sets it to the entire option item. I need it to set the item.id to the option.Id
<select ng-model="item.id" ng-options="option.id as option.Text for option in options" ng-change='selectChange()'>
You want to select option.id, not option and track by is unnecessary.
Bind the select to ng-model="item", not ng-model="item.id".
Also decide on id vs. Id
<div ng-app="myApp">
<div ng-controller="myctrl">
<select ng-model="item" ng-options="option.Text for option in options track by option.Id" ng-change='selectChange()'>
</select>
</div>
</div>
angular.module('myApp', [])
.controller('myctrl', ['$scope', function($scope) {
$scope.item = {
Id: 1
};
$scope.options = [{
Text: "zero",
Id: 0
}, {
Text: "one",
Id: 1
}, {
Text: "two",
Id: 2
}, {
Text: "three",
Id: 3
}, ];
$scope.selectChange = function() {
console.log ($scope.item.Id)
alert($scope.item.Id);
};
}]);
See here for a fixed version: https://jsfiddle.net/ax3k418p/
https://jsfiddle.net/vb2xe1mc/10/
You need to bind item to ng-model, and inititally $scope.Id should be set to 1 not $scope.id = 1
Also check when you alert it should be alert($scope.item.Id);
<div ng-app="myApp">
<div ng-controller="myctrl">
<select ng-model="item" ng-options="option.Text for option in options" ng-change='selectChange()'>
</select>
</div>
</div>
JS:
angular.module('myApp', [])
.controller('myctrl', ['$scope', function($scope) {
$scope.item = {
Id: 1
};
$scope.options = [{
Text: "zero",
Id: 0
}, {
Text: "one",
Id: 1
}, {
Text: "two",
Id: 2
}, {
Text: "three",
Id: 3
}, ];
$scope.selectChange = function() {
alert($scope.item.Id);
};
}]);

Angularjs Dropdown OnChange Selected Text and Value

I am new to AngularJS and trying to get Selected Text and Value from Dropdown. I followed a lot of tutorials with still unable to get there. SelectedValue and SelectedText are always undefined. Below is my code:
Html:
<div ng-app="SelectApp">
<div ng-controller="selectController">
<select name="category-group" id="categoryGroup" class="form-control" ng-model="itemSelected" ng-change="onCategoryChange(itemSelected)">
<option value="0">Select a category...</option>
<option ng-repeat="category in categories" value="{{category.id}}"
ng-disabled="category.disabled" ng-class="{'mainCategory' : category.disabled}">
{{category.name}}
</option>
</select>
</div>
Js:
'use strict';
var app = angular.module('SelectApp', [ ]);
app.controller('selectController', ['$scope', '$window', function ($scope, $window) {
$scope.categories = [
{ id: 1, name: "- Vehicles -", disabled: true },
{ id: 2, name: "Cars" },
{ id: 3, name: "Commercial vehicles", disabled: false },
{ id: 4, name: "Motorcycles", disabled: false },
{ id: 5, name: "Car & Motorcycle Equipment", disabled: false },
{ id: 6, name: "Boats", disabled: false },
{ id: 7, name: "Other Vehicles", disabled: false },
{ id: 8, name: "- House and Children -", disabled: true },
{ id: 9, name: "Appliances", disabled: false },
{ id: 10, name: "Inside", disabled: false },
{ id: 11, name: "Games and Clothing", disabled: false },
{ id: 12, name: "Garden", disabled: false }
];
$scope.onCategoryChange = function () {
$window.alert("Selected Value: " + $scope.itemSelected.id + "\nSelected Text: " + $scope.itemSelected.name);
};
}]);
And one more thing, I have defined my first item as Select a category... then Why first item in Dropdown is always empty.
Below is my fiddle sample.
http://jsfiddle.net/Qgmz7/136/
That's because, your model itemSelected captures the current value of your select drop down which is nothing but the value attribute of your option element. You have
<option ng-repeat="category in categories" value="{{category.id}}">
in your code, so in the rendered version, you'll get
<option ng-repeat="category in categories" value="0">
but you're expecting itemSelected to be your category object and any attempt to query id or other property will return undefined.
You can use ng-options with group by with little bit of change to your data or you can use normal ng-repeat, get the selectedIndex and lookup the category object from your categories list using that index. Showcasing the first approach here.
HTML
<select name="category-group" id="categoryGroup"
ng-model="itemSelected" ng-change="onCategoryChange(itemSelected)"
ng-options="category.name group by category.group for category in categories">
</select>
Updated Data
$scope.categories = [
{ id: 0, name: "Select a category..."},
{ id: 1, name: "Cars", group : "- Vehicles -" },
{ id: 2, name: "Commercial vehicles", group : "- Vehicles -" },
{ id: 3, name: "Motorcycles", group : "- Vehicles -" }
];
$scope.itemSelected = $scope.categories[0];
Instead of disabled property, you can add a group property which can be used in group by.
Here' an updated Fiddle to illustrate the idea.
You should use ng-options to set object to your ng-model value on change of you select options.
Markup
<select name="category-group" id="categoryGroup" class="form-control"
ng-model="itemSelected" ng-change="onCategoryChange(itemSelected)"
ng-options="category.name for category in categories">
<option value="0">Select a category...</option>
</select>
Fiddle Here
Update
For persisting style you have to use ng-repeat there, in that case you will only have id binded to your ng-model and while retrieving whole object you need to filter your data.
$scope.onCategoryChange = function () {
var currentSelected = $filter('filter')($scope.categories, {id: $scope.itemSelected})[0]
$window.alert("Selected Value: " + currentSelected.id + "\nSelected Text: " + currentSelected.name);
};
Updated Fiddle
<div ng-app="SelectApp">
<div ng-controller="selectController">
<select ng-change='onCategoryChange()' ng-model="itemSelected" ng-options="category.name for category in categories">
<option value="">-- category --</option>
</select>
</div>
//http://jsbin.com/zajipe/edit?html,js,output
A little change in your onCategoryChange() should work:
$scope.onCategoryChange = function () {
$window.alert("Selected Value: " + $scope.categories[$scope.itemSelected - 1].id + "\nSelected Text: " + $scope.categories[$scope.itemSelected -1].name);
};
JSFiddle: http://jsfiddle.net/Qgmz7/144/
ngChange only returns the value of your selected option and that's why you don't get the whole data.
Here's a working solution without changing your markup logic.
Markup:
<select
name="category-group"
id="categoryGroup"
class="form-control"
ng-model="id"
ng-change="onCategoryChange(id)">
ngChange handler:
$scope.onCategoryChange = function (id) {
//get selected item data from categories
var selectedIndex = $scope.categories.map(function(obj) { return obj.id; }).indexOf( parseInt(id) );
var itemSelected = $scope.categories[selectedIndex];
$window.alert("Selected Value: " + itemSelected.id + "\nSelected Text: " + itemSelected.name);
};
Another solution (little bit dirty) would be to change only the value of your options into something like this:
<option .... value="{{category.id}}|{{category.name}}">
...and inside your actual ngChange handler, just split the value to get all the values as an array:
$scope.onCategoryChange = function (itemSelected) {
$scope.itemSelected = itemSelected.split('|'); //string value to array
$window.alert("Selected Value: " + $scope.itemSelected[0] + "\nSelected Text: " + $scope.itemSelected[1]);
};
Here very Simple and easy code What I did
<div ng-app="myApp" ng-controller="myCtrl">
Select Person:
<select ng-model="selectedData">
<option ng-repeat="person in persons" value={{person.age}}>
{{person.name}}
</option>
</select>
<div ng-bind="selectedData">AGE:</DIV>
<br>
</div>
<script>
var app = angular.module('myApp', []);
app.controller('myCtrl',myCtrlFn);
function myCtrlFn($scope) {
$scope.persons =[
{'name': 'Prabu','age': 20},
{'name': 'Ram','age': 24},
{'name': 'S','age': 14},
{'name': 'P','age': 15}
];
}
</script>

Angularjs: update select options

I have two select menus . One for country selection and other for state. I need to update states based country selected. I am able to log states but not able to list them in select menu.Please help.
Angular:
angular.module('demoApp', []).controller('DemoController', function($scope) {
$scope.countries = [
{ label: 'Please select', value: 0 },
{ label: 'India', value: 1 },
{ label: 'US', value: 2 }
];
$scope.data = [{'1':[{ label: 'Delhi', value: 0 },{ label: 'Mumbai', value: 1 },{ label: 'Chennai', value: 2 }]},
{'2':[{ label: 'Alabama', value: 3 },{ label: 'Alaska', value: 4 },{ label: 'Arizona', value: 5 }]}];
$scope.vm = {states: []};
$scope.updateStates = function(countryCode){
$scope.vm.states = $scope.data[countryCode-1];
console.log($scope.vm.states);
};
$scope.correctlySelected = $scope.countries[0];
});
HTML:
<body ng-app="demoApp">
<div ng-controller="DemoController">
<select ng-model="correctlySelected" ng-change="updateStates(correctlySelected.value)" ng-options="opt as opt.label for opt in countries">
</select>
<select ng-options="opt as opt.label for opt in vm.states">
</select>
</div>
</body>
JS Bin:
http://jsbin.com/pafosewedo/1/edit?html,js,console,output
You need to add ng-model to your states <select> - this is required when you are using ng-options
You also have an inconvenient model for the states data. Each element of the data array that corresponds to the country's states is an object with a changing key whose value is an array of states. You could make it work, but it's better to change it to something more reasonable:
$scope.data = {
1: [{ label: 'Delhi', value: 0 }, {...}, ],
2: [{...}, {...}, ] // same for US
}
Then it would work with how you specified your ng-options for states, and you wouldn't have to deal with indices:
$scope.updateStates = function(countryCode){
$scope.vm.states = $scope.data[countryCode]; // access by property
};
I think, that you should use some filter like that if you don't want to change your model:
.filter('stateFilter', function() {
return function(states, countryID) {
var filtered = [];
angular.forEach(states, function(state){
if(state.value === countryID)
filtered.push(state);
});
return filtered;
};
});
to filter out all values that have value equal to selected country.value in first select control.
To use that filter you need to modify your ng-repeat directive value in state select control:
ng-options="state as state.label for data | stateFilter:correctlySelected"
I came up with the following solution, view my JSBin
This solutions works by setting the countryCode in the scope when we are updatingStates.
$scope.updateStates = function(countryCode){
$scope.countryCode = countryCode;
$scope.vm.states = $scope.data[countryCode-1];
console.log($scope.vm.states[countryCode]);
};
This change is then reflected in the view.
<select>
<option ng-repeat='i in vm.states[countryCode]'> {{i.label}}
</option>
</select>

Categories

Resources