diff --git a/packages/core/src/render3/instructions.ts b/packages/core/src/render3/instructions.ts
index df1d347ee4..3f2b0a5add 100644
--- a/packages/core/src/render3/instructions.ts
+++ b/packages/core/src/render3/instructions.ts
@@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
-import './ng_dev_mode';
+
import {resolveForwardRef} from '../di/forward_ref';
import {InjectionToken} from '../di/injection_token';
import {Injector} from '../di/injector';
@@ -16,6 +16,7 @@ import {Sanitizer} from '../sanitization/security';
import {StyleSanitizeFn} from '../sanitization/style_sanitizer';
import {Type} from '../type';
import {noop} from '../util/noop';
+
import {assertDefined, assertEqual, assertLessThan, assertNotEqual} from './assert';
import {attachPatchData, getComponentViewByInstance} from './context_discovery';
import {diPublicInInjector, getNodeInjectable, getOrCreateInjectable, getOrCreateNodeInjectorForNode, injectAttributeImpl} from './di';
@@ -40,7 +41,7 @@ import {createStylingContextTemplate, renderStyleAndClassBindings, updateClassPr
import {BoundPlayerFactory} from './styling/player_factory';
import {getStylingContext} from './styling/util';
import {NO_CHANGE} from './tokens';
-import {getComponentViewByIndex, getNativeByIndex, getNativeByTNode, getRootContext, getRootView, getTNode, isComponent, isComponentDef, isDifferent, loadInternal, readPatchedLViewData, stringify} from './util';
+import {getComponentViewByIndex, getNativeByIndex, getNativeByTNode, getRootContext, getRootView, getTNode, isComponent, isComponentDef, isDifferent, loadInternal, readElementValue, readPatchedLViewData, stringify} from './util';
/**
* A permanent marker promise which signifies that the current CD tree is
@@ -125,6 +126,12 @@ export function setHostBindings(tView: TView, viewData: LViewData): void {
viewData[BINDING_INDEX] = bindingRootIndex;
// We must subtract the header offset because the load() instruction
// expects a raw, unadjusted index.
+ // : set the `previousOrParentTNode` so that hostBindings functions can
+ // correctly retrieve it. This should be removed once we call the hostBindings function
+ // inline as part of the `RenderFlags.Create` because in that case the value will already be
+ // correctly set.
+ setPreviousOrParentTNode(getTView().data[currentElementIndex + HEADER_OFFSET] as TNode);
+ //
instruction(currentDirectiveIndex - HEADER_OFFSET, currentElementIndex);
currentDirectiveIndex++;
}
@@ -1069,17 +1076,21 @@ function generatePropertyAliases(
* This instruction is meant to handle the [class.foo]="exp" case
*
* @param index The index of the element to update in the data array
- * @param className Name of class to toggle. Because it is going to DOM, this is not subject to
+ * @param classIndex Index of class to toggle. Because it is going to DOM, this is not subject to
* renaming as part of minification.
* @param value A value indicating if a given class should be added or removed.
* @param directiveIndex the index for the directive that is attempting to change styling.
*/
export function elementClassProp(
- index: number, stylingIndex: number, value: boolean | PlayerFactory,
+ index: number, classIndex: number, value: boolean | PlayerFactory,
directiveIndex?: number): void {
+ if (directiveIndex != undefined) {
+ return hackImplementationOfElementClassProp(
+ index, classIndex, value, directiveIndex); // proper supported in next PR
+ }
const val =
(value instanceof BoundPlayerFactory) ? (value as BoundPlayerFactory) : (!!value);
- updateElementClassProp(getStylingContext(index, getViewData()), stylingIndex, val);
+ updateElementClassProp(getStylingContext(index, getViewData()), classIndex, val);
}
/**
@@ -1115,7 +1126,13 @@ export function elementStyling(
classDeclarations?: (string | boolean | InitialStylingFlags)[] | null,
styleDeclarations?: (string | boolean | InitialStylingFlags)[] | null,
styleSanitizer?: StyleSanitizeFn | null, directiveIndex?: number): void {
- if (directiveIndex) return; // supported in next PR
+ if (directiveIndex !== undefined) {
+ getCreationMode() &&
+ hackImplementationOfElementStyling(
+ classDeclarations || null, styleDeclarations || null, styleSanitizer || null,
+ directiveIndex); // supported in next PR
+ return;
+ }
const tNode = getPreviousOrParentTNode();
const inputData = initializeTNodeInputs(tNode);
@@ -1159,7 +1176,9 @@ export function elementStyling(
* @param directiveIndex the index for the directive that is attempting to change styling.
*/
export function elementStylingApply(index: number, directiveIndex?: number): void {
- if (directiveIndex) return; // supported in next PR
+ if (directiveIndex != undefined) {
+ return hackImplementationOfElementStylingApply(index, directiveIndex); // supported in next PR
+ }
const viewData = getViewData();
const isFirstRender = (viewData[FLAGS] & LViewFlags.CreationMode) !== 0;
const totalPlayersQueued = renderStyleAndClassBindings(
@@ -1194,7 +1213,9 @@ export function elementStylingApply(index: number, directiveIndex?: number): voi
export function elementStyleProp(
index: number, styleIndex: number, value: string | number | String | PlayerFactory | null,
suffix?: string, directiveIndex?: number): void {
- if (directiveIndex) return; // supported in next PR
+ if (directiveIndex != undefined)
+ return hackImplementationOfElementStyleProp(
+ index, styleIndex, value, suffix, directiveIndex); // supported in next PR
let valueToAdd: string|null = null;
if (value) {
if (suffix) {
@@ -1237,7 +1258,9 @@ export function elementStyleProp(
export function elementStylingMap(
index: number, classes: {[key: string]: any} | string | NO_CHANGE | null,
styles?: {[styleName: string]: any} | NO_CHANGE | null, directiveIndex?: number): void {
- if (directiveIndex) return; // supported in next PR
+ if (directiveIndex != undefined)
+ return hackImplementationOfElementStylingMap(
+ index, classes, styles, directiveIndex); // supported in next PR
const viewData = getViewData();
const tNode = getTNode(index, viewData);
const stylingContext = getStylingContext(index, viewData);
@@ -1250,6 +1273,74 @@ export function elementStylingMap(
updateStylingMap(stylingContext, classes, styles);
}
+/* START OF HACK BLOCK */
+/*
+ * HACK
+ * The code below is a quick and dirty implementation of the host style binding so that we can make
+ * progress on TestBed. Once the correct implementation is created this code should be removed.
+ */
+interface HostStylingHack {
+ classDeclarations: string[];
+ styleDeclarations: string[];
+ styleSanitizer: StyleSanitizeFn|null;
+}
+interface HostStylingHackMap {
+ [directiveIndex: number]: HostStylingHack;
+}
+
+function hackImplementationOfElementStyling(
+ classDeclarations: (string | boolean | InitialStylingFlags)[] | null,
+ styleDeclarations: (string | boolean | InitialStylingFlags)[] | null,
+ styleSanitizer: StyleSanitizeFn | null, directiveIndex: number): void {
+ const node = getNativeByTNode(getPreviousOrParentTNode(), getViewData());
+ ngDevMode && assertDefined(node, 'expecting parent DOM node');
+ const hostStylingHackMap: HostStylingHackMap =
+ ((node as any).hostStylingHack || ((node as any).hostStylingHack = {}));
+ hostStylingHackMap[directiveIndex] = {
+ classDeclarations: hackSquashDeclaration(classDeclarations),
+ styleDeclarations: hackSquashDeclaration(styleDeclarations), styleSanitizer
+ };
+}
+
+function hackSquashDeclaration(declarations: (string | boolean | InitialStylingFlags)[] | null):
+ string[] {
+ // assume the array is correct. This should be fine for View Engine compatibility.
+ return declarations || [] as any;
+}
+
+function hackImplementationOfElementClassProp(
+ index: number, classIndex: number, value: boolean | PlayerFactory,
+ directiveIndex: number): void {
+ const node = getNativeByIndex(index, getViewData());
+ ngDevMode && assertDefined(node, 'could not locate node');
+ const hostStylingHack: HostStylingHack = (node as any).hostStylingHack[directiveIndex];
+ const className = hostStylingHack.classDeclarations[classIndex];
+ const renderer = getRenderer();
+ if (isProceduralRenderer(renderer)) {
+ value ? renderer.addClass(node, className) : renderer.removeClass(node, className);
+ } else {
+ const classList = (node as HTMLElement).classList;
+ value ? classList.add(className) : classList.remove(className);
+ }
+}
+
+function hackImplementationOfElementStylingApply(index: number, directiveIndex?: number): void {
+ // Do nothing because the hack implementation is eager.
+}
+
+function hackImplementationOfElementStyleProp(
+ index: number, styleIndex: number, value: string | number | String | PlayerFactory | null,
+ suffix?: string, directiveIndex?: number): void {
+ throw new Error('unimplemented. Should not be needed by ViewEngine compatibility');
+}
+
+function hackImplementationOfElementStylingMap(
+ index: number, classes: {[key: string]: any} | string | NO_CHANGE | null,
+ styles?: {[styleName: string]: any} | NO_CHANGE | null, directiveIndex?: number): void {
+ throw new Error('unimplemented. Should not be needed by ViewEngine compatibility');
+}
+
+/* END OF HACK BLOCK */
//////////////////////////
//// Text
//////////////////////////
diff --git a/packages/core/test/bundling/animation_world/bundle.golden_symbols.json b/packages/core/test/bundling/animation_world/bundle.golden_symbols.json
index ec84f12fa5..0fdfdf721e 100644
--- a/packages/core/test/bundling/animation_world/bundle.golden_symbols.json
+++ b/packages/core/test/bundling/animation_world/bundle.golden_symbols.json
@@ -785,6 +785,18 @@
{
"name": "getViewData"
},
+ {
+ "name": "hackImplementationOfElementStyling"
+ },
+ {
+ "name": "hackImplementationOfElementStylingApply"
+ },
+ {
+ "name": "hackImplementationOfElementStylingMap"
+ },
+ {
+ "name": "hackSquashDeclaration"
+ },
{
"name": "hasParentInjector"
},
diff --git a/packages/core/test/bundling/todo/bundle.golden_symbols.json b/packages/core/test/bundling/todo/bundle.golden_symbols.json
index 6a2f61b698..427f0c9959 100644
--- a/packages/core/test/bundling/todo/bundle.golden_symbols.json
+++ b/packages/core/test/bundling/todo/bundle.golden_symbols.json
@@ -818,6 +818,18 @@
{
"name": "getViewData"
},
+ {
+ "name": "hackImplementationOfElementClassProp"
+ },
+ {
+ "name": "hackImplementationOfElementStyling"
+ },
+ {
+ "name": "hackImplementationOfElementStylingApply"
+ },
+ {
+ "name": "hackSquashDeclaration"
+ },
{
"name": "hasParentInjector"
},
diff --git a/packages/core/test/bundling/todo_r2/bundle.golden_symbols.json b/packages/core/test/bundling/todo_r2/bundle.golden_symbols.json
index 2ec554f072..bf92044df9 100644
--- a/packages/core/test/bundling/todo_r2/bundle.golden_symbols.json
+++ b/packages/core/test/bundling/todo_r2/bundle.golden_symbols.json
@@ -1943,6 +1943,18 @@
{
"name": "globalListener"
},
+ {
+ "name": "hackImplementationOfElementClassProp"
+ },
+ {
+ "name": "hackImplementationOfElementStyling"
+ },
+ {
+ "name": "hackImplementationOfElementStylingApply"
+ },
+ {
+ "name": "hackSquashDeclaration"
+ },
{
"name": "hasBalancedQuotes"
},
diff --git a/packages/forms/test/reactive_integration_spec.ts b/packages/forms/test/reactive_integration_spec.ts
index 2ba8f67604..22a1c16191 100644
--- a/packages/forms/test/reactive_integration_spec.ts
+++ b/packages/forms/test/reactive_integration_spec.ts
@@ -12,7 +12,6 @@ import {AbstractControl, AsyncValidator, AsyncValidatorFn, COMPOSITION_BUFFER_MO
import {By} from '@angular/platform-browser/src/dom/debug/by';
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
import {dispatchEvent} from '@angular/platform-browser/testing/src/browser_util';
-import {fixmeIvy} from '@angular/private/testing';
import {merge, timer} from 'rxjs';
import {tap} from 'rxjs/operators';
@@ -713,133 +712,127 @@ import {MyInput, MyInputForm} from './value_accessor_integration_spec';
});
- fixmeIvy('Host bindings to styles do not yet work') &&
- describe('setting status classes', () => {
- it('should work with single fields', () => {
- const fixture = initTest(FormControlComp);
- const control = new FormControl('', Validators.required);
- fixture.componentInstance.control = control;
- fixture.detectChanges();
+ describe('setting status classes', () => {
+ it('should work with single fields', () => {
+ const fixture = initTest(FormControlComp);
+ const control = new FormControl('', Validators.required);
+ fixture.componentInstance.control = control;
+ fixture.detectChanges();
- const input = fixture.debugElement.query(By.css('input')).nativeElement;
- expect(sortedClassList(input)).toEqual(['ng-invalid', 'ng-pristine', 'ng-untouched']);
+ const input = fixture.debugElement.query(By.css('input')).nativeElement;
+ expect(sortedClassList(input)).toEqual(['ng-invalid', 'ng-pristine', 'ng-untouched']);
- dispatchEvent(input, 'blur');
- fixture.detectChanges();
+ dispatchEvent(input, 'blur');
+ fixture.detectChanges();
- expect(sortedClassList(input)).toEqual(['ng-invalid', 'ng-pristine', 'ng-touched']);
+ expect(sortedClassList(input)).toEqual(['ng-invalid', 'ng-pristine', 'ng-touched']);
- input.value = 'updatedValue';
- dispatchEvent(input, 'input');
- fixture.detectChanges();
+ input.value = 'updatedValue';
+ dispatchEvent(input, 'input');
+ fixture.detectChanges();
- expect(sortedClassList(input)).toEqual(['ng-dirty', 'ng-touched', 'ng-valid']);
- });
+ expect(sortedClassList(input)).toEqual(['ng-dirty', 'ng-touched', 'ng-valid']);
+ });
- it('should work with single fields and async validators', fakeAsync(() => {
- const fixture = initTest(FormControlComp);
- const control = new FormControl('', null !, uniqLoginAsyncValidator('good'));
- fixture.debugElement.componentInstance.control = control;
- fixture.detectChanges();
+ it('should work with single fields and async validators', fakeAsync(() => {
+ const fixture = initTest(FormControlComp);
+ const control = new FormControl('', null !, uniqLoginAsyncValidator('good'));
+ fixture.debugElement.componentInstance.control = control;
+ fixture.detectChanges();
- const input = fixture.debugElement.query(By.css('input')).nativeElement;
- expect(sortedClassList(input)).toEqual([
- 'ng-pending', 'ng-pristine', 'ng-untouched'
- ]);
+ const input = fixture.debugElement.query(By.css('input')).nativeElement;
+ expect(sortedClassList(input)).toEqual(['ng-pending', 'ng-pristine', 'ng-untouched']);
- dispatchEvent(input, 'blur');
- fixture.detectChanges();
- expect(sortedClassList(input)).toEqual(['ng-pending', 'ng-pristine', 'ng-touched']);
+ dispatchEvent(input, 'blur');
+ fixture.detectChanges();
+ expect(sortedClassList(input)).toEqual(['ng-pending', 'ng-pristine', 'ng-touched']);
- input.value = 'good';
- dispatchEvent(input, 'input');
- tick();
- fixture.detectChanges();
+ input.value = 'good';
+ dispatchEvent(input, 'input');
+ tick();
+ fixture.detectChanges();
- expect(sortedClassList(input)).toEqual(['ng-dirty', 'ng-touched', 'ng-valid']);
- }));
+ expect(sortedClassList(input)).toEqual(['ng-dirty', 'ng-touched', 'ng-valid']);
+ }));
- it('should work with single fields that combines async and sync validators',
- fakeAsync(() => {
- const fixture = initTest(FormControlComp);
- const control =
- new FormControl('', Validators.required, uniqLoginAsyncValidator('good'));
- fixture.debugElement.componentInstance.control = control;
- fixture.detectChanges();
+ it('should work with single fields that combines async and sync validators', fakeAsync(() => {
+ const fixture = initTest(FormControlComp);
+ const control =
+ new FormControl('', Validators.required, uniqLoginAsyncValidator('good'));
+ fixture.debugElement.componentInstance.control = control;
+ fixture.detectChanges();
- const input = fixture.debugElement.query(By.css('input')).nativeElement;
- expect(sortedClassList(input)).toEqual([
- 'ng-invalid', 'ng-pristine', 'ng-untouched'
- ]);
+ const input = fixture.debugElement.query(By.css('input')).nativeElement;
+ expect(sortedClassList(input)).toEqual(['ng-invalid', 'ng-pristine', 'ng-untouched']);
- dispatchEvent(input, 'blur');
- fixture.detectChanges();
- expect(sortedClassList(input)).toEqual(['ng-invalid', 'ng-pristine', 'ng-touched']);
+ dispatchEvent(input, 'blur');
+ fixture.detectChanges();
+ expect(sortedClassList(input)).toEqual(['ng-invalid', 'ng-pristine', 'ng-touched']);
- input.value = 'bad';
- dispatchEvent(input, 'input');
- fixture.detectChanges();
+ input.value = 'bad';
+ dispatchEvent(input, 'input');
+ fixture.detectChanges();
- expect(sortedClassList(input)).toEqual(['ng-dirty', 'ng-pending', 'ng-touched']);
+ expect(sortedClassList(input)).toEqual(['ng-dirty', 'ng-pending', 'ng-touched']);
- tick();
- fixture.detectChanges();
+ tick();
+ fixture.detectChanges();
- expect(sortedClassList(input)).toEqual(['ng-dirty', 'ng-invalid', 'ng-touched']);
+ expect(sortedClassList(input)).toEqual(['ng-dirty', 'ng-invalid', 'ng-touched']);
- input.value = 'good';
- dispatchEvent(input, 'input');
- tick();
- fixture.detectChanges();
+ input.value = 'good';
+ dispatchEvent(input, 'input');
+ tick();
+ fixture.detectChanges();
- expect(sortedClassList(input)).toEqual(['ng-dirty', 'ng-touched', 'ng-valid']);
- }));
+ expect(sortedClassList(input)).toEqual(['ng-dirty', 'ng-touched', 'ng-valid']);
+ }));
- it('should work with single fields in parent forms', () => {
- const fixture = initTest(FormGroupComp);
- const form = new FormGroup({'login': new FormControl('', Validators.required)});
- fixture.componentInstance.form = form;
- fixture.detectChanges();
+ it('should work with single fields in parent forms', () => {
+ const fixture = initTest(FormGroupComp);
+ const form = new FormGroup({'login': new FormControl('', Validators.required)});
+ fixture.componentInstance.form = form;
+ fixture.detectChanges();
- const input = fixture.debugElement.query(By.css('input')).nativeElement;
- expect(sortedClassList(input)).toEqual(['ng-invalid', 'ng-pristine', 'ng-untouched']);
+ const input = fixture.debugElement.query(By.css('input')).nativeElement;
+ expect(sortedClassList(input)).toEqual(['ng-invalid', 'ng-pristine', 'ng-untouched']);
- dispatchEvent(input, 'blur');
- fixture.detectChanges();
+ dispatchEvent(input, 'blur');
+ fixture.detectChanges();
- expect(sortedClassList(input)).toEqual(['ng-invalid', 'ng-pristine', 'ng-touched']);
+ expect(sortedClassList(input)).toEqual(['ng-invalid', 'ng-pristine', 'ng-touched']);
- input.value = 'updatedValue';
- dispatchEvent(input, 'input');
- fixture.detectChanges();
+ input.value = 'updatedValue';
+ dispatchEvent(input, 'input');
+ fixture.detectChanges();
- expect(sortedClassList(input)).toEqual(['ng-dirty', 'ng-touched', 'ng-valid']);
- });
+ expect(sortedClassList(input)).toEqual(['ng-dirty', 'ng-touched', 'ng-valid']);
+ });
- it('should work with formGroup', () => {
- const fixture = initTest(FormGroupComp);
- const form = new FormGroup({'login': new FormControl('', Validators.required)});
- fixture.componentInstance.form = form;
- fixture.detectChanges();
+ it('should work with formGroup', () => {
+ const fixture = initTest(FormGroupComp);
+ const form = new FormGroup({'login': new FormControl('', Validators.required)});
+ fixture.componentInstance.form = form;
+ fixture.detectChanges();
- const input = fixture.debugElement.query(By.css('input')).nativeElement;
- const formEl = fixture.debugElement.query(By.css('form')).nativeElement;
+ const input = fixture.debugElement.query(By.css('input')).nativeElement;
+ const formEl = fixture.debugElement.query(By.css('form')).nativeElement;
- expect(sortedClassList(formEl)).toEqual(['ng-invalid', 'ng-pristine', 'ng-untouched']);
+ expect(sortedClassList(formEl)).toEqual(['ng-invalid', 'ng-pristine', 'ng-untouched']);
- dispatchEvent(input, 'blur');
- fixture.detectChanges();
+ dispatchEvent(input, 'blur');
+ fixture.detectChanges();
- expect(sortedClassList(formEl)).toEqual(['ng-invalid', 'ng-pristine', 'ng-touched']);
+ expect(sortedClassList(formEl)).toEqual(['ng-invalid', 'ng-pristine', 'ng-touched']);
- input.value = 'updatedValue';
- dispatchEvent(input, 'input');
- fixture.detectChanges();
+ input.value = 'updatedValue';
+ dispatchEvent(input, 'input');
+ fixture.detectChanges();
- expect(sortedClassList(formEl)).toEqual(['ng-dirty', 'ng-touched', 'ng-valid']);
- });
+ expect(sortedClassList(formEl)).toEqual(['ng-dirty', 'ng-touched', 'ng-valid']);
+ });
- });
+ });
describe('updateOn options', () => {
diff --git a/packages/forms/test/template_integration_spec.ts b/packages/forms/test/template_integration_spec.ts
index 7d2f8bbb18..ed487c032e 100644
--- a/packages/forms/test/template_integration_spec.ts
+++ b/packages/forms/test/template_integration_spec.ts
@@ -12,7 +12,6 @@ import {AbstractControl, AsyncValidator, COMPOSITION_BUFFER_MODE, FormControl, F
import {By} from '@angular/platform-browser/src/dom/debug/by';
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
import {dispatchEvent} from '@angular/platform-browser/testing/src/browser_util';
-import {fixmeIvy} from '@angular/private/testing';
import {merge} from 'rxjs';
import {NgModelCustomComp, NgModelCustomWrapper} from './value_accessor_integration_spec';
@@ -149,101 +148,85 @@ import {NgModelCustomComp, NgModelCustomWrapper} from './value_accessor_integrat
expect(form.value).toEqual({});
}));
- fixmeIvy('host bindings do not yet work with classes or styles') &&
- it('should set status classes with ngModel', async(() => {
- const fixture = initTest(NgModelForm);
- fixture.componentInstance.name = 'aa';
- fixture.detectChanges();
- fixture.whenStable().then(() => {
- fixture.detectChanges();
+ it('should set status classes with ngModel', async(() => {
+ const fixture = initTest(NgModelForm);
+ fixture.componentInstance.name = 'aa';
+ fixture.detectChanges();
+ fixture.whenStable().then(() => {
+ fixture.detectChanges();
- const input = fixture.debugElement.query(By.css('input')).nativeElement;
- expect(sortedClassList(input)).toEqual([
- 'ng-invalid', 'ng-pristine', 'ng-untouched'
- ]);
+ const input = fixture.debugElement.query(By.css('input')).nativeElement;
+ expect(sortedClassList(input)).toEqual(['ng-invalid', 'ng-pristine', 'ng-untouched']);
- dispatchEvent(input, 'blur');
- fixture.detectChanges();
+ dispatchEvent(input, 'blur');
+ fixture.detectChanges();
- expect(sortedClassList(input)).toEqual([
- 'ng-invalid', 'ng-pristine', 'ng-touched'
- ]);
+ expect(sortedClassList(input)).toEqual(['ng-invalid', 'ng-pristine', 'ng-touched']);
- input.value = 'updatedValue';
- dispatchEvent(input, 'input');
- fixture.detectChanges();
- expect(sortedClassList(input)).toEqual(['ng-dirty', 'ng-touched', 'ng-valid']);
- });
- }));
+ input.value = 'updatedValue';
+ dispatchEvent(input, 'input');
+ fixture.detectChanges();
+ expect(sortedClassList(input)).toEqual(['ng-dirty', 'ng-touched', 'ng-valid']);
+ });
+ }));
- fixmeIvy('host bindings do not yet work with classes or styles') &&
- it('should set status classes with ngModel and async validators', fakeAsync(() => {
+ it('should set status classes with ngModel and async validators', fakeAsync(() => {
- const fixture = initTest(NgModelAsyncValidation, NgAsyncValidator);
- fixture.whenStable().then(() => {
- fixture.detectChanges();
+ const fixture = initTest(NgModelAsyncValidation, NgAsyncValidator);
+ fixture.whenStable().then(() => {
+ fixture.detectChanges();
- const input = fixture.debugElement.query(By.css('input')).nativeElement;
- expect(sortedClassList(input)).toEqual([
- 'ng-pending', 'ng-pristine', 'ng-untouched'
- ]);
+ const input = fixture.debugElement.query(By.css('input')).nativeElement;
+ expect(sortedClassList(input)).toEqual(['ng-pending', 'ng-pristine', 'ng-untouched']);
- dispatchEvent(input, 'blur');
- fixture.detectChanges();
+ dispatchEvent(input, 'blur');
+ fixture.detectChanges();
- expect(sortedClassList(input)).toEqual([
- 'ng-pending', 'ng-pristine', 'ng-touched'
- ]);
+ expect(sortedClassList(input)).toEqual(['ng-pending', 'ng-pristine', 'ng-touched']);
- input.value = 'updatedValue';
- dispatchEvent(input, 'input');
- tick();
- fixture.detectChanges();
+ input.value = 'updatedValue';
+ dispatchEvent(input, 'input');
+ tick();
+ fixture.detectChanges();
- expect(sortedClassList(input)).toEqual(['ng-dirty', 'ng-touched', 'ng-valid']);
- });
- }));
+ expect(sortedClassList(input)).toEqual(['ng-dirty', 'ng-touched', 'ng-valid']);
+ });
+ }));
- fixmeIvy('host bindings do not yet work with classes or styles') &&
- it('should set status classes with ngModelGroup and ngForm', async(() => {
- const fixture = initTest(NgModelGroupForm);
- fixture.componentInstance.first = '';
- fixture.detectChanges();
+ it('should set status classes with ngModelGroup and ngForm', async(() => {
+ const fixture = initTest(NgModelGroupForm);
+ fixture.componentInstance.first = '';
+ fixture.detectChanges();
- const form = fixture.debugElement.query(By.css('form')).nativeElement;
- const modelGroup =
- fixture.debugElement.query(By.css('[ngModelGroup]')).nativeElement;
- const input = fixture.debugElement.query(By.css('input')).nativeElement;
+ const form = fixture.debugElement.query(By.css('form')).nativeElement;
+ const modelGroup = fixture.debugElement.query(By.css('[ngModelGroup]')).nativeElement;
+ const input = fixture.debugElement.query(By.css('input')).nativeElement;
- // ngModelGroup creates its control asynchronously
- fixture.whenStable().then(() => {
- fixture.detectChanges();
- expect(sortedClassList(modelGroup)).toEqual([
- 'ng-invalid', 'ng-pristine', 'ng-untouched'
- ]);
+ // ngModelGroup creates its control asynchronously
+ fixture.whenStable().then(() => {
+ fixture.detectChanges();
+ expect(sortedClassList(modelGroup)).toEqual([
+ 'ng-invalid', 'ng-pristine', 'ng-untouched'
+ ]);
- expect(sortedClassList(form)).toEqual([
- 'ng-invalid', 'ng-pristine', 'ng-untouched'
- ]);
+ expect(sortedClassList(form)).toEqual(['ng-invalid', 'ng-pristine', 'ng-untouched']);
- dispatchEvent(input, 'blur');
- fixture.detectChanges();
+ dispatchEvent(input, 'blur');
+ fixture.detectChanges();
- expect(sortedClassList(modelGroup)).toEqual([
- 'ng-invalid', 'ng-pristine', 'ng-touched'
- ]);
- expect(sortedClassList(form)).toEqual(['ng-invalid', 'ng-pristine', 'ng-touched']);
+ expect(sortedClassList(modelGroup)).toEqual([
+ 'ng-invalid', 'ng-pristine', 'ng-touched'
+ ]);
+ expect(sortedClassList(form)).toEqual(['ng-invalid', 'ng-pristine', 'ng-touched']);
- input.value = 'updatedValue';
- dispatchEvent(input, 'input');
- fixture.detectChanges();
+ input.value = 'updatedValue';
+ dispatchEvent(input, 'input');
+ fixture.detectChanges();
- expect(sortedClassList(modelGroup)).toEqual([
- 'ng-dirty', 'ng-touched', 'ng-valid'
- ]);
- expect(sortedClassList(form)).toEqual(['ng-dirty', 'ng-touched', 'ng-valid']);
- });
- }));
+ expect(sortedClassList(modelGroup)).toEqual(['ng-dirty', 'ng-touched', 'ng-valid']);
+ expect(sortedClassList(form)).toEqual(['ng-dirty', 'ng-touched', 'ng-valid']);
+ });
+ }));
it('should not create a template-driven form when ngNoForm is used', () => {
const fixture = initTest(NgNoFormComp);
diff --git a/packages/forms/test/value_accessor_integration_spec.ts b/packages/forms/test/value_accessor_integration_spec.ts
index 59b533c24f..a8061fe60c 100644
--- a/packages/forms/test/value_accessor_integration_spec.ts
+++ b/packages/forms/test/value_accessor_integration_spec.ts
@@ -11,7 +11,6 @@ import {ComponentFixture, TestBed, async, fakeAsync, tick} from '@angular/core/t
import {AbstractControl, ControlValueAccessor, FormControl, FormGroup, FormsModule, NG_VALIDATORS, NG_VALUE_ACCESSOR, NgControl, NgForm, NgModel, ReactiveFormsModule, Validators} from '@angular/forms';
import {By} from '@angular/platform-browser/src/dom/debug/by';
import {dispatchEvent} from '@angular/platform-browser/testing/src/browser_util';
-import {fixmeIvy} from '@angular/private/testing';
{
describe('value accessors', () => {