Skip to content

Commit 4171834

Browse files
committed
feat(textarea): reflect disabled and readonly props
1 parent 46806bd commit 4171834

File tree

14 files changed

+532
-221
lines changed

14 files changed

+532
-221
lines changed

core/api.txt

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -569,7 +569,6 @@ ion-datetime,part,calendar-day today
569569
ion-datetime,part,month-year-button
570570
ion-datetime,part,time-button
571571
ion-datetime,part,time-button active
572-
ion-datetime,part,wheel
573572
ion-datetime,part,wheel-item
574573
ion-datetime,part,wheel-item active
575574

@@ -1693,7 +1692,6 @@ ion-segment-content,shadow
16931692

16941693
ion-segment-view,shadow
16951694
ion-segment-view,prop,disabled,boolean,false,false,false
1696-
ion-segment-view,prop,swipeGesture,boolean,true,false,false
16971695
ion-segment-view,event,ionSegmentViewScroll,SegmentViewScrollEvent,true
16981696

16991697
ion-select,shadow
@@ -1768,7 +1766,6 @@ ion-select,part,supporting-text
17681766
ion-select,part,text
17691767

17701768
ion-select-modal,scoped
1771-
ion-select-modal,prop,cancelText,string,'Close',false,false
17721769
ion-select-modal,prop,header,string | undefined,undefined,false,false
17731770
ion-select-modal,prop,multiple,boolean | undefined,undefined,false,false
17741771
ion-select-modal,prop,options,SelectModalOption[],[],false,false
@@ -1876,7 +1873,7 @@ ion-textarea,prop,cols,number | undefined,undefined,false,true
18761873
ion-textarea,prop,counter,boolean,false,false,false
18771874
ion-textarea,prop,counterFormatter,((inputLength: number, maxLength: number) => string) | undefined,undefined,false,false
18781875
ion-textarea,prop,debounce,number | undefined,undefined,false,false
1879-
ion-textarea,prop,disabled,boolean,false,false,false
1876+
ion-textarea,prop,disabled,boolean,false,false,true
18801877
ion-textarea,prop,enterkeyhint,"done" | "enter" | "go" | "next" | "previous" | "search" | "send" | undefined,undefined,false,false
18811878
ion-textarea,prop,errorText,string | undefined,undefined,false,false
18821879
ion-textarea,prop,fill,"outline" | "solid" | undefined,undefined,false,false
@@ -1889,7 +1886,7 @@ ion-textarea,prop,minlength,number | undefined,undefined,false,false
18891886
ion-textarea,prop,mode,"ios" | "md",undefined,false,false
18901887
ion-textarea,prop,name,string,this.inputId,false,false
18911888
ion-textarea,prop,placeholder,string | undefined,undefined,false,false
1892-
ion-textarea,prop,readonly,boolean,false,false,false
1889+
ion-textarea,prop,readonly,boolean,false,false,true
18931890
ion-textarea,prop,required,boolean,false,false,false
18941891
ion-textarea,prop,rows,number | undefined,undefined,false,false
18951892
ion-textarea,prop,shape,"round" | undefined,undefined,false,false

core/src/components/textarea/textarea.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ export class Textarea implements ComponentInterface {
132132
/**
133133
* If `true`, the user cannot interact with the textarea.
134134
*/
135-
@Prop() disabled = false;
135+
@Prop({ reflect: true }) disabled = false;
136136

137137
/**
138138
* The fill for the item. If `"solid"` the item will have a background. If
@@ -177,7 +177,7 @@ export class Textarea implements ComponentInterface {
177177
/**
178178
* If `true`, the user cannot modify the value.
179179
*/
180-
@Prop() readonly = false;
180+
@Prop({ reflect: true }) readonly = false;
181181

182182
/**
183183
* If `true`, the user must fill in a value before submitting a form.

packages/angular/test/base/e2e/src/lazy/inputs.spec.ts

Lines changed: 116 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -5,105 +5,126 @@ test.describe('Inputs', () => {
55
await page.goto('/lazy/inputs');
66
});
77

8-
test('should have default values', async ({ page }) => {
9-
// Check primary elements for default values
10-
await expect(page.locator('ion-checkbox').first()).toHaveJSProperty('checked', true);
11-
await expect(page.locator('ion-radio-group').first()).toHaveJSProperty('value', 'nes');
12-
await expect(page.locator('ion-toggle').first()).toHaveJSProperty('checked', true);
13-
await expect(page.locator('ion-input').first()).toHaveJSProperty('value', 'some text');
14-
await expect(page.locator('ion-input-otp').first()).toHaveJSProperty('value', '1234');
15-
await expect(page.locator('ion-datetime').first()).toHaveJSProperty('value', '1994-03-15');
16-
await expect(page.locator('ion-select').first()).toHaveJSProperty('value', 'nes');
17-
await expect(page.locator('ion-range').first()).toHaveJSProperty('value', 50);
18-
});
8+
test.describe('basic functionality', () => {
9+
test('should have default values', async ({ page }) => {
10+
// Check primary elements for default values
11+
await expect(page.locator('ion-checkbox').first()).toHaveJSProperty('checked', true);
12+
await expect(page.locator('ion-radio-group').first()).toHaveJSProperty('value', 'nes');
13+
await expect(page.locator('ion-toggle').first()).toHaveJSProperty('checked', true);
14+
await expect(page.locator('ion-input').first()).toHaveJSProperty('value', 'some text');
15+
await expect(page.locator('ion-input-otp').first()).toHaveJSProperty('value', '1234');
16+
await expect(page.locator('ion-datetime').first()).toHaveJSProperty('value', '1994-03-15');
17+
await expect(page.locator('ion-select').first()).toHaveJSProperty('value', 'nes');
18+
await expect(page.locator('ion-range').first()).toHaveJSProperty('value', 50);
19+
});
1920

20-
test('should reset values', async ({ page }) => {
21-
await page.locator('#reset-button').click();
22-
23-
// Check primary elements after reset
24-
await expect(page.locator('ion-checkbox').first()).toHaveJSProperty('checked', false);
25-
await expect(page.locator('ion-radio-group').first()).toHaveJSProperty('value', undefined);
26-
await expect(page.locator('ion-toggle').first()).toHaveJSProperty('checked', false);
27-
/**
28-
* The `value` property gets set to undefined
29-
* for these components, so we need to check
30-
* that the value property is undefined.
31-
*/
32-
await expect(page.locator('ion-input').first()).toHaveJSProperty('value', undefined);
33-
await expect(page.locator('ion-input-otp').first()).toHaveJSProperty('value', undefined);
34-
await expect(page.locator('ion-datetime').first()).toHaveJSProperty('value', undefined);
35-
await expect(page.locator('ion-select').first()).toHaveJSProperty('value', undefined);
36-
await expect(page.locator('ion-range').first()).toHaveJSProperty('value', undefined);
37-
});
21+
test('should reset values', async ({ page }) => {
22+
await page.locator('#reset-button').click();
23+
24+
// Check primary elements after reset
25+
await expect(page.locator('ion-checkbox').first()).toHaveJSProperty('checked', false);
26+
await expect(page.locator('ion-radio-group').first()).toHaveJSProperty('value', undefined);
27+
await expect(page.locator('ion-toggle').first()).toHaveJSProperty('checked', false);
28+
/**
29+
* The `value` property gets set to undefined
30+
* for these components, so we need to check
31+
* that the value property is undefined.
32+
*/
33+
await expect(page.locator('ion-input').first()).toHaveJSProperty('value', undefined);
34+
await expect(page.locator('ion-input-otp').first()).toHaveJSProperty('value', undefined);
35+
await expect(page.locator('ion-datetime').first()).toHaveJSProperty('value', undefined);
36+
await expect(page.locator('ion-select').first()).toHaveJSProperty('value', undefined);
37+
await expect(page.locator('ion-range').first()).toHaveJSProperty('value', undefined);
38+
});
3839

39-
test('should set values', async ({ page }) => {
40-
await page.locator('#reset-button').click();
41-
await page.locator('#set-button').click();
42-
43-
// Check primary elements after setting values
44-
await expect(page.locator('ion-checkbox').first()).toHaveJSProperty('checked', true);
45-
await expect(page.locator('ion-radio-group').first()).toHaveJSProperty('value', 'nes');
46-
await expect(page.locator('ion-toggle').first()).toHaveJSProperty('checked', true);
47-
await expect(page.locator('ion-input').first()).toHaveJSProperty('value', 'some text');
48-
await expect(page.locator('ion-input-otp').first()).toHaveJSProperty('value', '1234');
49-
await expect(page.locator('ion-datetime').first()).toHaveJSProperty('value', '1994-03-15');
50-
await expect(page.locator('ion-select').first()).toHaveJSProperty('value', 'nes');
51-
await expect(page.locator('ion-range').first()).toHaveJSProperty('value', 50);
52-
});
40+
test('should set values', async ({ page }) => {
41+
await page.locator('#reset-button').click();
42+
await page.locator('#set-button').click();
43+
44+
// Check primary elements after setting values
45+
await expect(page.locator('ion-checkbox').first()).toHaveJSProperty('checked', true);
46+
await expect(page.locator('ion-radio-group').first()).toHaveJSProperty('value', 'nes');
47+
await expect(page.locator('ion-toggle').first()).toHaveJSProperty('checked', true);
48+
await expect(page.locator('ion-input').first()).toHaveJSProperty('value', 'some text');
49+
await expect(page.locator('ion-input-otp').first()).toHaveJSProperty('value', '1234');
50+
await expect(page.locator('ion-datetime').first()).toHaveJSProperty('value', '1994-03-15');
51+
await expect(page.locator('ion-select').first()).toHaveJSProperty('value', 'nes');
52+
await expect(page.locator('ion-range').first()).toHaveJSProperty('value', 50);
53+
});
5354

54-
test('should update angular when values change', async ({ page }) => {
55-
await page.locator('#reset-button').click();
56-
57-
await page.locator('ion-checkbox#first-checkbox').click();
58-
await page.locator('ion-radio').first().click();
59-
await page.locator('ion-toggle').first().click();
60-
61-
await page.locator('ion-input').nth(0).locator('input').fill('hola');
62-
await page.locator('ion-input').nth(0).locator('input').blur();
63-
64-
await page.locator('ion-input-otp input').nth(0).fill('1');
65-
await page.locator('ion-input-otp input').nth(1).fill('2');
66-
await page.locator('ion-input-otp input').nth(2).fill('3');
67-
await page.locator('ion-input-otp input').nth(3).fill('4');
68-
await page.locator('ion-input-otp input').nth(3).blur();
69-
70-
// Set date to 1994-03-14
71-
await page.locator('ion-datetime').first().click();
72-
await page.locator('ion-datetime').first().locator('.calendar-day:not([disabled])').first().click();
73-
74-
await page.locator('ion-select#game-console').click();
75-
await expect(page.locator('ion-alert')).toBeVisible();
76-
// Playstation option
77-
await page.locator('ion-alert .alert-radio-button').nth(3).click();
78-
// Click confirm button
79-
await page.locator('ion-alert .alert-button:not(.alert-button-role-cancel)').click();
80-
81-
// Check note text (Angular binding updates)
82-
await expect(page.locator('#checkbox-note')).toHaveText('true');
83-
await expect(page.locator('#radio-note')).toHaveText('nes');
84-
await expect(page.locator('#toggle-note')).toHaveText('true');
85-
await expect(page.locator('#input-note')).toHaveText('hola');
86-
await expect(page.locator('#input-otp-note')).toHaveText('1234');
87-
await expect(page.locator('#datetime-note')).toHaveText('1994-03-14');
88-
await expect(page.locator('#select-note')).toHaveText('ps');
89-
});
55+
test('should update angular when values change', async ({ page }) => {
56+
await page.locator('#reset-button').click();
9057

91-
test('should update values when erasing input', async ({ page }) => {
92-
// Focus the input and press backspace to remove last character
93-
await page.locator('ion-input').nth(0).locator('input').click();
94-
await page.locator('ion-input').nth(0).locator('input').press('Backspace');
95-
// Check mirror element reflects the change
96-
await expect(page.locator('ion-input').nth(1)).toHaveJSProperty('value', 'some tex');
97-
// Check note text (Angular binding)
98-
await expect(page.locator('#input-note')).toHaveText('some tex');
99-
100-
// Focus the last OTP input and press backspace
101-
await page.locator('ion-input-otp input').last().click();
102-
await page.locator('ion-input-otp input').last().press('Backspace');
103-
// Check mirror element reflects the change
104-
await expect(page.locator('ion-input-otp').nth(1)).toHaveJSProperty('value', '123');
105-
// Check note text (Angular binding)
106-
await expect(page.locator('#input-otp-note')).toHaveText('123');
58+
await page.locator('ion-checkbox#first-checkbox').click();
59+
await page.locator('ion-radio').first().click();
60+
await page.locator('ion-toggle').first().click();
61+
62+
await page.locator('ion-input').nth(0).locator('input').fill('hola');
63+
await page.locator('ion-input').nth(0).locator('input').blur();
64+
65+
await page.locator('ion-input-otp input').nth(0).fill('1');
66+
await page.locator('ion-input-otp input').nth(1).fill('2');
67+
await page.locator('ion-input-otp input').nth(2).fill('3');
68+
await page.locator('ion-input-otp input').nth(3).fill('4');
69+
await page.locator('ion-input-otp input').nth(3).blur();
70+
71+
// Set date to 1994-03-14
72+
await page.locator('ion-datetime').first().click();
73+
await page.locator('ion-datetime').first().locator('.calendar-day:not([disabled])').first().click();
74+
75+
await page.locator('ion-select#game-console').click();
76+
await expect(page.locator('ion-alert')).toBeVisible();
77+
// Playstation option
78+
await page.locator('ion-alert .alert-radio-button').nth(3).click();
79+
// Click confirm button
80+
await page.locator('ion-alert .alert-button:not(.alert-button-role-cancel)').click();
81+
82+
// Check note text (Angular binding updates)
83+
await expect(page.locator('#checkbox-note')).toHaveText('true');
84+
await expect(page.locator('#radio-note')).toHaveText('nes');
85+
await expect(page.locator('#toggle-note')).toHaveText('true');
86+
await expect(page.locator('#input-note')).toHaveText('hola');
87+
await expect(page.locator('#input-otp-note')).toHaveText('1234');
88+
await expect(page.locator('#datetime-note')).toHaveText('1994-03-14');
89+
await expect(page.locator('#select-note')).toHaveText('ps');
90+
});
91+
92+
test('should update values when erasing input', async ({ page }) => {
93+
// Focus the input and press backspace to remove last character
94+
await page.locator('ion-input').nth(0).locator('input').click();
95+
await page.locator('ion-input').nth(0).locator('input').press('Backspace');
96+
// Check mirror element reflects the change
97+
await expect(page.locator('ion-input').nth(1)).toHaveJSProperty('value', 'some tex');
98+
// Check note text (Angular binding)
99+
await expect(page.locator('#input-note')).toHaveText('some tex');
100+
101+
// Focus the last OTP input and press backspace
102+
await page.locator('ion-input-otp input').last().click();
103+
await page.locator('ion-input-otp input').last().press('Backspace');
104+
// Check mirror element reflects the change
105+
await expect(page.locator('ion-input-otp').nth(1)).toHaveJSProperty('value', '123');
106+
// Check note text (Angular binding)
107+
await expect(page.locator('#input-otp-note')).toHaveText('123');
108+
});
109+
110+
test('should reflect props when component has a default value', async ({ page }) => {
111+
// Disable inputs
112+
await page.locator('#disable-button').click();
113+
114+
// Disabled prop
115+
await expect(page.locator('ion-input').first()).toHaveAttribute('disabled', '');
116+
await expect(page.locator('ion-input-otp').first()).toHaveAttribute('disabled', '');
117+
await expect(page.locator('ion-textarea').first()).toHaveAttribute('disabled', '');
118+
119+
// Reset disabled state and set readonly state
120+
await page.locator('#disable-button').click();
121+
await page.locator('#readonly-button').click();
122+
123+
// Readonly prop
124+
await expect(page.locator('ion-input').first()).toHaveAttribute('readonly', '');
125+
await expect(page.locator('ion-input-otp').first()).toHaveAttribute('readonly', '');
126+
await expect(page.locator('ion-textarea').first()).toHaveAttribute('readonly', '');
127+
});
107128
});
108129

109130
test.describe('updating text input refs', () => {
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { test, expect } from '@playwright/test';
2+
3+
test.describe('Inputs', () => {
4+
test.beforeEach(async ({ page }) => {
5+
await page.goto('/standalone/inputs');
6+
});
7+
8+
test.describe('basic functionality', () => {
9+
test('should reflect props when component has a default value', async ({ page }) => {
10+
// Disable inputs
11+
await page.locator('#disable-button').click();
12+
13+
// Disabled prop
14+
await expect(page.locator('ion-input')).toHaveAttribute('disabled', '');
15+
await expect(page.locator('ion-input-otp')).toHaveAttribute('disabled', '');
16+
await expect(page.locator('ion-textarea')).toHaveAttribute('disabled', '');
17+
18+
// Reset disabled state and set readonly state
19+
await page.locator('#disable-button').click();
20+
await page.locator('#readonly-button').click();
21+
22+
// Readonly prop
23+
await expect(page.locator('ion-input')).toHaveAttribute('readonly', '');
24+
await expect(page.locator('ion-input-otp')).toHaveAttribute('readonly', '');
25+
await expect(page.locator('ion-textarea')).toHaveAttribute('readonly', '');
26+
});
27+
});
28+
});

0 commit comments

Comments
 (0)