How to set angularjs ng-repeat on select option - angularjs

At the moment I have a select, but i need to have custom styling for my options, that requires me to change my setup a bit.
At the moment I have
<select ng-model="vm.selectedStation"
ng-options="s.stationName for s in vm.nearbyStations" .....>
</select>
Now I am changing it to
<select ng-model="vm.selectedStation">
<option ng-repeat="s in vm.nearbyStations" value="{{s}}">
{{s.stationName}}
</option>
</select>
It visibly shows the same, but the value is different. I require ng-model to be s. to be the object, but instead it shows as the s.stationName May I ask how do I set the value properly

Use the ng-value directive:
<select ng-model="vm.selectedStation">
̶<̶o̶p̶t̶i̶o̶n̶ ̶n̶g̶-̶r̶e̶p̶e̶a̶t̶=̶"̶s̶ ̶i̶n̶ ̶v̶m̶.̶n̶e̶a̶r̶b̶y̶S̶t̶a̶t̶i̶o̶n̶s̶"̶ ̶v̶a̶l̶u̶e̶=̶"̶{̶{̶s̶}̶}̶"̶>̶
<option ng-repeat="s in vm.nearbyStations" ng-value="s">
{{s.stationName}}
</option>
</select>
Interpolation with curly brackets {{ }} converts the expression to a string. The ng-value directive evaluates the expression and retains its type.
For more information, see
AngularJS ng-value Directive API Reference
AngularJS <select> - Using ngValue to bind the model to an array of objects

Simply use ng-value on each <option> to assign directly to each constituent of vm.nearbyStations.
See an example usage below.
(As an aside, your HTML appears to have an unpaired </option>.)
angular
.module('app', [])
.controller('ctrl', function () {
this.nearbyStations = [
{ stationName: 'a' },
{ stationName: 'b' },
{ stationName: 'c' },
];
});
<script src="https://unpkg.com/angular#1.7.9/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl as vm">
<select ng-model="vm.selectedStation">
<option ng-repeat="s in vm.nearbyStations" ng-value="s">{{ s.stationName }}</option>
</select>
<pre>selectedStation = {{ vm.selectedStation }}</pre>
</div>

Related

ng-selected not working in anagular.js 1.6.6 [duplicate]

I'm trying to set ng-selected in my option element, selected attribute is set to true, but option not selected, When I remove ng-model from select all become working.
The question: How to make option selected, when I'm using the model?
Here is my plunker (selected not working here)
My code:
var app = angular.module("plunker", []);
app.controller("TestController", ["$scope", function($scope) {
$scope.test = 1;
$scope.array = [
{"id": 1, "name": "first"},
{"id": 2, "name": "second"},
{"id": 3, "name": "third"}
];
}]);
My template:
<body ng-controller="TestController">
Selected item must be {{ array[test-1].name }}
<select ng-model="myModel">
<option value="">Choose item..</option>
<option ng-repeat="item in array"
ng-value="item.id"
ng-selected="item.id == test">
{{ item.name }} ({{item.id == test}})
</option>
</select>
</body>
Thanks a lot for any help!
Don't use ngSelected with ngRepeat. Go with ngOptions:
<body ng-controller="TestController">
Selected item must be {{ array[test-1].name }}
<select ng-model="myModel" ng-options="item.id as item.name for item in array">
<option value="">Choose item..</option>
</select>
</body>
Don't use ngSelected with ngModel
From the Docs:
Note: ngSelected does not interact with the <select> and ngModel directives, it only sets the selected attribute on the element. If you are using ngModel on the select, you should not use ngSelected on the options, as ngModel will set the select value and selected options.
— AngularJS ng-selected API Reference
See additional Docs:
Using ng-repeat to generate select options
Using select with ng-options and setting a default value
See Stackoverflow:
Using ng-repeat to generate select options (with Demo)

AngularJS: dynamic custom directive with multiple templates

I'm a Java developer working on a side-project. I've decided to use AngularJS to consume my RESTful webservice.
My JSON structure is following:
[
{
"generatorName": "name1",
"constructorParams": [
{
"type": "Boolean",
"value": "true",
},
{
"type": "Integer",
"value": "2",
}
]
},
{
"generatorName": "name2",
"constructorParams": [
{
"type": "Integer",
"value": "10",
},
{
"type": "Integer",
"value": "10",
}
]
}
]
My goal is to display a specific (for ex. number, text etc.) input field based on the "type" of constructor param and initialise it with a "value". So, if the first generator was selected, I'd like to have something like this:
<html>
<select>
<option selected="selected" value="true">Yes</option>
<option value="false">No</option>
</select>
<input type="number" value="2">
<html>
I've read some threads and decided to use custom directive inside my loop:
<p ng-repeat="param in selectedGenerator.constructorParams">
<constructor-param param="{{param}}"></constructor-param>
</p>
Here's my custom directive:
app.directive("constructorParam", function() {
return {
scope : {
param : '#'
},
templateUrl : '/html_templates/constructor_param_template.html'
};
});
And here's template:
<div ng-switch="{{param.type}}">
<div ng-switch-when="Integer">
<input type="number" ng-attr-name="{{param.type}}" min="0" ng-attr-value="{{param.value}}">
</div>
<div ng-switch-when="Boolean">
<select ng-if="{{param.value}}" ng-attr-name="{{param.type}}">
<option selected="selected" value="true">Yes</option>
<option value="false">No</option>
</select>
<select ng-if="!{{param.value}}" ng-attr-name="{{param.type}}">
<option value="true">Yes</option>
<option selected="selected" value="false">No</option>
</select>
</div>
<div ng-switch-when="String">
<input type="text" ng-attr-name="{{param.type}}" ng-attr-value="{{param.value}}">
</div>
<div ng-switch-when="Double">
<input type="number" ng-attr-name="{{param.type}}" step="0.01" min="0" ng-attr-value="{{param.value}}">
</div>
</div>
These don't work. I can see in the Chrome developer's tools that the directive is run, but it doesn't provide any visible output. My questions are:
1) Do I pass the param object correctly in the custom directive element?
2) I'm not sure about the scope of the directive - I've also tried param : '=param' - it doesn't work either...
3) How should I read the passed object's properties in the template? I've tried: value="{{param.type}}", value={{param.type}} and ng-attr-value="{{param.value}}". None works, but there could be completely different cause to that...
4) Can I use prefix "ng-attr-" for all such element's HTML attributes as name and value?
5) My template's code is exactly what I've pasted - do I need to make it a valid HTML structure with head, body etc.? Do I have to attach <script> with AngularJS? I've done that, but once again, no change.
6) The usage scenario for the whole story is to choose a concrete generator from a drop-down list and display it's constructor params in the specified way. So it has to regenerate HTML with a generator's change. I assume that it's done in the ng-repeat loop but please confirm that.
Thank you very, very much for your input! :)
When you do param : '#' that's a "text binding". That's useful in case you want to tell Angular to not interpret what you're binding to your attribute as a property on the scope but rather as a string directly.
So if you'd do
<my-custom-directive param="hello"></my-custom-directive>
Then in your directive, param would be equal to the the string "hello". While if you bind to param using two-way binding param : '=', then Angular would look for the hello property on the scope instead of taking it as a string literal.
In your case, when you do param="{{param}}" Angular is first unpacking "param" by looking at the scope, into a string literal, then it creates the binding. So even though this might have worked if param was a string, in your case it's an Object, so I don't think it will play well. So I would just do a direct binding to it (see my final code below).
In your directive template, you're also using a few Angular directive which expect a scope binding, so I would try to bind without the curly brackets. See my example code below.
app.directive("constructorParam", function() {
return {
scope: {
param: '='
},
templateUrl: '/html_templates/constructor_param_template.html'
};
});
<!-- container -->
<p ng-repeat="param in selectedGenerator.constructorParams">
<constructor-param param="{{param}}"></constructor-param>
</p>
<!-- TEMPLATE -->
<div ng-switch="param.type">
<div ng-switch-when="Integer">
<input type="number" ng-attr-name="param.type" min="0" ng-attr-value="param.value">
</div>
<div ng-switch-when="Boolean">
<select ng-if="param.value" ng-attr-name="param.type">
<option selected="selected" value="true">Yes</option>
<option value="false">No</option>
</select>
<select ng-if="!param.value" ng-attr-name="param.type">
<option value="true">Yes</option>
<option selected="selected" value="false">No</option>
</select>
</div>
<div ng-switch-when="String">
<input type="text" ng-attr-name="param.type" ng-attr-value="param.value">
</div>
<div ng-switch-when="Double">
<input type="number" ng-attr-name="param.type" step="0.01" min="0" ng-attr-value="param.value">
</div>
</div>
If it still doesn't work, let me know so I can try it in a CodePen.
1) No, you need to remove the curly brackets when passing the values to directive
<constructor-param param="param"></constructor-param>
2,3) in directive use = instead of #. Because # take string value of the parameter and = take the parameter value
scope: {
param: '='
},
4) if you need to bind data then use ng-model instead of ng-attr
5) You don't need to add html or body tag inside constructor_param_template.html template.
6) ng-repeat does that. once the array get updated it will dynamically update the DOM
Demo
First of all, thank you both guys for your help! Unfortunately, I can't mark any of the given answer as correct, because I have to mixed them in order to get what I was looking for.
I wouldn't elaborate here, let me just share with you the final code:
<!-- container -->
<p ng-repeat="param in selectedGenerator.constructorParams">
<constructor-param param="param"></constructor-param>
</p>
<!-- template -->
<div ng-switch="param.type">
<div ng-switch-when="Integer">
<input type="number" name={{param.type}} min="0" value={{param.value}}>
</div>
<div ng-switch-when="Boolean">
<select ng-if="param.value" name={{param.type}}>
<option selected="selected" value="true">Yes</option>
<option value="false">No</option>
</select>
<select ng-if="!param.value" name={{param.type}}>
<option value="true">Yes</option>
<option selected="selected" value="false">No</option>
</select>
</div>
<div ng-switch-when="String">
<input type="text" name={{param.type}} value={{param.value}}>
</div>
<div ng-switch-when="Double">
<input type="number" name={{param.type}} step="0.01" min="0" value={{param.value}}>
</div>
</div>
And here's the directive, you both get it right:
app.directive("constructorParam", function() {
return {
scope: {
param: '='
},
templateUrl: '/html_templates/constructor_param_template.html'
};
});
Once again - thank you very much, I wouldn't solve this problem so quickly without your help!

AngularJS. When select have ng-model attribute, ng-selected not working

I'm trying to set ng-selected in my option element, selected attribute is set to true, but option not selected, When I remove ng-model from select all become working.
The question: How to make option selected, when I'm using the model?
Here is my plunker (selected not working here)
My code:
var app = angular.module("plunker", []);
app.controller("TestController", ["$scope", function($scope) {
$scope.test = 1;
$scope.array = [
{"id": 1, "name": "first"},
{"id": 2, "name": "second"},
{"id": 3, "name": "third"}
];
}]);
My template:
<body ng-controller="TestController">
Selected item must be {{ array[test-1].name }}
<select ng-model="myModel">
<option value="">Choose item..</option>
<option ng-repeat="item in array"
ng-value="item.id"
ng-selected="item.id == test">
{{ item.name }} ({{item.id == test}})
</option>
</select>
</body>
Thanks a lot for any help!
Don't use ngSelected with ngRepeat. Go with ngOptions:
<body ng-controller="TestController">
Selected item must be {{ array[test-1].name }}
<select ng-model="myModel" ng-options="item.id as item.name for item in array">
<option value="">Choose item..</option>
</select>
</body>
Don't use ngSelected with ngModel
From the Docs:
Note: ngSelected does not interact with the <select> and ngModel directives, it only sets the selected attribute on the element. If you are using ngModel on the select, you should not use ngSelected on the options, as ngModel will set the select value and selected options.
— AngularJS ng-selected API Reference
See additional Docs:
Using ng-repeat to generate select options
Using select with ng-options and setting a default value
See Stackoverflow:
Using ng-repeat to generate select options (with Demo)

Angular - ng-change not firing upon select change

Please see this relevant jsFiddle
Within the code I am trying to fire a method when a different option is selected to alert the user. However no event is being trigged
HTML:
<div ng-controller = "MyCtrl">
<p>Term</p>
<select id = "term" ng-change="test()">
<option value="5">5</option>
<option value="10">10</option>
<option value="15">15</option>
</select>
</div>
JS:
var app = angular.module('HelloApp', []);
app.controller('MyCtrl',['$scope','$element', function($scope, $element) {
$scope.test = function () {
alert ("changed!");
}
}]);
You have some issues.
Firstly: <div ng-controller = "MyCtrl"> - you have spaces in between.
Secondly, you're not declaring your app with ng-app. This is because you set your fiddle as jquery, and not Angular. If you had set it as angular you wouldn't need this in the fiddle
This is your fiddle setup
This is an Angular fiddle setup
Thirdly, to use select with AngularJS, you need to have an ng-model on the select tag. In this case i just used bob
<div ng-app="HelloApp"> <!-- declare your angular app. typically would go on body or html -->
<div ng-controller="MyCtrl">
<p>Term</p>
<select ng-model="bob" ng-change="test()">
<option value="5">5</option>
<option value="10">10</option>
<option value="15">15</option>
</select>
</div>
</div>
var app = angular.module('HelloApp', []);
app.controller('MyCtrl',['$scope','$element', function($scope, $element) {
console.log('ctrl working');
$scope.test = function () {
alert ("changed!");
}
}]);
Here is a working fiddle
http://jsfiddle.net/ctbLparv/
Also, if your intention is to just set a property based on the selection, you don't need to use ng-change. You can rely on the two-way binding.
So for example, this fiddle: http://jsfiddle.net/ps8jnyL8/
No select is being called. We also default the selected term to 10 when it first loads.
<div ng-app="HelloApp">
<div ng-controller="MyCtrl">
<p>Term</p>
<select ng-init="selectedTerm = '10'" ng-model="selectedTerm">
<option value="5">5</option>
<option value="10">10</option>
<option value="15">15</option>
</select>
<p>Selected Term: {{selectedTerm}}</p>
</div>
</div>
Here is the working JSFiddle:
https://jsfiddle.net/G8S32/1162/
The main change was adding this line:
ng-model="items"
which doesn't do anything except update the model and cause the event to fire.
Check out the documentation for ng-change:
https://docs.angularjs.org/api/ng/directive/ngChange
Particularly this line:
The ngChange expression is only evaluated when a change in the input
value causes a new value to be committed to the model.

Propagate a Select with angularJS and read the option

I have a problem to read the information selected that is propagate in a select.
<div ng-show="deviceDetail != null" ng-model="example" >
<select >
<option value="NONE">Select</option>
<option ng-repeat="option in deviceDetail" ng-change="selectOption()">{{option}}</option>
</select>
<br/>
The value of the selection is: {{example}}
</div>
this is the HTML code and in the {{example}} I want to see the information that the user selected.
this is the part of the js releted:
$scope.selectOption = function() {
$scope.example = option.productName;
};
How I can fix it?
Thanks a million!
Set your example scope variable directly in <select> instead calling ng-change event and assigning into that function.
You can directly set option.name to example model with the use of ng-options too.
Here You have applied ng-model directive to div tag.
<div> is not input element so apply ng-model to <select> element here.
I would suggest to use ng-options directive for filling the selection list in <select>. ng-repeat is also fine.
Here you are binging ng-change event so in the function if requires then you can pass the object on which event is triggering so you can use that object or perform any operation on that.
Below is the modified template.
<div ng-show="deviceDetail != null">
<select >
<option value="NONE">Select</option>
<option ng-model="example" ng-options="option in deviceDetail" ng-change="selectOption(option)">{{option}}</option>
</select>
<br/>
The value of the selection is: {{example}}
</div>
You should to pass current option:
<select >
<option value="NONE">Select</option>
<option ng-repeat="option in deviceDetail" ng-change="selectOption(option )">{{option}}</option>
</select>
$scope.selectOption = function(option) {
$scope.example = option; // is there property .productName?;
};
Try this:
<div ng-show="deviceDetail != null">
<select >
<option value="NONE">Select</option>
<option ng-model="option" ng-options="option in deviceDetail" ng-change="selectOption(option)">
{{option}}</option>
</select>
<br/>
The value of the selection is: {{example}}
Js:
$scope.selectOption = function(option) {
$scope.example = option;
};
You should use ng-options
The value of the selection is: {{example}}

Resources