fix(ivy): support ICUs with pipes (#34198)
Prior to this commit, i18n runtime code failed with the exception saying that no provider was found for ChangeDetectorRef for a pipe used in ICU. The problem happened because the underlying `createViewRef` function was not taking into account IcuContainer as a valid TNodeType. This commit updates the `createViewRef` function to return corresponding ViewRef for TNodeType.IcuContainer. PR Close #34198
This commit is contained in:
parent
e315215983
commit
60b13d9948
|
@ -408,7 +408,7 @@ function createViewRef(tNode: TNode, lView: LView, isPipe: boolean): ViewEngine_
|
||||||
return new ViewRef(componentView, componentView);
|
return new ViewRef(componentView, componentView);
|
||||||
} else if (
|
} else if (
|
||||||
tNode.type === TNodeType.Element || tNode.type === TNodeType.Container ||
|
tNode.type === TNodeType.Element || tNode.type === TNodeType.Container ||
|
||||||
tNode.type === TNodeType.ElementContainer) {
|
tNode.type === TNodeType.ElementContainer || tNode.type === TNodeType.IcuContainer) {
|
||||||
// The LView represents the location where the injection is requested from.
|
// The LView represents the location where the injection is requested from.
|
||||||
// We need to locate the containing LView (in case where the `lView` is an embedded view)
|
// We need to locate the containing LView (in case where the `lView` is an embedded view)
|
||||||
const hostComponentView = lView[DECLARATION_COMPONENT_VIEW]; // look up
|
const hostComponentView = lView[DECLARATION_COMPONENT_VIEW]; // look up
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
// Make the `$localize()` global function available to the compiled templates, and the direct calls
|
// Make the `$localize()` global function available to the compiled templates, and the direct calls
|
||||||
// below. This would normally be done inside the application `polyfills.ts` file.
|
// below. This would normally be done inside the application `polyfills.ts` file.
|
||||||
import '@angular/localize/init';
|
import '@angular/localize/init';
|
||||||
import {registerLocaleData} from '@angular/common';
|
import {CommonModule, registerLocaleData} from '@angular/common';
|
||||||
import localeRo from '@angular/common/locales/ro';
|
import localeRo from '@angular/common/locales/ro';
|
||||||
import {Component, ContentChild, ContentChildren, Directive, HostBinding, Input, LOCALE_ID, QueryList, TemplateRef, Type, ViewChild, ViewContainerRef, Pipe, PipeTransform, NO_ERRORS_SCHEMA} from '@angular/core';
|
import {Component, ContentChild, ContentChildren, Directive, HostBinding, Input, LOCALE_ID, QueryList, TemplateRef, Type, ViewChild, ViewContainerRef, Pipe, PipeTransform, NO_ERRORS_SCHEMA} from '@angular/core';
|
||||||
import {setDelayProjection} from '@angular/core/src/render3/instructions/projection';
|
import {setDelayProjection} from '@angular/core/src/render3/instructions/projection';
|
||||||
|
@ -18,6 +18,7 @@ import {By} from '@angular/platform-browser';
|
||||||
import {expect} from '@angular/platform-browser/testing/src/matchers';
|
import {expect} from '@angular/platform-browser/testing/src/matchers';
|
||||||
import {onlyInIvy} from '@angular/private/testing';
|
import {onlyInIvy} from '@angular/private/testing';
|
||||||
import {computeMsgId} from '@angular/compiler';
|
import {computeMsgId} from '@angular/compiler';
|
||||||
|
import {BehaviorSubject} from 'rxjs';
|
||||||
|
|
||||||
|
|
||||||
onlyInIvy('Ivy i18n logic').describe('runtime i18n', () => {
|
onlyInIvy('Ivy i18n logic').describe('runtime i18n', () => {
|
||||||
|
@ -1198,6 +1199,41 @@ onlyInIvy('Ivy i18n logic').describe('runtime i18n', () => {
|
||||||
// check that nested ICU is removed if root ICU case has changed
|
// check that nested ICU is removed if root ICU case has changed
|
||||||
expect(fixture.nativeElement.textContent.trim()).toBe('-');
|
expect(fixture.nativeElement.textContent.trim()).toBe('-');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should support ICUs with pipes', () => {
|
||||||
|
loadTranslations({
|
||||||
|
idA: '{VAR_SELECT, select, 1 {{INTERPOLATION} article} 2 {deux articles}}',
|
||||||
|
});
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app',
|
||||||
|
template: `
|
||||||
|
<div i18n="@@idA">{count$ | async, select, 1 {{{count$ | async}} item} 2 {two items}}</div>
|
||||||
|
`
|
||||||
|
})
|
||||||
|
class AppComponent {
|
||||||
|
count$ = new BehaviorSubject<number>(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
imports: [CommonModule],
|
||||||
|
declarations: [AppComponent],
|
||||||
|
});
|
||||||
|
|
||||||
|
const fixture = TestBed.createComponent(AppComponent);
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(fixture.nativeElement.textContent).toBe('1 article');
|
||||||
|
|
||||||
|
fixture.componentInstance.count$.next(3);
|
||||||
|
fixture.detectChanges();
|
||||||
|
// there is no ICU case for count=3, expecting empty content
|
||||||
|
expect(fixture.nativeElement.textContent.trim()).toBe('');
|
||||||
|
|
||||||
|
fixture.componentInstance.count$.next(2);
|
||||||
|
fixture.detectChanges();
|
||||||
|
// checking the second ICU case
|
||||||
|
expect(fixture.nativeElement.textContent.trim()).toBe('deux articles');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('should support attributes', () => {
|
describe('should support attributes', () => {
|
||||||
|
|
Loading…
Reference in New Issue