@@ -817,22 +817,180 @@ describe('select', function() {
817817 } ) ;
818818
819819
820+ /**
821+ * This behavior is broken and should probably be cleaned up later as track by and select as
822+ * aren't compatible.
823+ */
820824 describe ( 'selectAs+trackBy expression' , function ( ) {
821825 beforeEach ( function ( ) {
822- scope . arr = [ { id : 10 , label : 'ten' } , { id :'20' , label : 'twenty' } ] ;
823- scope . obj = { '10' : { score : 10 , label : 'ten' } , '20' : { score : 20 , label : 'twenty' } } ;
826+ scope . arr = [ { subItem : { label : 'ten' , id : 10 } } , { subItem : { label : 'twenty' , id : 20 } } ] ;
827+ scope . obj = { '10' : { subItem : { id : 10 , label : 'ten' } } , '20' : { subItem : { id : 20 , label : 'twenty' } } } ;
824828 } ) ;
825829
826830
827- it ( 'should throw a helpful minerr' , function ( ) {
828- expect ( function ( ) {
831+ it ( 'It should use the "value" variable to represent items in the array as well as for the ' +
832+ 'selected values in track by expression (single&array)' , function ( ) {
833+ createSelect ( {
834+ 'ng-model' : 'selected' ,
835+ 'ng-options' : 'item.subItem as item.subItem.label for item in arr track by (item.id || item.subItem.id)'
836+ } ) ;
837+
838+ // First test model -> view
839+
840+ scope . $apply ( function ( ) {
841+ scope . selected = scope . arr [ 0 ] . subItem ;
842+ } ) ;
843+ expect ( element . val ( ) ) . toEqual ( '0' ) ;
844+
845+ scope . $apply ( function ( ) {
846+ scope . selected = scope . arr [ 1 ] . subItem ;
847+ } ) ;
848+ expect ( element . val ( ) ) . toEqual ( '1' ) ;
849+
850+ // Now test view -> model
851+
852+ element . val ( '0' ) ;
853+ browserTrigger ( element , 'change' ) ;
854+ expect ( scope . selected ) . toBe ( scope . arr [ 0 ] . subItem ) ;
855+
856+ // Now reload the array
857+ scope . $apply ( function ( ) {
858+ scope . arr = [ {
859+ subItem : { label : 'new ten' , id : 10 }
860+ } , {
861+ subItem : { label : 'new twenty' , id : 20 }
862+ } ] ;
863+ } ) ;
864+ expect ( element . val ( ) ) . toBe ( '0' ) ;
865+ expect ( scope . selected . id ) . toBe ( 10 ) ;
866+ } ) ;
867+
868+
869+ it ( 'It should use the "value" variable to represent items in the array as well as for the ' +
870+ 'selected values in track by expression (multiple&array)' , function ( ) {
871+ createSelect ( {
872+ 'ng-model' : 'selected' ,
873+ 'multiple' : true ,
874+ 'ng-options' : 'item.subItem as item.subItem.label for item in arr track by (item.id || item.subItem.id)'
875+ } ) ;
876+
877+ // First test model -> view
878+
879+ scope . $apply ( function ( ) {
880+ scope . selected = [ scope . arr [ 0 ] . subItem ] ;
881+ } ) ;
882+ expect ( element . val ( ) ) . toEqual ( [ '0' ] ) ;
883+
884+ scope . $apply ( function ( ) {
885+ scope . selected = [ scope . arr [ 1 ] . subItem ] ;
886+ } ) ;
887+ expect ( element . val ( ) ) . toEqual ( [ '1' ] ) ;
888+
889+ // Now test view -> model
890+
891+ element . find ( 'option' ) [ 0 ] . selected = true ;
892+ element . find ( 'option' ) [ 1 ] . selected = false ;
893+ browserTrigger ( element , 'change' ) ;
894+ expect ( scope . selected ) . toEqual ( [ scope . arr [ 0 ] . subItem ] ) ;
895+
896+ // Now reload the array
897+ scope . $apply ( function ( ) {
898+ scope . arr = [ {
899+ subItem : { label : 'new ten' , id : 10 }
900+ } , {
901+ subItem : { label : 'new twenty' , id : 20 }
902+ } ] ;
903+ } ) ;
904+ expect ( element . val ( ) ) . toEqual ( [ '0' ] ) ;
905+ expect ( scope . selected [ 0 ] . id ) . toEqual ( 10 ) ;
906+ expect ( scope . selected . length ) . toBe ( 1 ) ;
907+ } ) ;
829908
830- createSelect ( {
831- 'ng-model' : 'selected' ,
832- 'ng-options' : 'item.id as item.name for item in values track by item.id'
833- } ) ;
834909
835- } ) . toThrowMinErr ( 'ngOptions' , 'trkslct' , "Comprehension expression cannot contain both selectAs 'item.id' and trackBy 'item.id' expressions." ) ;
910+ it ( 'It should use the "value" variable to represent items in the array as well as for the ' +
911+ 'selected values in track by expression (multiple&object)' , function ( ) {
912+ createSelect ( {
913+ 'ng-model' : 'selected' ,
914+ 'multiple' : true ,
915+ 'ng-options' : 'val.subItem as val.subItem.label for (key, val) in obj track by (val.id || val.subItem.id)'
916+ } ) ;
917+
918+ // First test model -> view
919+
920+ scope . $apply ( function ( ) {
921+ scope . selected = [ scope . obj [ '10' ] . subItem ] ;
922+ } ) ;
923+ expect ( element . val ( ) ) . toEqual ( [ '10' ] ) ;
924+
925+
926+ scope . $apply ( function ( ) {
927+ scope . selected = [ scope . obj [ '10' ] . subItem ] ;
928+ } ) ;
929+ expect ( element . val ( ) ) . toEqual ( [ '10' ] ) ;
930+
931+ // Now test view -> model
932+
933+ element . find ( 'option' ) [ 0 ] . selected = true ;
934+ element . find ( 'option' ) [ 1 ] . selected = false ;
935+ browserTrigger ( element , 'change' ) ;
936+ expect ( scope . selected ) . toEqual ( [ scope . obj [ '10' ] . subItem ] ) ;
937+
938+ // Now reload the object
939+ scope . $apply ( function ( ) {
940+ scope . obj = {
941+ '10' : {
942+ subItem : { label : 'new ten' , id : 10 }
943+ } ,
944+ '20' : {
945+ subItem : { label : 'new twenty' , id : 20 }
946+ }
947+ } ;
948+ } ) ;
949+ expect ( element . val ( ) ) . toEqual ( [ '10' ] ) ;
950+ expect ( scope . selected [ 0 ] . id ) . toBe ( 10 ) ;
951+ expect ( scope . selected . length ) . toBe ( 1 ) ;
952+ } ) ;
953+
954+
955+ it ( 'It should use the "value" variable to represent items in the array as well as for the ' +
956+ 'selected values in track by expression (single&object)' , function ( ) {
957+ createSelect ( {
958+ 'ng-model' : 'selected' ,
959+ 'ng-options' : 'val.subItem as val.subItem.label for (key, val) in obj track by (val.id || val.subItem.id)'
960+ } ) ;
961+
962+ // First test model -> view
963+
964+ scope . $apply ( function ( ) {
965+ scope . selected = scope . obj [ '10' ] . subItem ;
966+ } ) ;
967+ expect ( element . val ( ) ) . toEqual ( '10' ) ;
968+
969+
970+ scope . $apply ( function ( ) {
971+ scope . selected = scope . obj [ '10' ] . subItem ;
972+ } ) ;
973+ expect ( element . val ( ) ) . toEqual ( '10' ) ;
974+
975+ // Now test view -> model
976+
977+ element . find ( 'option' ) [ 0 ] . selected = true ;
978+ browserTrigger ( element , 'change' ) ;
979+ expect ( scope . selected ) . toEqual ( scope . obj [ '10' ] . subItem ) ;
980+
981+ // Now reload the object
982+ scope . $apply ( function ( ) {
983+ scope . obj = {
984+ '10' : {
985+ subItem : { label : 'new ten' , id : 10 }
986+ } ,
987+ '20' : {
988+ subItem : { label : 'new twenty' , id : 20 }
989+ }
990+ } ;
991+ } ) ;
992+ expect ( element . val ( ) ) . toEqual ( '10' ) ;
993+ expect ( scope . selected . id ) . toBe ( 10 ) ;
836994 } ) ;
837995 } ) ;
838996
0 commit comments