HTML:
<select class="form-control" name="paramType" ng-change="setParamC($index)" ng-model="row.ParameterT" ng-options="item.ReferenceValue for item in pagemodel.ParamTList" required></select>
<select class="form-control" name="paramCat" ng-change="validatePCat($index)" ng-model="row.ParameterC" ng-options="item.ReferenceValue for item in pagemodel.ParamCList|filter:{ReferenceParentCode:row.ParameterT.ReferenceCode , ReferenceParentDomain:row.ParameterT.ReferenceDomain}" required></select>
<select class="form-control" name="paramName" ng-change="setParamV($index,0)" ng-model="row.ParameterN" ng-options="item.ReferenceValue for item in pagemodel.ParamNList|filter:{ReferenceParentCode:row.ParameterC.ReferenceCode , ReferenceParentDomain:row.ParameterC.ReferenceDomain}" required></select>
I have a list of data objects that are returned from the server to the front end via an ajax call. Each object contains three properties (ParameterT
, ParameterC
and ParameterN
) that point to other objects.
I also have three lists of objects that are used as the options for my three dropdowns. These three lists are generated by the server and sent to the front end via the same ajax call.
The 3 lists of objects for my dropdown options and the three properties in my main data object are all the same object type.
Here's the data in my first list, ParamTList
, as seen on the front end:
(2) [{…}, {…}]
0:
$$hashKey:"object:503"
ReferenceCode:1
ReferenceDomain:"AGG_TIER_PARAMETER_TYPE"
ReferenceParentCode:null
ReferenceParentDomain:null
ReferenceValue:"Static"
__proto__:Object
1:
$$hashKey:"object:504"
ReferenceCode:2
ReferenceDomain:"AGG_TIER_PARAMETER_TYPE"
ReferenceParentCode:null
ReferenceParentDomain:null
ReferenceValue:"Dynamic"
__proto__:Object
length:2
__proto__:Array(0)
and here's the ParameterT
object:
{ReferenceDomain: "AGG_TIER_PARAMETER_TYPE", ReferenceCode: 2, ReferenceValue: "Dynamic", ReferenceParentDomain: null, ReferenceParentCode: null}
ReferenceCode:2
ReferenceDomain:"AGG_TIER_PARAMETER_TYPE"
ReferenceParentCode:null
ReferenceParentDomain:null
ReferenceValue:"Dynamic"
__proto__:Object
The ParameterT
object that is used as the ng-model
is identical to one object used in the ng-options
list, except for the $$hashKey
property. I'm guessing that is why the binding does not take place. The ParameterT
object is a child object, but it's parent object, the main data object, does have a $$hashKey
property.
Is that correct? If YES, how do I get around this? If NO, what am I doing wrong?
I could do all of this with strings istead of objects, but I'd loose the ability to filter the dropdown selections based on the previous dropdown's setting.
This currently works in production, because the three child properties are set up on the front end, by looping through all of the data objects, and then looping through the three lists of options searching for matches. This performs poorly, that's why I'm trying to move inefficient stuff like that to the server.
Explanation:
You need to use a track by
expression in each of your ng-options
, which is standard practice.
The reason is that if you don't, Angular creates a $$hashkey
property on your repeated data for DOM change tracking. And this $$hashkey
causes the select object to be unmatchable with your http data, which doesn't have the property.
Using track by
, Angular just compares the specified property for equality instead of the whole object (and $$hashkey
is not added anyway.)
Solution:
So, using your ParamT
as an example, and assuming there is a unique property (such as ReferenceCode
) on each object, it would look like:
ng-options="item.ReferenceValue for item in pagemodel.ParamTList track by item.ReferenceCode"
Otherwise you can try:
ng-options="item.ReferenceValue for item in pagemodel.ParamTList track by $index"
which tracks by the position in the collection.
Here is a Working Fiddle;