Skip to content

Commit

Permalink
refactor(core): deprecate allowing full context object to be replaced…
Browse files Browse the repository at this point in the history
… in `EmbeddedViewRef` (#51887)

This partially reverts commit a3e1719
and deprecates behavior added.

The context of an embedded view ref at some point was switched from a
getter to an actual assignable property. This is something we revert
as it introduces additional complexity for our generated code
(in terms of closures capturing the `ctx`), creates technical
limitations for Angular's internals and the usage pattern is rarely
used (and can be addressed via simple assignments, `Object.assign` or
the use of a proxy if replacing the full context object is still
desirable)

DEPRECATED: Swapping out the context object for `EmbeddedViewRef`
is no longer supported. Support for this was introduced with v12.0.0, but
this pattern is rarely used. There is no replacement, but you can use
simple assignments in most cases, or `Object.assign , or alternatively
still replace the full object by using a `Proxy` (see `NgTemplateOutlet`
as an example).

Also adds a warning if the deprecated

PR Close #51887
  • Loading branch information
devversion authored and alxhub committed Oct 4, 2023
1 parent 7be3620 commit 9b9e11f
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 0 deletions.
12 changes: 12 additions & 0 deletions packages/core/src/render3/view_ref.ts
Expand Up @@ -63,7 +63,19 @@ export class ViewRef<T> implements EmbeddedViewRef<T>, InternalViewRef, ChangeDe
return this._lView[CONTEXT] as unknown as T;
}

/**
* @deprecated Replacing the full context object is not supported. Modify the context
* directly, or consider using a `Proxy` if you need to replace the full object.
* // TODO(devversion): Remove this.
*/
set context(value: T) {
if (ngDevMode) {
// Note: We have a warning message here because the `@deprecated` JSDoc will not be picked
// up for assignments on the setter. We want to let users know about the deprecated usage.
console.warn(
'Angular: Replacing the `context` object of an `EmbeddedViewRef` is deprecated.');
}

this._lView[CONTEXT] = value as unknown as {};
}

Expand Down
21 changes: 21 additions & 0 deletions packages/core/test/acceptance/template_ref_spec.ts
Expand Up @@ -317,5 +317,26 @@ describe('TemplateRef', () => {
button.click();
expect(events).toEqual(['Frodo', 'Bilbo']);
});

it('should warn if the context of an embedded view ref is replaced', () => {
TestBed.configureTestingModule({declarations: [App]});
const fixture = TestBed.createComponent(App);
fixture.detectChanges();
const viewRef = fixture.componentInstance.templateRef.createEmbeddedView({name: 'Frodo'});
fixture.componentInstance.containerRef.insert(viewRef);
fixture.detectChanges();

expect(fixture.nativeElement.textContent).toBe('Frodo');
spyOn(console, 'warn');

viewRef.context = {name: 'Bilbo'};
fixture.detectChanges();

expect(console.warn).toHaveBeenCalledTimes(1);
expect(console.warn)
.toHaveBeenCalledWith(jasmine.stringContaining(
'Replacing the `context` object of an `EmbeddedViewRef` is deprecated'));
expect(fixture.nativeElement.textContent).toBe('Bilbo');
});
});
});

0 comments on commit 9b9e11f

Please sign in to comment.