@@ -596,12 +596,14 @@ angularWidget('button', inputWidgetSelector);
596
596
* * binding to a value not in list confuses most browsers.
597
597
*
598
598
* @element select
599
- * @param {comprehension_expression } comprehension _expresion_ `for` _item_ `in` _array_.
599
+ * @param {comprehension_expression } comprehension _select_ `as` _label_ `for` _item_ `in` _array_.
600
600
*
601
601
* * _array_: an expression which evaluates to an array of objects to bind.
602
602
* * _item_: local variable which will refer to the item in the _array_ during the iteration
603
- * * _expression_: The result of this expression will be `option` label. The
604
- * `expression` most likely refers to the _item_ variable.
603
+ * * _select_: The result of this expression will be assigned to the scope.
604
+ * The _select_ can be ommited, in which case the _item_ itself will be assigned.
605
+ * * _label_: The result of this expression will be the `option` label. The
606
+ * `expression` most likely reffers to the _item_ variable. (optional)
605
607
*
606
608
* @example
607
609
<doc:example>
@@ -657,7 +659,7 @@ angularWidget('button', inputWidgetSelector);
657
659
</doc:example>
658
660
*/
659
661
660
- var NG_OPTIONS_REGEXP = / ^ ( .* ) \s + f o r \s + ( [ \$ \w ] [ \$ \w \d ] * ) \s + i n \s + ( .* ) $ / ;
662
+ var NG_OPTIONS_REGEXP = / ^ \s * ( ( . * ) \s + a s \s + ) ? ( .* ) \s + f o r \s + ( [ \$ \w ] [ \$ \w \d ] * ) \s + i n \s + ( .* ) $ / ;
661
663
angularWidget ( 'select' , function ( element ) {
662
664
this . descend ( true ) ;
663
665
this . directives ( true ) ;
@@ -669,12 +671,13 @@ angularWidget('select', function(element){
669
671
}
670
672
if ( ! ( match = expression . match ( NG_OPTIONS_REGEXP ) ) ) {
671
673
throw Error (
672
- "Expected ng:options in form of '_expresion_ for _item_ in _collection_' but got '" +
674
+ "Expected ng:options in form of '(_expression_ as)? _expresion_ for _item_ in _collection_' but got '" +
673
675
expression + "'." ) ;
674
676
}
675
- var displayFn = expressionCompile ( match [ 1 ] ) . fnSelf ;
676
- var itemName = match [ 2 ] ;
677
- var collectionFn = expressionCompile ( match [ 3 ] ) . fnSelf ;
677
+ var displayFn = expressionCompile ( match [ 3 ] ) . fnSelf ;
678
+ var itemName = match [ 4 ] ;
679
+ var itemFn = expressionCompile ( match [ 2 ] || itemName ) . fnSelf ;
680
+ var collectionFn = expressionCompile ( match [ 5 ] ) . fnSelf ;
678
681
// we can't just jqLite('<option>') since jqLite is not smart enough
679
682
// to create it in <select> and IE barfs otherwise.
680
683
var option = jqLite ( document . createElement ( 'option' ) ) ;
@@ -696,24 +699,33 @@ angularWidget('select', function(element){
696
699
var collection = collectionFn ( scope ) || [ ] ;
697
700
var value = select . val ( ) ;
698
701
var index , length ;
699
- if ( isMultiselect ) {
700
- value = [ ] ;
701
- for ( index = 0 , length = optionElements . length ; index < length ; index ++ ) {
702
- if ( optionElements [ index ] [ 0 ] . selected ) {
703
- value . push ( collection [ index ] ) ;
702
+ var tempScope = scope . $new ( ) ;
703
+ try {
704
+ if ( isMultiselect ) {
705
+ value = [ ] ;
706
+ for ( index = 0 , length = optionElements . length ; index < length ; index ++ ) {
707
+ if ( optionElements [ index ] [ 0 ] . selected ) {
708
+ tempScope [ itemName ] = collection [ index ] ;
709
+ value . push ( itemFn ( tempScope ) ) ;
710
+ }
704
711
}
705
- }
706
- } else {
707
- if ( value == '?' ) {
708
- value = undefined ;
709
712
} else {
710
- value = ( value == '' ? null : collection [ value ] ) ;
713
+ if ( value == '?' ) {
714
+ value = undefined ;
715
+ } else if ( value == '' ) {
716
+ value = null ;
717
+ } else {
718
+ tempScope [ itemName ] = collection [ value ] ;
719
+ value = itemFn ( tempScope ) ;
720
+ }
711
721
}
722
+ if ( ! isUndefined ( value ) ) model . set ( value ) ;
723
+ scope . $tryEval ( function ( ) {
724
+ scope . $root . $eval ( ) ;
725
+ } ) ;
726
+ } finally {
727
+ tempScope = null ; // TODO(misko): needs to be $destroy
712
728
}
713
- if ( ! isUndefined ( value ) ) model . set ( value ) ;
714
- scope . $tryEval ( function ( ) {
715
- scope . $root . $eval ( ) ;
716
- } ) ;
717
729
} ) ;
718
730
719
731
scope . $onEval ( function ( ) {
@@ -731,17 +743,19 @@ angularWidget('select', function(element){
731
743
var selectValue = '' ;
732
744
var isMulti = isMultiselect ;
733
745
734
- if ( isMulti ) {
735
- selectValue = new HashMap ( ) ;
736
- if ( modelValue && isNumber ( length = modelValue . length ) ) {
737
- for ( index = 0 ; index < length ; index ++ ) {
738
- selectValue . put ( modelValue [ index ] , true ) ;
746
+ try {
747
+ if ( isMulti ) {
748
+ selectValue = new HashMap ( ) ;
749
+ if ( modelValue && isNumber ( length = modelValue . length ) ) {
750
+ for ( index = 0 ; index < length ; index ++ ) {
751
+ selectValue . put ( modelValue [ index ] , true ) ;
752
+ }
739
753
}
740
754
}
741
- }
742
- try {
755
+
743
756
for ( index = 0 , length = collection . length ; index < length ; index ++ ) {
744
- currentItem = optionScope [ itemName ] = collection [ index ] ;
757
+ optionScope [ itemName ] = collection [ index ] ;
758
+ currentItem = itemFn ( optionScope ) ;
745
759
optionText = displayFn ( optionScope ) ;
746
760
if ( optionTexts . length > index ) {
747
761
// reuse
@@ -799,7 +813,7 @@ angularWidget('select', function(element){
799
813
}
800
814
801
815
} finally {
802
- optionScope = null ;
816
+ optionScope = null ; // TODO(misko): needs to be $destroy()
803
817
}
804
818
} ) ;
805
819
} ;
0 commit comments