@@ -469,12 +469,6 @@ impl<'a> Parser<'a> {
469469 let source_end = self . peek ( ) . map ( |t| t. index ) . unwrap_or ( self . source . len ( ) as u32 ) ;
470470
471471 let value_source = & self . source [ start as usize ..value_end as usize ] ;
472- let ast_with_source = ASTWithSource {
473- ast : value,
474- source : Some ( Atom :: from_in ( value_source, self . allocator ) ) ,
475- location : Atom :: from_in ( "" , self . allocator ) ,
476- absolute_offset : self . absolute_offset + start,
477- } ;
478472
479473 let key = self . make_template_binding_identifier (
480474 & template_key. source ,
@@ -483,7 +477,20 @@ impl<'a> Parser<'a> {
483477 ) ;
484478 let source_span =
485479 AbsoluteSourceSpan :: new ( template_key. span . start , self . absolute_offset + source_end) ;
486- let expr_binding = ExpressionBinding { source_span, key, value : Some ( ast_with_source) } ;
480+
481+ // Angular expects None for empty values (e.g., `*a=""`)
482+ let expr_value = if value_source. is_empty ( ) {
483+ None
484+ } else {
485+ Some ( ASTWithSource {
486+ ast : value,
487+ source : Some ( Atom :: from_in ( value_source, self . allocator ) ) ,
488+ location : Atom :: from_in ( "" , self . allocator ) ,
489+ absolute_offset : self . absolute_offset + start,
490+ } )
491+ } ;
492+
493+ let expr_binding = ExpressionBinding { source_span, key, value : expr_value } ;
487494 bindings. push ( TemplateBinding :: Expression ( expr_binding) ) ;
488495
489496 // Check for `as` binding after the primary expression (e.g., `*ngIf="cond | async as result"`)
@@ -615,12 +622,9 @@ impl<'a> Parser<'a> {
615622 value_end,
616623 )
617624 } else {
618- // For bare `let item`, value is `$implicit`
625+ // For bare `let item`, Angular expects no value (None)
619626 // Source span includes trailing space after the variable name
620- (
621- Some ( self . make_template_binding_identifier ( "$implicit" , key_start, key_start) ) ,
622- key_end + 1 ,
623- )
627+ ( None , key_end + 1 )
624628 } ;
625629
626630 // Source span starts from 'let' keyword
@@ -3041,12 +3045,11 @@ mod tests {
30413045 _ => panic ! ( "Expected expression binding" ) ,
30423046 }
30433047
3044- // Second binding: let item (variable binding with $implicit )
3048+ // Second binding: let item (variable binding with no value - Angular behavior )
30453049 match & result. bindings [ 1 ] {
30463050 TemplateBinding :: Variable ( var) => {
30473051 assert_eq ! ( var. key. source. as_str( ) , "item" ) ;
3048- assert ! ( var. value. is_some( ) ) ;
3049- assert_eq ! ( var. value. as_ref( ) . unwrap( ) . source. as_str( ) , "$implicit" ) ;
3052+ assert ! ( var. value. is_none( ) ) ;
30503053 }
30513054 _ => panic ! ( "Expected variable binding" ) ,
30523055 }
@@ -3083,10 +3086,11 @@ mod tests {
30833086 _ => panic ! ( "Expected expression binding" ) ,
30843087 }
30853088
3086- // Second: let item ($implicit )
3089+ // Second: let item (no value )
30873090 match & result. bindings [ 1 ] {
30883091 TemplateBinding :: Variable ( var) => {
30893092 assert_eq ! ( var. key. source. as_str( ) , "item" ) ;
3093+ assert ! ( var. value. is_none( ) ) ;
30903094 }
30913095 _ => panic ! ( "Expected variable binding" ) ,
30923096 }
0 commit comments