refactor(common): change missing NgSwitch provider error message (#41704)
change error message of invalid NgSwitch use and add corner cases tests PR Close #41704
This commit is contained in:
parent
2b939767fe
commit
640ec7828f
|
@ -6,7 +6,7 @@
|
||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {Directive, DoCheck, Host, Input, TemplateRef, ViewContainerRef} from '@angular/core';
|
import {Directive, DoCheck, Host, Input, Optional, TemplateRef, ViewContainerRef, ɵRuntimeError as RuntimeError, ɵRuntimeErrorCode as RuntimeErrorCode} from '@angular/core';
|
||||||
|
|
||||||
export class SwitchView {
|
export class SwitchView {
|
||||||
private _created = false;
|
private _created = false;
|
||||||
|
@ -197,7 +197,11 @@ export class NgSwitchCase implements DoCheck {
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
viewContainer: ViewContainerRef, templateRef: TemplateRef<Object>,
|
viewContainer: ViewContainerRef, templateRef: TemplateRef<Object>,
|
||||||
@Host() private ngSwitch: NgSwitch) {
|
@Optional() @Host() private ngSwitch: NgSwitch) {
|
||||||
|
if ((typeof ngDevMode === 'undefined' || ngDevMode) && !ngSwitch) {
|
||||||
|
throwNgSwitchProviderNotFoundError('ngSwitchCase', 'NgSwitchCase');
|
||||||
|
}
|
||||||
|
|
||||||
ngSwitch._addCase();
|
ngSwitch._addCase();
|
||||||
this._view = new SwitchView(viewContainer, templateRef);
|
this._view = new SwitchView(viewContainer, templateRef);
|
||||||
}
|
}
|
||||||
|
@ -228,7 +232,20 @@ export class NgSwitchCase implements DoCheck {
|
||||||
export class NgSwitchDefault {
|
export class NgSwitchDefault {
|
||||||
constructor(
|
constructor(
|
||||||
viewContainer: ViewContainerRef, templateRef: TemplateRef<Object>,
|
viewContainer: ViewContainerRef, templateRef: TemplateRef<Object>,
|
||||||
@Host() ngSwitch: NgSwitch) {
|
@Optional() @Host() ngSwitch: NgSwitch) {
|
||||||
|
if ((typeof ngDevMode === 'undefined' || ngDevMode) && !ngSwitch) {
|
||||||
|
throwNgSwitchProviderNotFoundError('ngSwitchDefault', 'NgSwitchDefault');
|
||||||
|
}
|
||||||
|
|
||||||
ngSwitch._addDefault(new SwitchView(viewContainer, templateRef));
|
ngSwitch._addDefault(new SwitchView(viewContainer, templateRef));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function throwNgSwitchProviderNotFoundError(attrName: string, directiveName: string): never {
|
||||||
|
throw new RuntimeError(
|
||||||
|
RuntimeErrorCode.TEMPLATE_STRUCTURE_ERROR,
|
||||||
|
`An element with the "${attrName}" attribute ` +
|
||||||
|
`(matching the "${
|
||||||
|
directiveName}" directive) must be located inside an element with the "ngSwitch" attribute ` +
|
||||||
|
`(matching "NgSwitch" directive)`);
|
||||||
|
}
|
||||||
|
|
|
@ -7,8 +7,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {CommonModule} from '@angular/common';
|
import {CommonModule} from '@angular/common';
|
||||||
import {Attribute, Component, Directive, TemplateRef, ViewChild} from '@angular/core';
|
import {Attribute, Component, Directive, TemplateRef, ViewChild,} from '@angular/core';
|
||||||
import {ComponentFixture, TestBed} from '@angular/core/testing';
|
import {ComponentFixture, TestBed, waitForAsync} from '@angular/core/testing';
|
||||||
import {expect} from '@angular/platform-browser/testing/src/matchers';
|
import {expect} from '@angular/platform-browser/testing/src/matchers';
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -176,6 +176,24 @@ import {expect} from '@angular/platform-browser/testing/src/matchers';
|
||||||
detectChangesAndExpectText('when b1;when b2;');
|
detectChangesAndExpectText('when b1;when b2;');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should throw error when ngSwitchCase is used outside of ngSwitch', waitForAsync(() => {
|
||||||
|
const template = '<div [ngSwitch]="switchValue"></div>' +
|
||||||
|
'<div *ngSwitchCase="\'a\'"></div>';
|
||||||
|
|
||||||
|
expect(() => createTestComponent(template))
|
||||||
|
.toThrowError(
|
||||||
|
'NG0305: An element with the "ngSwitchCase" attribute (matching the "NgSwitchCase" directive) must be located inside an element with the "ngSwitch" attribute (matching "NgSwitch" directive)');
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should throw error when ngSwitchDefault is used outside of ngSwitch', waitForAsync(() => {
|
||||||
|
const template = '<div [ngSwitch]="switchValue"></div>' +
|
||||||
|
'<div *ngSwitchDefault></div>';
|
||||||
|
|
||||||
|
expect(() => createTestComponent(template))
|
||||||
|
.toThrowError(
|
||||||
|
'NG0305: An element with the "ngSwitchDefault" attribute (matching the "NgSwitchDefault" directive) must be located inside an element with the "ngSwitch" attribute (matching "NgSwitch" directive)');
|
||||||
|
}));
|
||||||
|
|
||||||
it('should support nested NgSwitch on ng-container with ngTemplateOutlet', () => {
|
it('should support nested NgSwitch on ng-container with ngTemplateOutlet', () => {
|
||||||
fixture = TestBed.createComponent(ComplexComponent);
|
fixture = TestBed.createComponent(ComplexComponent);
|
||||||
detectChangesAndExpectText('Foo');
|
detectChangesAndExpectText('Foo');
|
||||||
|
|
|
@ -24,6 +24,7 @@ export {CodegenComponentFactoryResolver as ɵCodegenComponentFactoryResolver} fr
|
||||||
export {clearResolutionOfComponentResourcesQueue as ɵclearResolutionOfComponentResourcesQueue, resolveComponentResources as ɵresolveComponentResources} from './metadata/resource_loading';
|
export {clearResolutionOfComponentResourcesQueue as ɵclearResolutionOfComponentResourcesQueue, resolveComponentResources as ɵresolveComponentResources} from './metadata/resource_loading';
|
||||||
export {ReflectionCapabilities as ɵReflectionCapabilities} from './reflection/reflection_capabilities';
|
export {ReflectionCapabilities as ɵReflectionCapabilities} from './reflection/reflection_capabilities';
|
||||||
export {GetterFn as ɵGetterFn, MethodFn as ɵMethodFn, SetterFn as ɵSetterFn} from './reflection/types';
|
export {GetterFn as ɵGetterFn, MethodFn as ɵMethodFn, SetterFn as ɵSetterFn} from './reflection/types';
|
||||||
|
export {RuntimeError as ɵRuntimeError, RuntimeErrorCode as ɵRuntimeErrorCode} from './render3/error_code';
|
||||||
export {allowSanitizationBypassAndThrow as ɵallowSanitizationBypassAndThrow, BypassType as ɵBypassType, getSanitizationBypassType as ɵgetSanitizationBypassType, SafeHtml as ɵSafeHtml, SafeResourceUrl as ɵSafeResourceUrl, SafeScript as ɵSafeScript, SafeStyle as ɵSafeStyle, SafeUrl as ɵSafeUrl, SafeValue as ɵSafeValue, unwrapSafeValue as ɵunwrapSafeValue} from './sanitization/bypass';
|
export {allowSanitizationBypassAndThrow as ɵallowSanitizationBypassAndThrow, BypassType as ɵBypassType, getSanitizationBypassType as ɵgetSanitizationBypassType, SafeHtml as ɵSafeHtml, SafeResourceUrl as ɵSafeResourceUrl, SafeScript as ɵSafeScript, SafeStyle as ɵSafeStyle, SafeUrl as ɵSafeUrl, SafeValue as ɵSafeValue, unwrapSafeValue as ɵunwrapSafeValue} from './sanitization/bypass';
|
||||||
export {_sanitizeHtml as ɵ_sanitizeHtml} from './sanitization/html_sanitizer';
|
export {_sanitizeHtml as ɵ_sanitizeHtml} from './sanitization/html_sanitizer';
|
||||||
export {_sanitizeUrl as ɵ_sanitizeUrl} from './sanitization/url_sanitizer';
|
export {_sanitizeUrl as ɵ_sanitizeUrl} from './sanitization/url_sanitizer';
|
||||||
|
|
|
@ -27,6 +27,7 @@ export const enum RuntimeErrorCode {
|
||||||
PIPE_NOT_FOUND = '302',
|
PIPE_NOT_FOUND = '302',
|
||||||
UNKNOWN_BINDING = '303',
|
UNKNOWN_BINDING = '303',
|
||||||
UNKNOWN_ELEMENT = '304',
|
UNKNOWN_ELEMENT = '304',
|
||||||
|
TEMPLATE_STRUCTURE_ERROR = '305'
|
||||||
|
|
||||||
// Styling Errors
|
// Styling Errors
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue