NG Select from array there has to be a better way - javascript

I have an array of options, they are static and won't be changing my preference was to simply do a standard select with ng-model attached and then add my options. As far as I can tell this doesn't really work as the model does not bind. Fine. I'll do it the Angular way which is the first time I've seen the Angular way take so much more than any other way.
So I have my array
$scope.options = ['1', '2' 'Etc'];
Then the select:
<select ng-model="stupidAngular" ng-options="options as options for options in options"></select>
Is there a better way to bind the model to a select in angular?

Here is an example:
<select ng-model="selectedGroup" ng-options="group.title for group in groups">
<option value="">-- choose group --</option>
</select>
$scope.groups = [
{
title: "option 1"
},
{
title: "option 2"
},
{
title: "option 3"
}
];
There is also good documentation here.

Related

Vue, building a select list out of array of options but pre-selecting based on async response

I've been trying to test out a way in vue to build a select list with a hardcoded array of options, however, if a certain async response/event comes in with an assignee attached, I am setting that as 'currentAssignee' which is my preselected option.
This kind of works, but it initially looks empty/invisible. If I click the seemingly non-existent select box, the options will show 'Name One', 'Name Two' and 'John Doe' which is the name from the response. But it doesn't actually satisfy the 'selected' option because it is essentially invisible to the user on page load, until it's clicked
Should I be doing something different?
<select class="firstLastNames linkBox" v-model="currentAssignee" #change="changeAssignee()" >
<option :selected="true">{{currentAssigneeFirst}} {{currentAssigneeLast}}</option>
<option v-for="assignee in assigneeOptions" >{{assignee.email}}</option>
</select>
data () {
return {
currentAssignee: '',
assigneeOptions: [
{id: 0, email: "Name one"},
{id: 1, email: "Name two"}
],
},
}
/**further down, I set currentAssignee based on async event**/
this.currentAssignee = triggerEvent[0].assignee;
I put a code sample together here which I think fixes your issue:
https://codepen.io/timfranklin/pen/bGWYggG
Take a look at what is being bound by the v-model. The "value" of a select is not the object itself, it's some value of an object.
<select class="firstLastNames linkBox" v-model="currentAssignee" #change="changeAssignee($event)" >
<option disabled >Choose One</option>
<option v-for="assignee in assigneeOptions" :key="assignee.id" :value="assignee.id">{{assignee.email}}</option>
</select>
The important note here is the :value="assignee.id";

Dynamically change dropdown select defaults depending on existing values in array

I am new to web development and AngularJS and I have been struggling with how to go about this. Sorry for the bad English.
I use an ng-repeat that creates the correct number of dropdowns I need as this needs to be dynamic. The dropdowns have a label like:
Test1: <dropdown here>
Test2: <dropdown here> ...etc.
I have a HTTP request that returns an array. If the array has "Test1 State1" in it, I would like the dropdown for Test1: to change to State1 on default. (continues with all the Tests)
How can I go about this?
HTML
<div ng-repeat="o in options track by $index">
<label for="{{::$o}}" class="col-xs-3">{{o}}:</label>
<select id="{{::$o}}" ng-model="stateModel"
ng-options="state.changeToState for state in states"
ng-change="onStateSelect(stateModel.platformReleaseNotes, o)">
{{state}}
</select>
</div>
$scope.states = [
{
changeToState: 'State1',
notes: 'Hello World'
},
{
changeToState: 'State2',
notes: 'Goodbye'
},
{
changeToState: 'State3',
notes: ' is State3'
},
{
changeToState: 'State4',
notes: ' is State4'
}
];
You cannot share model if you want to have different values for all drop downs.
ng-model should be different for all drop downs and this can be achieved by having array of drop downs as below.
$scope.dropDowns = [{
dropDownName: 'Test1:',
id: 'test1',
selectedOption: ''
}, {
dropDownName: 'Test2:',
id: 'test2',
selectedOption: ''
}];
see the running example in
http://plnkr.co/edit/jsAn1jwGkQfxXK5I9G6J?p=preview

Angularjs ngrepeat and ngoptions, what is "as" "for" keyword?

$scope.items = [{
id: 1,
label: 'aLabel',
subItem: { name: 'aSubItem' }
}, {
id: 2,
label: 'bLabel',
subItem: { name: 'bSubItem' }
}];
based on above list, below is what I normally use:
<select ng-options="item in items" ng-model="selected"></select>
Very straightforward, as in, I can access the value by using item.xxx
But what is the syntax below:
<select ng-options="item as item.label for item in items" ng-model="selected"></select>
I am totally blur, the as and for keyword is for what purpose? I could not really find the doc that explain this, please help.
PS:
Original syntax is <select ng-options="item as item.label for item in items track by item.id" ng-model="selected"></select> but I removed track by, because I understand that by reading from the doc.
Here's the options list which <select> should refer to populate options.
$scope.items = [{
id: 1,
label: 'aLabel',
subItem: { name: 'aSubItem' }
}, {
id: 2,
label: 'bLabel',
subItem: { name: 'bSubItem' }
}];
When you write ng-options="item as item.label for item in items", you are iterating over items, where each item is assigned to item by using item in items.
So for 1st iteration, item's value will be:
{
id: 1,
label: 'aLabel',
subItem: { name: 'aSubItem' }
}
Note that item is an object in this case.
<option> doesn't care about how you're fetching data for it, it only cares about what it needs to show and assign what value when it's selected. So, we tell ng-options using for that take item as input and generate corresponding <option> elements.
Now in select option, suppose you want your input to be id. But hey, who knows what is the meaning of your id, to be human readable you would want to display some meaning message to identify it, which is label in this case.
So, instead of using the entire object, you will use only it's id while using label to identify it(text displayed in dropdown).
Now your code changes to:
ng-options="item.id as item.label for item in items"
So the final generated HTML becomes something like this:
<select>
<option value="1">aLabel</option>
<option value="2">bLabel</option>
</select>
<select ng-options="item as item.label for item in items" ng-model="selected"></select> is almost similar in functionality to
<select ng-options="item in items" ng-model="selected"></select>
But here the first one is giving more clarity to the framework
in item as item.label for item in items,
'as': item as item.label is telling that in the options of select tag show item.label, but item.label representing whole object item. Which means that even though the option is showing only item.label in DOM, the other properties (id, subtype etc) are also accessible using the ng-model (or selected option)
'for': Here for item in items comes because when mentioning item as item.label the DOM has no idea what is this item. So this is clearly saying that the item in the statement of item.label is an object in the object array $scope.items (or simply itmes in term of DOM)
You can find the official documentation in the ngOptions directive https://docs.angularjs.org/api/ng/directive/ngOptions

Selecting default option value with knockout

I'm trying to select a default select option based on one of the property with which I'm populating my select option.
This code is copied straight from #rneimeyer's fiddle. I did tweak it to do what I wanted to do.
So, I have choices as my observableArray.
var choices = [
{ id: 1, name: "one", choice: false },
{ id: 2, name: "two", choice: true },
{ id: 3, name: "three", choice: false }
];
function ViewModel(choices, choice) {
this.choices = ko.observableArray(choices);
};
The difference between rneimeyer's fiddle and mine is that I have choice property added on my object inside the observableArray instead of having a separate observable for the option that we want to be default.
Here's the fiddle on my attempt.
Now I'm checking in my select element tag whether the choice attribute is true or not. And if it is then I want to set the name to the value attribute so that it becomes the default.
<select data-bind="options: choices, optionsText: 'name', value: choice"></select>
I've tested this with simple data model in my fiddle here as well which is working just as I wanted.
I guess what my real query is how to check choice property in the data-bind. I see that optionText is being able to access the name property just fine. Not sure why it isn't same for choice property in value attribute.
I might have misdirected to some people. Also, I apologize for not mentioning the version that I'm using. I'm currently using Knockout 3.0.0 (you'll see why this is important later)
Also, just to note that I'm not saying #XGreen's method is wrong but that wasn't exactly what I was looking for and this might be due to my poor explanation.
Let me first try to clarify what I was trying to accomplish.
First of all, I will be having an array of object with the information for the options.
[
{ id: 1, name: "one", choice: false },
{ id: 2, name: "two", choice: true },
{ id: 3, name: "three", choice: false }
]
Now, what I wanted to do was to data-bind select option to that array with choice true being the default selected one.
I'm not intending to create any extra observable except the array itself which is going to be an observableArray.
After much research I finally found optionsAfterRender attribute for options property in Knockout's Docs.
<select data-bind="options: choices,
optionsValue: 'name',
optionsAfterRender: $root.selectDefault">
</select>
So what optionsAfterRender really does is, on each array element it calls custom function which I've set to check if the choice is true or not and make the value of select option that which has the true.
Do note that ko.applyBindingsToNode does not work on version 2.2.0 which I had in my original fiddle.
function ViewModel(choices) {
this.choices = ko.observableArray(choices);
this.selectDefault = function(option,item){
if(item.choice){
ko.applyBindingsToNode(option.parentElement, {value: item.name}, item);
}
};
};
ko.applyBindings(new ViewModel(choices));
And here's the fiddle for it.
Ok If I understand you want to set the true choice as your default selected value.
First you need to involve id in your drop down so it becomes the value of the options as we will filter our collection based on that unique id
<select data-bind="options: choices, optionsText: 'name', optionsValue: 'id', value: selectedChoice"></select>
As you see now you need to create a new observable called selectedChoice and we are going to populate that observable with the choice that is true using a computed.
var choices = [
{ id: 1, name: "one", choice: false },
{ id: 2, name: "two", choice: true },
{ id: 3, name: "three", choice: false }
];
function ViewModel(choices) {
var self = this;
self.choices = ko.observableArray(choices);
self.trueChoice = ko.computed(function(){
return ko.utils.arrayFirst(self.choices(), function(item){
return item.choice === true;
});
});
self.selectedChoice = ko.observable(self.trueChoice().id);
};
ko.applyBindings(new ViewModel(choices));
the new computed property trueChoice uses the arrayFirst method in order to return the first item in your choices collection that has its choice property set to true.
Now that we have our true choice all we have to do is to set the selected value of the dropdown aka selectedChoice to be the id of that true choice so the item becomes selected in the drop down.
Here is also a working fiddle for this
Added a Gist that disabled the first option in a select drop down list, and work nicely with KO's optionsCaption binding, using a optionsDisableDefault binding:
https://gist.github.com/garrypas/d2e72a54162787aca345e9ce35713f1f
HTML:
<select data-bind="value: MyValueField,
options:OptionsList,
optionsText: 'name',
optionsValue: 'value',
optionsCaption: 'Select an option',
optionsDisableDefault: true">
</select>
You could create a computed that holds the selected items
self.selected_options = ko.computed({
read: function() {
return self.choices.filter(function(item){ return item.choice });
},
write: function(value) {
self.choices.forEach(function(item) { item.choice = value.indexOf(item) > 0;});
}
})
Then bind to that as the selected options.

How do I set default value of select box in angularjs

I have a form that is used to edit a object and I can't select a value in the select box.
I have a json array which represents the to be edited and look like this:
$scope.item = [{
"objectID": "76",
"versionID": "0",
"versionName": "CURRENT",
"objectName": "xyz",
}]
now I am at the same time populating a select box from another json array that looks like this:
$scope.versions = [
{
"id": "0",
"description": "CURRENT",
"name": "CURRENT"
},
{
"id": "114",
"description": "description of Version 2",
"name": "version2"
},
{
"id": "126",
"description": "description of Version 3",
"name": "version3"
},
{
"id": "149",
"description": "description of Version 4",
"name": "version4"
}]
inside my webpage I am creating the select box as follows:
Version: <select ng-model="item.versionID"
ng-selected="item.versionID"
ng-options="version.name for version in versions"
required>
the select box is populating for me but it should be selecting the the value that matches the version in item. I have tried both versionID and versionName, I have even tried setting ng-selected="0" and that doesn't even work.
I have looked here on SO, the Angularjs site and googled and gone through countless tutorials but still having issues with this. I just can't seem to see what the issue is so any Help greatly appreciated
JSFiddle Added
Added a JsFiddle here
You can simple use ng-init like this
<select ng-init="somethingHere = options[0]" ng-model="somethingHere" ng-options="option.name for option in options"></select>
You can just append
track by version.id
to your ng-options.
It doesn't set the default value because your model isn't bound to the id or name properties, it's bound to each version object. Try setting the versionID to one of the objects and it should work, ie $scope.item.versionID = $scope.versions[2];
If you want to set by the id property then you need to add the select as syntax:
ng-options="version.id as version.name for version in versions"
http://jsfiddle.net/LrhAQ/1/
After searching and trying multiple non working options to get my select default option working. I find a clean solution at:
http://www.undefinednull.com/2014/08/11/a-brief-walk-through-of-the-ng-options-in-angularjs/
<select class="ajg-stereo-fader-input-name ajg-select-left" ng-options="option.name for option in selectOptions" ng-model="inputLeft"></select>
<select class="ajg-stereo-fader-input-name ajg-select-right" ng-options="option.name for option in selectOptions" ng-model="inputRight"></select>
scope.inputLeft = scope.selectOptions[0];
scope.inputRight = scope.selectOptions[1];
As per the docs select, the following piece of code worked for me.
<div ng-controller="ExampleController">
<form name="myForm">
<label for="mySelect">Make a choice:</label>
<select name="mySelect" id="mySelect"
ng-options="option.name for option in data.availableOptions track by option.id"
ng-model="data.selectedOption"></select>
</form>
<hr>
<tt>option = {{data.selectedOption}}</tt><br/>
</div>
<select ng-model="selectedCar" ><option ng-repeat="car in cars " value="{{car.model}}">{{car.model}}</option></select>
<script>var app = angular.module('myApp', []);app.controller('myCtrl', function($scope) { $scope.cars = [{model : "Ford Mustang", color : "red"}, {model : "Fiat 500", color : "white"},{model : "Volvo XC90", color : "black"}];
$scope.selectedCar=$scope.cars[0].model ;});
if you don't even want to initialize ng-model to a static value and each value is DB driven, it can be done in the following way. Angular compares the evaluated value and populates the drop down.
Here below modelData.unitId is retrieved from DB and is compared to the list of unit id which is a separate list from db-
<select id="uomList" ng-init="modelData.unitId"
ng-model="modelData.unitId" ng-options="unitOfMeasurement.id as unitOfMeasurement.unitName for unitOfMeasurement in unitOfMeasurements">

Categories