diff --git a/crates/oxc_angular_compiler/src/pipeline/phases/resolve_names.rs b/crates/oxc_angular_compiler/src/pipeline/phases/resolve_names.rs
index 70a8feb64..3722d461d 100644
--- a/crates/oxc_angular_compiler/src/pipeline/phases/resolve_names.rs
+++ b/crates/oxc_angular_compiler/src/pipeline/phases/resolve_names.rs
@@ -980,6 +980,18 @@ fn resolve_expression<'a>(
);
}
+ // Parenthesized expression - resolve the inner expression
+ IrExpression::Parenthesized(paren) => {
+ resolve_expression(
+ paren.expr.as_mut(),
+ scope,
+ root_xref,
+ saved_view,
+ allocator,
+ expressions,
+ );
+ }
+
// Other expression types don't need resolution
_ => {}
}
diff --git a/crates/oxc_angular_compiler/tests/integration_test.rs b/crates/oxc_angular_compiler/tests/integration_test.rs
index 88d35a968..690b98a35 100644
--- a/crates/oxc_angular_compiler/tests/integration_test.rs
+++ b/crates/oxc_angular_compiler/tests/integration_test.rs
@@ -3650,3 +3650,36 @@ export class TestComponent {
result.code
);
}
+
+#[test]
+fn test_nested_if_listener_ctx_reference() {
+ // Test: nested @if where a listener in the inner @if accesses component properties.
+ // The listener should use nextContext() to get the component context,
+ // not bare `ctx` which would be the inner embedded view's context.
+ let js = compile_template_to_js(
+ r#"@if (show) {
+ @if (active) {
+
+ }
+}"#,
+ "TestComponent",
+ );
+ insta::assert_snapshot!("nested_if_listener_ctx_reference", js);
+}
+
+#[test]
+fn test_nested_if_alias_listener_ctx_reference() {
+ // Test: @if with alias, nested @if where listener accesses both
+ // the alias from the outer @if and a method from the component.
+ // All context references inside the listener should use named variables (ctx_rN),
+ // not bare `ctx`.
+ let js = compile_template_to_js(
+ r#"@if (getItem(); as item) {
+ @if (item.active) {
+
+ }
+}"#,
+ "TestComponent",
+ );
+ insta::assert_snapshot!("nested_if_alias_listener_ctx_reference", js);
+}
diff --git a/crates/oxc_angular_compiler/tests/snapshots/integration_test__nested_if_alias_listener_ctx_reference.snap b/crates/oxc_angular_compiler/tests/snapshots/integration_test__nested_if_alias_listener_ctx_reference.snap
new file mode 100644
index 000000000..908f8c057
--- /dev/null
+++ b/crates/oxc_angular_compiler/tests/snapshots/integration_test__nested_if_alias_listener_ctx_reference.snap
@@ -0,0 +1,38 @@
+---
+source: crates/oxc_angular_compiler/tests/integration_test.rs
+expression: js
+---
+function TestComponent_Conditional_0_Conditional_1_Template(rf,ctx) {
+ if ((rf & 1)) {
+ const _r1 = i0.ɵɵgetCurrentView();
+ i0.ɵɵtext(0,"\n ");
+ i0.ɵɵelementStart(1,"button",0);
+ i0.ɵɵlistener("click",function TestComponent_Conditional_0_Conditional_1_Template_button_click_1_listener() {
+ i0.ɵɵrestoreView(_r1);
+ const item_r2 = i0.ɵɵnextContext();
+ const ctx_r2 = i0.ɵɵnextContext();
+ return i0.ɵɵresetView(ctx_r2.makePrivate(!(item_r2.private && !item_r2.shareWithTeam)));
+ });
+ i0.ɵɵtext(2,"Toggle");
+ i0.ɵɵelementEnd();
+ i0.ɵɵtext(3,"\n ");
+ }
+}
+function TestComponent_Conditional_0_Template(rf,ctx) {
+ if ((rf & 1)) {
+ i0.ɵɵtext(0,"\n ");
+ i0.ɵɵconditionalCreate(1,TestComponent_Conditional_0_Conditional_1_Template,4,
+ 0);
+ }
+ if ((rf & 2)) {
+ i0.ɵɵadvance();
+ i0.ɵɵconditional((ctx.active? 1: -1));
+ }
+}
+function TestComponent_Template(rf,ctx) {
+ if ((rf & 1)) { i0.ɵɵconditionalCreate(0,TestComponent_Conditional_0_Template,2,1); }
+ if ((rf & 2)) {
+ let tmp_0_0;
+ i0.ɵɵconditional(((tmp_0_0 = ctx.getItem())? 0: -1),tmp_0_0);
+ }
+}
diff --git a/crates/oxc_angular_compiler/tests/snapshots/integration_test__nested_if_listener_ctx_reference.snap b/crates/oxc_angular_compiler/tests/snapshots/integration_test__nested_if_listener_ctx_reference.snap
new file mode 100644
index 000000000..3094fbe89
--- /dev/null
+++ b/crates/oxc_angular_compiler/tests/snapshots/integration_test__nested_if_listener_ctx_reference.snap
@@ -0,0 +1,35 @@
+---
+source: crates/oxc_angular_compiler/tests/integration_test.rs
+expression: js
+---
+function TestComponent_Conditional_0_Conditional_1_Template(rf,ctx) {
+ if ((rf & 1)) {
+ const _r1 = i0.ɵɵgetCurrentView();
+ i0.ɵɵtext(0,"\n ");
+ i0.ɵɵelementStart(1,"button",0);
+ i0.ɵɵlistener("click",function TestComponent_Conditional_0_Conditional_1_Template_button_click_1_listener() {
+ i0.ɵɵrestoreView(_r1);
+ const ctx_r1 = i0.ɵɵnextContext(2);
+ return i0.ɵɵresetView(ctx_r1.handleClick());
+ });
+ i0.ɵɵtext(2,"Click");
+ i0.ɵɵelementEnd();
+ i0.ɵɵtext(3,"\n ");
+ }
+}
+function TestComponent_Conditional_0_Template(rf,ctx) {
+ if ((rf & 1)) {
+ i0.ɵɵtext(0,"\n ");
+ i0.ɵɵconditionalCreate(1,TestComponent_Conditional_0_Conditional_1_Template,4,
+ 0);
+ }
+ if ((rf & 2)) {
+ const ctx_r1 = i0.ɵɵnextContext();
+ i0.ɵɵadvance();
+ i0.ɵɵconditional((ctx_r1.active? 1: -1));
+ }
+}
+function TestComponent_Template(rf,ctx) {
+ if ((rf & 1)) { i0.ɵɵconditionalCreate(0,TestComponent_Conditional_0_Template,2,1); }
+ if ((rf & 2)) { i0.ɵɵconditional((ctx.show? 0: -1)); }
+}