Angular ng-repeat doesn't select bound value - angularjs

I have a key field that should be selected into a SELECT html element. This SELECT is populated with an ng-repeat.
I define two SELECTs, one with ng-repeat, other with ng-options:
<div ng-controller="MyDisplayCtrl">
<select ng-model="context.id1">
<option value="">-</option>
<option ng-repeat="i in lista" value="{{i.id}}">{{i.value}}</option>
</select> Should have "three" selected, but shows - <br/>
<select ng-model="context.id2" ng-options="i.value for i in lista">
</select> Selects "three" automatically <br/>
</div>
And my controller goes like this:
function MyDisplayCtrl($scope) {
var x1 = {id: 1, value: 'one'};
var x2 = {id: 2, value: 'two'};
var x3 = {id: 3, value: 'three'};
window.setTimeout(function() {
$scope.$apply(function() {
$scope.lista = [x1, x2, x3];
});
}, 2000);
$scope.context = {id1: 3, id2: x3};
}
I'd have this list brought to client by an AJAX, so I used a setTimeout() here.
The approach with ng-options works, but I wouldn't have an object, sole its key.
Take a look at this fiddle: http://jsfiddle.net/nCG2H/
Problem: I'm trying to understand why the first SELECT doesn't work, algo because I got it to work depending on timing from AJAX response.

Please use ng-selected="{{i.id}}" instead of value="{{i.id}}"...

Related

How to run multiple successive select buttons in AngularJS

I facing an issue with having multiple selects in angularJS where each one of them is linked to the previous one and the value depended on the previous item selected which looks like could be done easily by angular but I am having a hard time figuring out how do I make the index of one select be passed to another select and at the same time making it unresponsive until some value is selected.
I also created a fiddle for the same for people to fiddle around with it.
Here is the concerned HTML
<div ng-app="myApp">
<div ng-controller="testController">
<select ng-model="carBrand" name="carBrand" required ng-options=" brand for brand in brands"></select>
<select ng-model="carModel" name="carModel" required ng-options="model.name for model in cars[0]"></select>
<!--I want the car brand(cars[0]) to be dynamic here. It should be prefreberably blacked out or uneditable until a Car brand is selected and once that particular brand is selected all the models pertaining to that brand only should be displayed in the ajoining select button-->
</div>
</div>
and an example app.js. Find the complete one at the fiddle
var app = angular.module('myApp', []);
app.controller("testController", function($scope) {
$scope.brands = ['Ford', 'Honda', 'Hyundai', 'Mahindra',
'Maruti Suzuki', 'Nissan', 'Renault', 'Skoda', 'Tata', 'Toyota', 'Volksvagen'
];
$scope.carBrand = $scope.brands[0];
$scope.cars = [];
/*These cars[0] and cars[1] are static declared but could well be called from a REST API endpoint in angular. For simplicity lets say they are already present. */
$scope.cars[0] = $scope.cars[0] = [{
name: "Figo",
capacity: 45
}, {
name: "Ecosport",
capacity: 52
}, {
name: "Fiesta",
capacity: 45
}, {
name: "Endeavour",
capacity: 71
}];
});
How do I solve the issue of getting an index from one select and passing it to the other to make this work and probably an additional perk would be to make it unresponsive in case no brand is selected.
Try ng-change:
<select ng-model="carBrand" name="carBrand" required ng-options=" brand for brand in brands"
ng-change="selectedCar(carBrand)"></select>
This returns the index of the selected brand:
$scope.selectedCar = function(brand) {
$scope.carIndex = $scope.brands.indexOf(brand);
};
Use it with the other dropdown as:
<select ng-model="carModel" name="carModel" required
ng-options="model.name for model in cars[carIndex]"></select>
Working Fiddle
When you select something from the first select, carBrand goes from undefined to the selected brand. You thus want the second select to be disabled if the carBrand is undefined (falsy):
<select ng-disabled="!carBrand" ...>
Then, you need to second select to contain the models associated to the selected brand (which is carBrand). So you need something like
<select ng-options="model.name for model in getModelsOfBrand(carBrand)" ...>
Now just implement this getModelsOfBrand(carBrand) function in the scope. It would be much easier if you had a better object model, like for example:
$scope.brands = [
{
name: 'Ford',
models: [
{
name: 'Figo',
capacity: 45
},
...
]
},
...
];
Then it would be as easy as
<select ng-options="model.name for model in carBrand.models" ...>

AngularJS: refresh ng-options when property source object changes

Full description:
I have list of options with multiple properties (not just key-value pair):
[
{
id: 1,
name: "111",
some: "qqq"
},
{
id: 2,
name: "222",
some: "www"
}
];
And select defined as:
<select name="mySelect" id="mySelect"
ng-options="option.name for option in opts track by option.id"
ng-model="mod1"></select>
Depending on app logic, extra property may change:
{
id: 2,
name: "222",
some: "www1"
}
But actual list in Select doesn't change!
However, if name changes, then entire optionList will be refreshed.
In short you can see demo on JSFiddle OR JSFiddle. I prepared 2 very similar examples:
When button is clicked only extra property updates
When button is clicked - both extra property and key receive new value
Does anybody know solution?
UPDATE
For now I'm solving that issue with update + delay + update solution:
this.click = function(){
$scope.opts = {};
$timeout(function() {
$scope.opts = { /* NEW OBJECT */};
}, 0);
}
OK, so I think I understand what you want, which is to be able to select an option whose nested values may have changed since the list was rendered in the DOM.
Based on that understanding, I believe that the plunker I have created illustrates a solution for you. If you select one of the options, and change the child value in the input field, two-way binding will update the model.
Basically, it is taking the users selection, and on select change, re-assigning the selected object to reference the original option in the options array. This will allow two-way binding to occur. If you view the code, you will see that the input fields are updating the option list itself ($scope.options), where-as the model that is being displayed is $scope.formData.model.
https://plnkr.co/edit/DLhI7t7XBw9EbIezBCjI?p=preview
HTML
<select
name="mySelect"
id="mySelect"
ng-model="formData.model"
ng-change="onChange(formData.model)"
ng-options="option.name for option in options track by option.id"></select>
SELECTED CHILD: {{formData.model.child.name}}
<hr>
<div ng-repeat="option in options">
Child Name for {{ option.name }}: <input ng-model="option.child.name">
</div>
JS
$scope.onChange = function(option) {
angular.forEach($scope.options,function(optionItem){
if (optionItem.id == option.id){
$scope.formData.model = optionItem;
}
})
}
$scope.options = [
{
id: 1,
name: "111",
child: {
id: 11,
name: "111-1"
}
},
{
id: 2,
name: "222",
child: {
id: 22,
name: "222-1"
}
}
];
$scope.formData = {
model: $scope.options[0]
};
Call $apply whenever you want to apply changes made.
$scope.$apply();
This will tell AngularJS to refresh.

Unselected radio button value in Angularjs

I've got an angularjs application that has a form/controller that look essentially like this (boiled down to the pertinent stuff):
angular.module('testApp', [])
.controller('testCtrl', function ($scope) {
$scope.envelopes = [{
id: 1,
name: 'first',
default_spend: '1'
}, {
id: 2,
name: 'second',
default_spend: '0'
}, {
id: 3,
name: 'third',
default_spend: '0'
}, ];
});
And a form that looks roughly like this:
<div ng-app="testApp">
<div ng-controller="testCtrl">
<div ng-repeat="envelope in envelopes">
<div>{{envelope.name}}
<input type="radio" name="default_spend" ng-model="envelope.default_spend" ng-value="1" />
Default Spend: {{envelope.default_spend}}
</div>
</div>
</div>
</div>
You can see this in action with this fiddle.
As you can see, the first envelope is marked as the default_spend envelope and the other two aren't. When I select a different envelope, that envelope also gets marked as the default_spend, but when the radio button is unselected, the model value stays the same ("1"). I understand that I'm dealing with a child scope here due to ng-repeat, but is there a way for me to set an "unselected" value without having to jump through hoops with ngChange?
Not really. When you use ng-value it is what is going to get bound to the ng-model and in your case all of them are having value 1. Also i really did not get the purpose of toggling 1 and 0, however you could just achieve it this way:-
<input type="radio" name="default_spend"
ng-click="selected.envelope = envelope" /> <!--Register an ng-click and set selected one
Default Spend: {{getDefSpend(envelope)}}</div> <!-- Show the text based on selection-->
And in your controller:-
$scope.selected = {envelope: $scope.envelopes[0]};
$scope.getDefSpend = function(envelope){
return $scope.selected.envelope === envelope ? 1 : 0;
}
//$scope.selected.envelope will be your selected option at any point.
Demo
It's because what you have is actually 3 different model values. To work as you want it, you would have ONE model value for all 3. You can either restructure your data, or use ng-change to modify your model manually.

AngularJs dropdown values clearing out model value

My dropdown html looks like this:
<select name="originType" class="form-control"
ng-model="myLocationType"
ng-options="type.Key as type.Value for type in allLocationTypes"
required></select>
This works fine to populate the dropdown. However, when I'm loading the page and populating it with model data, the value that should be selected never is. The dropdown is always on the default (blank) value. I have no problem with dropdowns that are not key/value pairs. For example:
<select name="shipId" class="form-control"
ng-model="WageAgreement.ShipId"
ng-options="shipId for shipId in manufacturers"
required></select>
Populating the model value should work if the model value matches up with the supplied value in the array. See http://jsfiddle.net/5qp54/2/ where 2 is selected when set as the model value for WageAgreement.ShipId
var mod = angular.module("myApp", []);
mod.controller("MainController", function ($scope) {
$scope.allLocationTypes = [
{Key: 1, Value: "Shipyard 1"},
{Key: 2, Value: "Shipyard 2"},
{Key: 3, Value: "Shipyard 3"}
];
$scope.WageAgreement = {};
//Populate value here
$scope.WageAgreement.ShipId = 2;
});
Does your model value match the Key in your object array? I suspect something isn't matching up if it is not selecting the value on the dropdown.
If this doesn't answer your question, can you update your post with a jsfiddle or sample of how you populate manufacturers/allLocations and WageAgreement?

Setting default value in select drop-down using Angularjs

I have an object as below. I have to display this as a drop-down:
var list = [{id:4,name:"abc"},{id:600,name:"def"},{id:200,name:"xyz"}]
In my controller I have a variable that carries a value. This value decided which of the above three items in the array will be selected by default in the drop-down:
$scope.object.setDefault = 600;
When I create a drop-down form item as below:
<select ng-model="object.setDefault" ng-options="r.name for r in list">
I face two problems:
the list is generated as
<option value="0">abc</option>
<option value="1">def</option>
<option value="2">xyz</option>
instead of
<option value="4">abc</option>
<option value="600">def</option>
<option value="200">xyz</option>
No option gets selected by default even though i have ng-model="object.setDefault"
Problem 1:
The generated HTML you're getting is normal. Apparently it's a feature of Angular to be able to use any kind of object as value for a select. Angular does the mapping between the HTML option-value and the value in the ng-model.
Also see Umur's comment in this question: How do I set the value property in AngularJS' ng-options?
Problem 2:
Make sure you're using the following ng-options:
<select ng-model="object.item" ng-options="item.id as item.name for item in list" />
And put this in your controller to select a default value:
object.item = 4
When you use ng-options to populate a select list, it uses the entire object as the selected value, not just the single value you see in the select list. So in your case, you'd need to set
$scope.object.setDefault = {
id:600,
name:"def"
};
or
$scope.object.setDefault = $scope.selectItems[1];
I also recommend just outputting the value of $scope.object.setDefault in your template to see what I'm talking about getting selected.
<pre>{{object.setDefault}}</pre>
In View
<select ng-model="boxmodel"><option ng-repeat="lst in list" value="{{lst.id}}">{{lst.name}}</option></select>
JS:
In side controller
$scope.boxModel = 600;
You can do it with following code(track by),
<select ng-model="modelName" ng-options="data.name for data in list track by data.id" ></select>
This is an old question and you might have got the answer already.
My plnkr explains on my approach to accomplish selecting a default dropdown value. Basically, I have a service which would return the dropdown values [hard coded to test]. I was not able to select the value by default and almost spend a day and finally figured out that I should have set $scope.proofGroupId = "47"; instead of $scope.proofGroupId = 47; in the script.js file. It was my bad and I did not notice that I was setting an integer 47 instead of the string "47". I retained the plnkr as it is just in case if some one would like to see. Hopefully, this would help some one.
<select ng-init="somethingHere = options[0]" ng-model="somethingHere" ng-options="option.name for option in options"></select>
This would get you desired result Dude :) Cheers
Some of the scenarios, object.item would not be loaded or will be undefined.
Use ng-init
<select ng-init="object.item=2" ng-model="object.item"
ng-options="item.id as item.name for item in list"
$scope.item = {
"id": "3",
"name": "ALL",
};
$scope.CategoryLst = [
{ id: '1', name: 'MD' },
{ id: '2', name: 'CRNA' },
{ id: '3', name: 'ALL' }];
<select ng-model="item.id" ng-selected="3" ng-options="i.id as i.name for i in CategoryLst"></select>
we should use name value pair binding values into dropdown.see the
code for more details
function myCtrl($scope) {
$scope.statusTaskList = [
{ name: 'Open', value: '1' },
{ name: 'In Progress', value: '2' },
{ name: 'Complete', value: '3' },
{ name: 'Deleted', value: '4' },
];
$scope.atcStatusTasks = $scope.statusTaskList[0]; // 0 -> Open
}
<select ng-model="atcStatusTasks" ng-options="s.name for s in statusTaskList"></select>
I could help you out with the html:
<option value="">abc</option>
instead of
<option value="4">abc</option>
to set abc as the default value.

Resources