AngularJS <select> view value not updated - angularjs

I have an array of models. I start with one model, then copy that model and push it to the stack. My view shows the array of models in one page.
But the view for the copied models isn't correct. More specifically the <select> isn't displaying the correct value.
Controller:
$scope.colors = [
{
id: 1,
name: 'Green'
},
{
id: 2,
name: 'Red'
}
];
var itemModel = {
name: '',
color: null
};
$scope.items = [
angular.copy(itemModel)
];
$scope.copyItem = function(item) {
$scope.items.push(angular.copy(item));
};
Plunker: https://plnkr.co/edit/sVBL9j3JmCjdLZtr7HCH?p=preview
Any suggestions?

How about this:
<select ng-model="item.color" ng-options="color.name as color.name for color in colors">
<option value="">None</option>
</select>

Try this:
<select ng-model="item.color" ng-options="color as color.name for color in colors track by color.id">
<option value="">None</option>
</select>

Related

Angularjs: Select ng-model not working

I'm having an issue with a selection box. When I select the option I can't get the value that I just selected. I read a lot of answers, but none of them seems to work for me. Here is my code.
HTML:
<select class="wide" style="width: 96%;height: 100px;"
ng-options="element as element.type for element in elements"
ng-model="selectedType" >
<option value="">Choose an option</option>
</select>
<p> {{selectedType}} </p>
Controller:
elements:[
{
desc: "example1",
article: "OF",
type: "example1Type"
},
{
desc: "example2",
article: "P-8955625",
type: "example2Type"
}
];
$scope.selectedType = "";
The <p> {{selectedType}} </p> shows nothing.
Thanks in advance
The as its only for the display value, but for the ng-model present the entire selected item.
so you need wirte:
<p> {{selectedType.type}} </p>
https://embed.plnkr.co/bicmN1loBGdcxsWOLv6x/
elements needs to be set in the controller scope. e.g.
app.controller('ExCtrl', function($scope) {
$scope.elements = [{
desc: "example1",
article: "OF",
type: "example1Type"
}, {
desc: "example2",
article: "P-8955625",
type: "example2Type"
}];
});
Also, attach the controller to your view. e.g.
<body ng-controller="ExCtrl">
<select class="wide"
ng-options="element.type for element in elements"
ng-model="selectedType" >
<option value="">Choose an option</option>
</select>
<p>{{selectedType}} </p>
</body>
Et voila!
See the repl

two level ng-options nested object

EDIT: Using only ng-options as much as possible.
How the data looks like:
vm.category = [
0: {
label: 'Label A',
children: [
{
label: 'Label A.1',
value: 'labelA1',
}
]
}
1: {},
2: {}
]
How it will look like in the HTML. Expected HTML
<select>
<optionGroup> Label A </optionGroup>
<option value="labelA1"> Label A.1 </option>
<option value="labelA2"> Label A.2 </option>
<optionGroup> Label B </optionGroup>
<option value="labelB1"> Label B.1 </option>
</select>
How to achieve this without changing the data structure as much as possible?
I tried ng-options="category.children.label group by category.label for category in vm.categoryTree". But the output is
<select>
<optionGroup> Label A </optionGroup>
<option> undefined </option>
<optionGroup> Label B </optionGroup>
<option> undefined </option>
</select>
Easiest way would be to map the data to a format more easily used by the ng-options "group by" expression
angular.module('so', []).controller('snippet', function() {
this.categoru = [{"label":"Label A","children":[{"label":"Label A.1","value":"labelA1"}]},{"label":"Label B","children":[{"label":"Label B.1","value":"labelB1"}]}];
this.options = this.categoru.reduce((flat, group) => {
Array.prototype.push.apply(flat, group.children.map(child => {
return Object.assign({
parent: group.label
}, child);
}));
return flat;
}, []);
console.log(this.options);
});
<form ng-app="so" ng-controller="snippet as vm">
<select ng-model="vm.selected"
ng-options="opt.label group by opt.parent for opt in vm.options track by opt.value">
</select>
<pre>vm.selected = {{vm.selected | json }}</pre>
</form>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
You can do this,
<select ng-model='theModel' ng-change="display(theModel)">
<optgroup ng-repeat='group in collection' label="{{group.Name}}">
<option ng-repeat='veh in group.Fields' value='{{group.Name}}::{{veh.Name}}'>{{veh.Name}}</option>
</optgroup>
</select>
DEMO

Angular: ng-options add custom directive

I want to create a select tag with 'selected' value. I am doing this with ng-repeat since I cannot add a custom directive to ng-options. This is the code.
<select class="ng-valid ng-dirty" ng-model="selectedCity">
<option ng-repeat="city in allCities" value="{{city.id}}" after-render-cities>{{city.name}}</option>
</select>
This adds an extra option with value =?string:1? which I searched a lot. Since ng-options solves this issue, I however have to add the directive after-render-cities for each option. How can I solve this issue?
Use this
<select class="ng-valid ng-dirty" ng-model="selectedCity" ng-options="city.id as city.name for city in allCities">
</select>
for selection of first value, write following code in your controller
$scope.selectedCity = $scope.allCities[0].id;
use ng-init for solve value =?string:1?
<select class="ng-valid ng-dirty" ng-model="selectedCity" ng-init='selectedCity=allCities[0].id'>
<option ng-repeat="city in allCities" value="{{city.id}}" after-render-cities>{{city.name}}</option>
</select>
another choice you can use ng-selected fiddle
<option ng-repeat="(key,city) in allCities" ng-selected='key==0' value="{{city.id}}" after-render-cities>{{city.name}}</option>
</select>
You can create a custom directive, using select and ng-options.
Snippet:
JS:
template: "<select ng-options='item.id as item.name for item in list' ng-model='data'></select>",
HTML:
<div select-option list="list" ng-model='data'></div>
Refer to the demo here.
Try this code
Java Script
var app = angular.module('myApp', []);
app.controller('SampleController', function ($scope) {
$scope.Cities = [
{ Id: 1, Name: "New York" },
{ Id: 2, Name: "Colombo" },
{ Id: 3, Name: "Real Madrid" },
{ Id: 4, Name: "Bostan" },
{ Id: 5, Name: "Birmingham" }
];
$scope.City= 3;
});
HTML
<select ng-options="C.Id as C.Name for C in Cities" ng-model="City"></select>
Read This Blog, it has everything explained.

Filter multiple items based on array of values

I have a select box that is populated using ng-options.
$scope.items = [
{ID: '2012', Title: 'Chicago'},
{ID: '2013', Title: 'New York'},
{ID: '2014', Title: 'Washington'},
];
<select ng-model="selectedItem" ng-options="item.ID as item.Title for item in items | filter:filterItemNames">
</select>
This returns...
<option value="2012">Chicago</option>
<option value="2013">New York</option>
<option value="2014">Washington</option>
I would like to filter and display multiple items based on their name (i.e. New York and Chicago).
I'm currently trying to use an array with item names to filter, but this is not working.
$scope.filterItemNames = ['New York', 'Chicago'];
In this case you could create custom filter function:
$scope.filterByNames = function(el) {
return !$scope.filterItemNames || $scope.filterItemNames.indexOf(el.Title) > -1;
};
and use it like this in HTML:
<select ng-model="selectedItem"
ng-options="item.ID as item.Title for item in items | filter:filterByNames">
</select>
Demo: http://plnkr.co/edit/lqiMIlEYdrLlS6K0H2g9?p=preview

Reset Model Value On Cascaded DropDown Change

I have two drop downs .One to show departments and other to show sections on change of department .
<div class="row" ng-controller="cascaded as cas">
<div class="form-group">
<label for="select-department" class="control-label col-md-2">Department</label>
<div class="col-md-4">
<select id="select-department" class="form-control" name="department" ng-model="myModel.department"
ng-options="option.name for option in departments track by option.id">
<option value=""></option>
</select>
</div>
<label for="select-department" class="control-label col-md-2">Section</label>
<div class="col-md-4">
<select id="select-section" class="form-control" name="section" ng-model="myModel.section"
ng-options="option.name for option in sections track by option.id">
<option value=""></option>
</select>
{{myModel.section}}
</div>
</div>
</div>
It works fine for me . If I change department all respective section gets updated and if I select any section respective section also gets assigned to the model . But the problem is if second time I change my department value, section drop down gets updated the model value doesn't reset to blank . It still shows the last selected value .
var app = angular.module("mainApp", []);
angular.module("mainApp").controller("cascaded", function ($scope, $filter) {
$scope.departments = [
{
id: 1, name: "Dep A"
}, {
id: 2, name: "Dep B"
}, {
id: 3, name: "Dep C"
}];
var sections = [
{
id: 1, name: "Sec A", parentId: 1
}, {
id: 2, name: "Sec B", parentId: 2
}, {
id: 3, name: "Sec C", parentId: 3
}];
$scope.$watch("myModel.department", function (newVal) {
if (newVal) {
$scope.sections = $filter("filter")(sections, { parentId: newVal.id });
}
});
})
I want to reset my model value when section drop down gets refreshed with new data .
You need to assign the sections value to your mymodel.section value
$scope.myModel.section= $scope.sections;
Because $scope.myModel.section is does not update, when you changing the department,
Your watch event should be
$scope.$watch("myModel.department", function (newVal) {
if (newVal) {
$scope.sections = $filter("filter")(sections, { parentId: newVal.id });
**$scope.myModel.section= $scope.sections;**
}
});
Fiddler Demo
Simply put one method in ng-change of department like:
<select id="select-department" class="form-control" name="department" ng-model="myModel.department"
ng-options="option.name for option in departments track by option.id" ng-change="setBlank()">
<option value=""></option>
</select>
And in the method setBlank() set myModel.section to blank like this:
$scope.setBlank=function(){
$scope.myModel.section='';
}

Resources