diff --git a/BREAKING.md b/BREAKING.md
index f769be99ce..8d90fe890b 100644
--- a/BREAKING.md
+++ b/BREAKING.md
@@ -35,6 +35,7 @@ This is a comprehensive list of the breaking changes introduced in the major ver
- [Types](#version-7x-types)
- [Overlay Attribute Interfaces](#version-7x-overlay-attribute-interfaces)
- [JavaScript Frameworks](#version-7x-javascript-frameworks)
+ - [Angular](#version-7x-angular)
- [React](#version-7x-react)
- [Vue](#version-7x-vue)
- [Utilities](#version-7x-utilities)
@@ -101,6 +102,8 @@ This section details the desktop browser, JavaScript framework, and mobile platf
- Datetime no longer incorrectly reports the time zone when `value` is updated. Datetime does not manage time zones, so any time zone information provided is ignored.
+- Passing the empty string to the `value` property will now error as it is not a valid ISO-8601 value.
+
- `ionChange` is no longer emitted when the `value` of `ion-input` is modified externally. `ionChange` is only emitted from user committed changes, such as typing in the input and the input losing focus or from clicking the clear action within the input.
@@ -223,6 +226,10 @@ Any references to the virtual scroll types from `@ionic/core` have been removed.
JavaScript Frameworks
+Angular
+
+- `null` values on form components will no longer be converted to the empty string (`''`) or `false`. This impacts `ion-checkbox`, `ion-datetime`, `ion-input`, `ion-radio`, `ion-radio-group`, ion-range`, `ion-searchbar`, `ion-segment`, `ion-select`, `ion-textarea`, and `ion-toggle`.
+
React
`@ionic/react` and `@ionic/react-router` no longer ship a CommonJS entry point. Instead, only an ES Module entry point is provided for improved compatibility with Vite.
diff --git a/angular/src/directives/control-value-accessors/boolean-value-accessor.ts b/angular/src/directives/control-value-accessors/boolean-value-accessor.ts
index b8484516e4..c70b0a40dd 100644
--- a/angular/src/directives/control-value-accessors/boolean-value-accessor.ts
+++ b/angular/src/directives/control-value-accessors/boolean-value-accessor.ts
@@ -19,7 +19,7 @@ export class BooleanValueAccessorDirective extends ValueAccessor {
}
writeValue(value: any): void {
- this.el.nativeElement.checked = this.lastValue = value == null ? false : value;
+ this.el.nativeElement.checked = this.lastValue = value;
setIonicClasses(this.el);
}
diff --git a/angular/src/directives/control-value-accessors/value-accessor.ts b/angular/src/directives/control-value-accessors/value-accessor.ts
index 77bb27b2b6..5d6e7d5f46 100644
--- a/angular/src/directives/control-value-accessors/value-accessor.ts
+++ b/angular/src/directives/control-value-accessors/value-accessor.ts
@@ -18,14 +18,7 @@ export class ValueAccessor implements ControlValueAccessor, AfterViewInit, OnDes
constructor(protected injector: Injector, protected el: ElementRef) {}
writeValue(value: any): void {
- /**
- * TODO FW-2646
- * Change `value == null ? '' : value;`
- * to `value`. This was a fix for IE9, but IE9
- * is no longer supported; however, this change
- * is potentially a breaking change
- */
- this.el.nativeElement.value = this.lastValue = value == null ? '' : value;
+ this.el.nativeElement.value = this.lastValue = value;
setIonicClasses(this.el);
}
diff --git a/angular/test/base/e2e/src/inputs.spec.ts b/angular/test/base/e2e/src/inputs.spec.ts
index 873ae2374f..2b076f6284 100644
--- a/angular/test/base/e2e/src/inputs.spec.ts
+++ b/angular/test/base/e2e/src/inputs.spec.ts
@@ -16,9 +16,15 @@ describe('Inputs', () => {
cy.get('ion-checkbox').should('have.prop', 'checked').and('equal', false);
cy.get('ion-toggle').should('have.prop', 'checked').and('equal', false);
- cy.get('ion-input').should('have.prop', 'value').and('equal', '');
- cy.get('ion-datetime').should('have.prop', 'value').and('equal', '');
- cy.get('ion-select').should('have.prop', 'value').and('equal', '');
+ /**
+ * The `value` property gets set to undefined
+ * for these components, so we need to check
+ * not.have.prop which will check that the
+ * value property is undefined.
+ */
+ cy.get('ion-input').should('not.have.prop', 'value');
+ cy.get('ion-datetime').should('not.have.prop', 'value');
+ cy.get('ion-select').should('not.have.prop', 'value');
});
it('should get some value', () => {
diff --git a/core/src/components/datetime-button/datetime-button.tsx b/core/src/components/datetime-button/datetime-button.tsx
index 3200b84ca9..532dd01481 100644
--- a/core/src/components/datetime-button/datetime-button.tsx
+++ b/core/src/components/datetime-button/datetime-button.tsx
@@ -160,8 +160,7 @@ export class DatetimeButton implements ComponentInterface {
* to keep checking if the datetime value is `string` or `string[]`.
*/
private getParsedDateValues = (value?: string[] | string | null): string[] => {
- // TODO FW-2646 Remove value === ''
- if (value === '' || value === undefined || value === null) {
+ if (value === undefined || value === null) {
return [];
}
diff --git a/core/src/components/datetime/datetime.tsx b/core/src/components/datetime/datetime.tsx
index be157ec576..eefe21a446 100644
--- a/core/src/components/datetime/datetime.tsx
+++ b/core/src/components/datetime/datetime.tsx
@@ -1171,7 +1171,7 @@ export class Datetime implements ComponentInterface {
}
private processValue = (value?: string | string[] | null) => {
- const hasValue = value !== '' && value !== null && value !== undefined;
+ const hasValue = value !== null && value !== undefined;
const valueToProcess = hasValue ? parseDate(value) : this.defaultParts;
const { minParts, maxParts } = this;
@@ -1283,7 +1283,7 @@ export class Datetime implements ComponentInterface {
};
private hasValue = () => {
- return this.value != null && this.value !== '';
+ return this.value != null;
};
private nextMonth = () => {