Skip to content

Commit

Permalink
fix(angular): item styling when control has value (#24932)
Browse files Browse the repository at this point in the history
Resolves #23809
  • Loading branch information
sean-perkins committed Apr 5, 2022
1 parent 982dc85 commit eea25d0
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 11 deletions.
21 changes: 11 additions & 10 deletions angular/src/directives/control-value-accessors/value-accessor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,13 +110,17 @@ export class ValueAccessor implements ControlValueAccessor, AfterViewInit, OnDes

export const setIonicClasses = (element: ElementRef): void => {
raf(() => {
const input = element.nativeElement as HTMLElement;
const input = element.nativeElement as HTMLInputElement;
const hasValue = input.value != null && input.value.toString().length > 0;
const classes = getClasses(input);
setClasses(input, classes);

const item = input.closest('ion-item');
if (item) {
setClasses(item, classes);
if (hasValue) {
setClasses(item, [...classes, 'item-has-value']);
} else {
setClasses(item, classes);
}
}
});
};
Expand All @@ -127,21 +131,18 @@ const getClasses = (element: HTMLElement) => {
for (let i = 0; i < classList.length; i++) {
const item = classList.item(i);
if (item !== null && startsWith(item, 'ng-')) {
classes.push(`ion-${item.substr(3)}`);
classes.push(`ion-${item.substring(3)}`);
}
}
return classes;
};

const setClasses = (element: HTMLElement, classes: string[]) => {
const classList = element.classList;
['ion-valid', 'ion-invalid', 'ion-touched', 'ion-untouched', 'ion-dirty', 'ion-pristine'].forEach((c) =>
classList.remove(c)
);

classes.forEach((c) => classList.add(c));
classList.remove('ion-valid', 'ion-invalid', 'ion-touched', 'ion-untouched', 'ion-dirty', 'ion-pristine');
classList.add(...classes);
};

const startsWith = (input: string, search: string): boolean => {
return input.substr(0, search.length) === search;
return input.substring(0, search.length) === search;
};
27 changes: 26 additions & 1 deletion angular/test/test-app/e2e/src/modal.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ describe('Modals', () => {

});


describe('Modals: Inline', () => {
beforeEach(() => {
cy.visit('/modal-inline');
Expand Down Expand Up @@ -77,3 +76,29 @@ describe('Modals: Inline', () => {
cy.get('ion-modal').children('.ion-page').should('not.exist');
})
});

describe('when in a modal', () => {

beforeEach(() => {
cy.visit('/modals');
cy.get('#action-button').click();
cy.get('#close-modal').click();
cy.get('#action-button').click();
});

it('should render ion-item item-has-value class when control value is set', () => {
cy.get('[formControlName="select"]').invoke('attr', 'value', 0);
cy.get('#inputWithFloatingLabel').should('have.class', 'item-has-value');
});

it('should not render ion-item item-has-value class when control value is undefined', () => {
cy.get('[formControlName="select"]').invoke('attr', 'value', undefined);
cy.get('#inputWithFloatingLabel').should('not.have.class', 'item-has-value');
});

it('should not render ion-item item-has-value class when control value is null', () => {
cy.get('[formControlName="select"]').invoke('attr', 'value', null);
cy.get('#inputWithFloatingLabel').should('not.have.class', 'item-has-value');
});

});
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,14 @@ <h3>{{valueFromParams}}</h3>
<ion-button (click)="push()" class="push-page">Push page</ion-button>
<ion-button (click)="pop()" class="pop-page">Pop page</ion-button>
</p>

<form [formGroup]="form">
<ion-item id="inputWithFloatingLabel">
<ion-label color="primary" position="floating">Floating Label</ion-label>
<ion-select multiple="false" formControlName="select">
<ion-select-option [value]="0">Option 0</ion-select-option>
<ion-select-option [value]="1">Option 1</ion-select-option>
</ion-select>
</ion-item>
</form>
</ion-content>
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Component, Input, NgZone, OnInit, Optional } from '@angular/core';
import { FormControl, FormGroup } from '@angular/forms';
import { ModalController, NavParams, IonNav, ViewWillLeave, ViewDidEnter, ViewDidLeave } from '@ionic/angular';

@Component({
Expand All @@ -9,6 +10,10 @@ export class ModalExampleComponent implements OnInit, ViewWillLeave, ViewDidEnte

@Input() value: string;

form = new FormGroup({
select: new FormControl([])
});

valueFromParams: string;
onInit = 0;
willEnter = 0;
Expand Down

0 comments on commit eea25d0

Please sign in to comment.