Skip to content

Commit efa8f5f

Browse files
ashley-hunterclaude
andcommitted
fix: handle animation trigger bindings in directive host property
The directive's parse_host_property_name was missing the @ animation check, causing host: { '[@slidein]': 'state' } on directives to emit ɵɵdomProperty instead of ɵɵsyntheticHostProperty. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent e5f1e8f commit efa8f5f

File tree

3 files changed

+61
-0
lines changed

3 files changed

+61
-0
lines changed

crates/oxc_angular_compiler/src/directive/compiler.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -743,6 +743,9 @@ fn parse_host_property_name(name: &str) -> (BindingType, &str, Option<&str>) {
743743
}
744744
} else if let Some(rest) = name.strip_prefix("attr.") {
745745
(BindingType::Attribute, rest, None)
746+
} else if name.starts_with('@') {
747+
// Animation binding like @triggerName
748+
(BindingType::Animation, name, None)
746749
} else {
747750
(BindingType::Property, name, None)
748751
}

crates/oxc_angular_compiler/tests/integration_test.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2341,6 +2341,42 @@ export class SlideComponent {
23412341
);
23422342
}
23432343

2344+
#[test]
2345+
fn test_directive_host_animation_trigger_binding() {
2346+
// Directive with animation trigger in host property should emit ɵɵsyntheticHostProperty
2347+
let source = r#"
2348+
import { Directive } from '@angular/core';
2349+
import { trigger, transition, style, animate } from '@angular/animations';
2350+
2351+
@Directive({
2352+
selector: '[appSlide]',
2353+
host: {
2354+
'[@slideIn]': 'animationState',
2355+
}
2356+
})
2357+
export class SlideDirective {
2358+
animationState = 'active';
2359+
}
2360+
"#;
2361+
let allocator = Allocator::default();
2362+
let result = transform_angular_file(&allocator, "slide.directive.ts", source, None, None);
2363+
assert!(!result.has_errors(), "Should not have errors: {:?}", result.diagnostics);
2364+
2365+
let code = &result.code;
2366+
2367+
// Should have ɵɵsyntheticHostProperty in the hostBindings update block
2368+
assert!(
2369+
code.contains(r#"syntheticHostProperty("@slideIn""#),
2370+
"Expected syntheticHostProperty with @slideIn name for directive.\nGot:\n{code}"
2371+
);
2372+
2373+
// Should NOT use regular hostProperty for animation triggers
2374+
assert!(
2375+
!code.contains(r#"hostProperty("@slideIn""#),
2376+
"Should not use hostProperty for animation triggers.\nGot:\n{code}"
2377+
);
2378+
}
2379+
23442380
/// Test that multiple components with host bindings in the same file have unique constant names.
23452381
///
23462382
/// This test simulates the real-world scenario from Material Angular's fab.ts where

napi/angular-compiler/e2e/compare/fixtures/animations/animation-host.fixture.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,28 @@ import { Component } from '@angular/core';
135135
})
136136
export class AnimationParamsComponent {
137137
state = 'initial';
138+
}
139+
`.trim(),
140+
expectedFeatures: ['ɵɵsyntheticHostProperty'],
141+
},
142+
{
143+
name: 'animation-directive-host-property-trigger',
144+
category: 'animations',
145+
description: 'Animation trigger binding in directive host property',
146+
className: 'SlideDirective',
147+
type: 'full-transform',
148+
sourceCode: `
149+
import { Directive } from '@angular/core';
150+
import { trigger, transition, style, animate } from '@angular/animations';
151+
152+
@Directive({
153+
selector: '[appSlide]',
154+
host: {
155+
'[@slideIn]': 'animationState',
156+
}
157+
})
158+
export class SlideDirective {
159+
animationState = 'active';
138160
}
139161
`.trim(),
140162
expectedFeatures: ['ɵɵsyntheticHostProperty'],

0 commit comments

Comments
 (0)