AngularJS drop down (ng- options) not binding - string to object (initial selection)
Asked Answered
A

2

6

I am having a problem binding data retrieved from the server to a drop down list. The main issue I think is the fact that the comparison is done on differing object types.

For example: 1. The object returned from the server contains a currency code string. we want this to be bound to an item in the dropdown list

"baseCurrencyCode":"GBP"
  1. The view model returns the list of currencies.. These are returned as a list of currency objects with different properties

    {"currencies":[{"id":1,"rateId":0,"abbreviation":"AFN","description":"Afghani","rate":0.0,"rateDescription":null,"languageCode":"en-gb","isDefault":true,"fullDescription":"AFN - Afghani - ","shortDescription":"AFN - Afghani"}}
    

etc.

Currently, I have got this working by writing a function to go through every property for every item in the list, find the correct property we wish to compare to - do the comparison and then return the initial selection.

When calling my save method I then need to manually bind the currency abbreviation to the object I wish to return to the server.

Surely there must be a better way to do this?

Some of my code for reference..

<select ng-model="selectedCurrency" ng-options="currency.shortDescription for currency in viewModel.currencies"></select>

// Call to my custom method..List, PropertyName, value to compare 
$scope.selectedCurrency = InitialiseDropdown($scope.viewModel.currencies, "abbreviation", $scope.updatedObject.baseCurrencyCode);

// Code executed when saving - to bind the currency to the updated object
$scope.updatedObject.baseCurrencyCode = $scope.selectedCurrency.abbreviation;

Any help is appreciated!

EDIT Sorry if I wasn't clear enough.. To summarise..

The main problem here is binding to the drop down and initial selection.

The object we are updating contains a parameter (string) of the currency abbreviation.

The list we select from is a list of currency objects. As these are two differing object types I have been unable to plug in angulars 2 way binding and have written some code to do this on initial retrieval and when saving.

The cleanest way to fix this would be to return a currency object in our retrieval instead of a simple string of the abbreviation, but this is not an option.

Is there a better way of enabling 2 way binding on different object types ?

Thanks again

Anthracosilicosis answered 24/6, 2014 at 15:10 Comment(0)
F
18

It is not exactly clear what the problem is, but you can save yourself some work by binding the <select> to the currently selected currency object (so you don't have to look it up later).
select + ngOptions allow you to bind to one value while displaying another, with the following syntax:

<select ng-model="selectedCurrency"
        ng-options="currency as currency.shortDescription
                    for currency in viewModel.currencies">
</select>

In the above example, $scope.selectedCurrency will be bound to the whole currency object, but currency.shortDescription will be displayed in the dropdown.


See, also, this short demo.


UPDATE:

In case you don't need to bind to the whole currency object, but just bind updatedObject's baseCurrencyCode property to the abbreviation of the selected (in dropdown) currency, you can do it like this:

<!-- In the VIEW -->
<select ng-model="updatedObject.baseCurrencyCode"
        ng-options="c.abbreviation as c.shortDescription
                    for c in currencies">
</select>

// In the CONTROLLER
$scope.currencies = [...];
$scope.updatedObject = {
    ...
    baseCurrencyCode: <baseCurrencyCodeFromServer>
};

See, also, that short demo.

Follicle answered 24/6, 2014 at 16:33 Comment(6)
Thanks for your contribution.. The method you have described is pretty much what I have done, but it means we need to call that initialise method on every drop down. Isn't there a cleaner way to do this?Anthracosilicosis
There is: clean up your business logic. The server sends an array of objects and a currency-code and expects back a currency object (this is how I understand it at least). This means that there needs to be a look-up at some point (to determine which currency object corresponds to some currency code). Am I right ?Follicle
@user1863426: Take a look at my updated answer. Is that what you want ?Follicle
awesome, this is exactly what I was after. A nice, clean solution.. Thanks!Anthracosilicosis
Thanks. Same issue fixed for me too. :DDouville
A quick note that even if you do it all correct, but use an ng-if in a parent element, binding breaks. I had to switch to ng-show and all was well again.Analphabetic
C
0

I have had the same problem, ng-model and ng-option being from 2 different sources. My ng-model is bound to a value in a json object representing a chosen filename and my ng-option is a list of possible values taken from a csv file.

In the controller I am reading a directory via a Nodejs route, and creating a json array of filenames like this

var allCsvFiles = [{"name":"file1.csv"},{"name","file2.csv},etc..]

The current csv file, i.e. the selected one is stored in another json array

[{"date":"01-06-2017","csvfile":"file1.csv","colour":"red"},{...}, etc].

I was using the following code for the dropdown:

<select type="text" ng-model="file.csvfile" 
ng-options="opt.name for opt in allCsvFiles track by opt.name"></select>

Which caused the current selection to be blank and if I selected an item from the dropdown it put [object],[object] as the current selection. If I stepped through the code I found that it seemed to be selecting {"name","file1.csv"} as the option and couldn't display it, this seemed odd as my ng-options selection looks like it should just return the value of "name" not the array entry. I tried many different ways to make this work but eventually I found that if I made the list of possible selections a plain javascript array:

var allCsvFiles = ["file1.csv","file2.csv", "file3,csv] 

and changed the select to:

<select type="text" ng-model="file.csvfile" ng-options="opt for opt in allCsvFiles"></select>

then the dropdown selection worked as expected.

I may have missed some other obvious solution here, but as the array of json objects is one dimensional anyway it doesn't seem to be an issue.

It looks like the OPs question has been answered, I just thought I'd add this as it solved it for me.

Calx answered 1/6, 2017 at 10:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.