KnockoutJS: Selected option when using foreach - javascript

I am using KnockoutJS to render a Select control but to do so I am using the ko foreach binding rather than the options binding. The Select area currently looks like this:
<select class="form-control" data-bind="value: selectedItem">
<option>-- Select an Item --</option>
<!-- ko foreach: groups -->
<optgroup data-bind="attr: { label: name }, foreach: items">
<option data-bind="text: name, option: $data"></option>
</optgroup>
<!-- /ko -->
</select>
So why am I not using the options binding? The reason is because I need to send back 2 values to the server rather than just one, where just using the value field would not be enough. So underneath this control I have 2 hidden fields that looks like this:
<input type="hidden" name="Model.SelectItemId" data-bind="value: selectedItem().itemId" />
<input type="hidden" name="Model.SelectedItemTypeId" data-bind="value: selectedItem().itemTypeId" />
This all works fine, renders as expected and passes the correct values to the server. However now I want to ability to set a default value on the select field based on a value passed into the page, and I can't seem to get this to work.
I've tried setting a value in the observable on the model like this:
function ViewModel() {
...
this.groups = ko.observable(getGroups());
// Set selected to a hardcoded item just for now to test
this.selectedItem = ko.observable(this.groups()[0].items[1]);
}
This unfortunately doesn't make a difference since when the page renders it still shows the default -- Select an Item -- option in the control and the 2 hidden fields still have a value of 0. Note however that when I remove the select control from the view and render the page the 2 hidden fields do have the default item values set so it's as if the select control is resetting the selected item back to the first default item.
I've also tried setting an afterRender on the select control and the ko foreach so that I can set the selected item that way after knockout has finished rendering, but I run into the same issue and nothing has changed.
Any help on this issue would be much appreciated. Please let me know if you want me to go into more detail on a certain area to help resolve the issue.

I have a few comments:
ViewModel.groups should be an observableArray.
Try adding a non-observable defaultItem parameter to your ViewModel:
function ViewModel() {
this.groups = ko.observableArray(getGroups());
this.selectedItem = ko.observable();
this.defaultItem = this.groups()[0].items[1];
}
An 'option' (singular) binding doesn't exist. Update your binding on the options element, changing 'option' to 'value', and add this 'attr' component:
<option data-bind="text: name,
value: $data,
attr: { selected: ($data === $parents[1].defaultItem ? 'selected' : null) }">
</option>

Related

Add item to a dropdown and a text field in angular.js

I've been dealing with this problem for a long time. I currently have a function called "add ()" that allows me to add items to an array that feeds a dropdown and text fields. Every time I add a new item to the array, I add it empty:
$scope.aAnimals.push({"animal": ""})
This causes a problem with the dropdown, since the value of "animal" is equal to ""
  
<Option style="display: none" value=""> Select an animal </option>
Then the item is not added. Both "animal" and the dropdown value of the first option are empty strings. If you add a value for "animal", other than "" here it would work and would be added to the dropdown.
What I can do? I want the generated text fields to be empty, and the dropdown adds the item.
<select class="form-control" ng-model='obj.animal' id='animal' name='animal'
ng-options="opt as opt.animal for opt in aAnimals track by opt.animal">
<option style="display:none" value="">Select an animal</option>
</select>
<div ng-repeat='item in aAnimals'>
<input type='text' value={{item.animal}} class='animal' />
</div>
$scope.obj = {}
$scope.aAnimals=[{ "animal": "cat"},{ "animal": "dog"}]
$scope.add=function(){
$scope.aAnimals.push({ "animal": ""})
}
http://plnkr.co/edit/PRDp3a1bDJKtRmGR9GMY?p=preview
Let me verify what you need.
When the user click on the Add button, a new empty text box will be create in the page and a new empty option will be create in the drop down. When the user change the value in the text box, the drop down option will change.
In this case your need to modify the code like this.
<select class="form-control" ng-model='obj.animal' id='animal' name='animal'
ng-options="opt as opt.animal for opt in aAnimals">
<option style="display:none" value="">Select an animal</option>
</select>
<div ng-repeat='item in aAnimals'>
<input type='text' class='animal' ng-model='item.animal' />
</div>
I removed track by opt.animal like Pankas said, and added ng-model='item.animal', also don't need value={{item.animal}} since we use AngularJS 2-way binding.
Your code is working perfectly, just remove display none in option
<option value="">Select an animal</option>
I seen you are using jquery in Save functionality. We have jqlite in built in angular. Please check below code for save.
var length = $scope.aAnimals.length;
$scope.aAnimals[length-1].animal =
angular.element(document).find('.animal').eq(length-1).val();

AngularJS Setting the active option of a select element to the value of a different angular object

I have researched this issue and have found solutions using php but not angular.
One of the requirements for saving the data on my page requires that two seperate angular objects have the same Id. Below is the code:
HTML
<select class="form-control" ng-model="temp" ng-options="type as type.Name for type in Displays">
</select>
AngularJS
$scope.Prop = Prop.data;
$scope.Displays = Displays.data;
What I would like to do is when the angular object is selected in the dropdown I want to assign the Displays.Id to equal the Prop.TestTemplateId.
How would I do this? Thanks in advance
I understand that the value you select in your dropdownbox is bound to '$scope.temp'. Therefore, when initializing the controller, you could watch that variable and update '$scope.testProp.TestTemplateId' with the new value as follows:
$scope.$watch('temp', function(newType, oldType) {
$scope.Prop.TestTemplateId = newType.Id;
});
This will make ..
angular watch '$scope.temp'
whenever that value changes (e.g. selected via dropdown), the given function will be called with the new value (and the old value)
within that function you can update '$scope.testProp.TestTemplateId'
You could utilize ng-change directive on the <select> the would trigger a function that sets/updates the value of the property. You can retrieve the value of selected item from the "temp" property you defined in the ngModel directive.
HTML:
<select class="form-control" ng-model="temp" ng-options="type as type.Name for type in Displays" ng-change="update()">
</select>
JS:
$scope.update = function() {
// can retrieve value of selected item of "temp" ngModel property
$scope.Prop.TestTemplateId = $scope.temp.id;
};
The simple way would be ng-change
View:
<select class="form-control"
ng-options="type as type.Name for type in Displays"
ng-change="setId(type.Id)">
</select>
Ctrl:
$scope.setId = function(Id){
$scope.Prop.TestTemplateId = Id;
};
Or you can just set the value directly in the view
<select class="form-control"
ng-options="type as type.Name for type in Displays"
ng-change="Prop.TestTemplateId = type.Id;">
</select>

set default selected value in <option> in angularjs

I want to display by default a value from a json which is something like
[{"city":"SURAT"},{"city":"BARODA"},{"city":"AHMEDABAD"},{"city":"MUMBAI"}]
this is came from server. I am store this value in $scope.user_all_city and there is one city is provided to user which is i am stored in this
$scope.user_city = "surat";
now my select tag is something like this
<select ng-model="model.user_all_city" ng-options="rm.city for rm in user_all_city" ng-init="model.user_all_city=user_city">
it is display first value as a blank. it is return to me default city when i am print {{mode.user_all_city}} but it is didn't display as selected option in it.
please help me over here and how to call a function in when i am change the value.
Try using ng-repeat instead of ng-options basically the ng-options is not that much descriptive in angularjs.
<select ng-model="cityName" required>
<option>Select city</option>
<option ng-selected="cityName==city" value="{{city}}" ng-repeat="city in cityList"></option>
</select>
here the required attribute will enusre that select city is highlighted in case of null value. and ng-selected will check if that expression is true and the only that object is selected.The value inseide the model=cityName play the role of selected value here.

Angular binding not updating properly

What I'm trying to do is rather simple, I would think. I am trying to update a few values linked to an object in my controller based on what is selected from a select box. Hopefully you guys can shed some light on what I'm doing wrong.
My controller instantiates the object (which I'm not sure if I actually need to do):
$scope.newInvoice = {}
Then my html provides a dropdown box with a list of invoices that can be selected and the table should auto updated with the values from the selected invoices, but it does not:
<tr>
<td>
<select ng-model="newInvoice">
<option ng-repeat="name in names" value="{{name}}">{{name.Name}}</option>
</select>
</td>
<td>TBD</td>
<td>{{newInvoice.PoNumber}}</td>
<td>{{newInvoice.Price | currency}}</td>
<td>
<input type="number" ng-model="newInvoice.Quantity"/>
</td>
<td>{{newInvoice.Price * newInvoice.Quantity | currency}}</td>
</tr>
Essentially, the table does not fill in with the values provided from the select box. But if I print newInvoice to the screen with <pre>{{newInvoice}}</pre> I can see that newInvoice does in fact have all of the values, all properly named. So it would seem that the select box is binding well with the model. Any ideas?
Use ng-options instead of rendering options using ng-repeat, because when you use ng-repeat to render options, it does fill value attribute with object but that has been stringified. Where as if you use ng-options behind the scene it does assign actual object value to mentioned ng-model variable.
Markup
<select ng-model="newInvoice" ng-options="name.Name for name in names"></select>

How to get the value from a dropdown in angular?

I am trying to get the value that user selects from my dropdown.
I have
<select ng-model="item" ng-change="vm.getItem()">
<option value="discount">Discount</option>
<option value="{{::item}}"
ng-repeat="item in vm.items"
ng-bind="item.name"
</option>
</select>
In my controller
vm.getItem = function() {
vm.pickedItem = //not sure what to do...
//I need to get the select item
//please noted that the discount is a stand alone option value. I need to get
//that too if user selects it.
}
I don't want to use ng-option as it has some restriction that I don't need. I was hoping to get it from just regular <option> tag.
Thanks for the help!
I would recommend you to use ngOptions
Set up select element with proper model i.e. vm.pickedItem which can be directly used in controller, or you can pass it to your method like vm.getItem(vm.pickedItem)
<select ng-model="vm.pickedItem" ng-change="vm.getItem(vm.pickedItem )">
<option value="discount">Discount</option>
<option value="{{::item}}"
ng-repeat="item in vm.items"
ng-bind="item.name">
</option>
</select>
vm.getItem = function() {
var selectedItem = vm.item;
////vm.item is the bound variable to the dropdown's ng-model directive
}
If you really wanted to use the ng-change event in this scenario, then on your "getItem" event, you should access the model bound to the dropdown's ng-model called "item" as seen in your html markup.
you forgetting to alis your controller in your select
<select ng-model="vm.item" ng-change="vm.getItem()">
In controller
vm.getItem = function() {
console.log(vm.item)
or
console.log(this.item)
}

Categories