Skip to content

Commit 1cd81b9

Browse files
fix(reorder-group): add children fallback for framework compatibility (#30593)
Issue number: resolves #30592 --------- ## What is the current behavior? Reorder group is failing for Angular, React & Vue due to the change from `children` to `__children`. ## What is the new behavior? - Fallback to `children` if `__children` is undefined. - Adds an e2e test for Angular (depends on #30594) - Tasks have been created to migrate and add e2e tests for the other frameworks ## Does this introduce a breaking change? - [ ] Yes - [x] No ## Other information Dev build: `8.7.2-dev.11754087334.1815cf22` --------- Co-authored-by: Brandy Smith <6577830+brandyscarney@users.noreply.github.com>
1 parent 05026c5 commit 1cd81b9

File tree

11 files changed

+218
-3
lines changed

11 files changed

+218
-3
lines changed

core/src/components/reorder-group/reorder-group.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ export class ReorderGroup implements ComponentInterface {
153153
const heights = this.cachedHeights;
154154
heights.length = 0;
155155
const el = this.el;
156-
const children: any = el.__children;
156+
const children: any = el.__children || el.children;
157157
if (!children || children.length === 0) {
158158
return;
159159
}
@@ -259,7 +259,7 @@ export class ReorderGroup implements ComponentInterface {
259259
private completeReorder(listOrReorder?: boolean | any[]): any {
260260
const selectedItemEl = this.selectedItemEl;
261261
if (selectedItemEl && this.state === ReorderGroupState.Complete) {
262-
const children: any = this.el.__children;
262+
const children: any = this.el.__children || this.el.children;
263263
const len = children.length;
264264
const toIndex = this.lastToIndex;
265265
const fromIndex = indexForItem(selectedItemEl);
@@ -309,7 +309,7 @@ export class ReorderGroup implements ComponentInterface {
309309
/********* DOM WRITE ********* */
310310
private reorderMove(fromIndex: number, toIndex: number) {
311311
const itemHeight = this.selectedItemHeight;
312-
const children: any = this.el.__children;
312+
const children: any = this.el.__children || this.el.children;
313313
for (let i = 0; i < children.length; i++) {
314314
const style = (children[i] as any).style;
315315
let value = '';
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { expect } from '@playwright/test';
2+
import { test } from '@playwright/test';
3+
import { dragElementBy } from '../../utils/drag-utils';
4+
5+
test.describe('reorder-group: angular standalone', () => {
6+
test('should reorder the items', async ({ page }) => {
7+
await page.goto('/standalone/reorder-group');
8+
9+
// Get initial order
10+
const initialItems = await page.locator('ion-item').allTextContents();
11+
expect(initialItems).toEqual(['Item 1', 'Item 2', 'Item 3']);
12+
13+
const reorderGroup = page.locator('ion-reorder-group');
14+
15+
// Drag the first item down to move it to the end (below Item 3)
16+
await dragElementBy(reorderGroup.locator('ion-reorder').first(), page, 0, 300);
17+
18+
// Wait for the reorder to complete
19+
await page.waitForTimeout(500);
20+
21+
// Verify the new order - Item 1 should now be at the end
22+
const finalItems = await page.locator('ion-item').allTextContents();
23+
expect(finalItems).toEqual(['Item 2', 'Item 3', 'Item 1']);
24+
});
25+
});

packages/angular/test/base/src/app/standalone/app-standalone/app.routes.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ export const routes: Routes = [
1919
{ path: 'providers', loadComponent: () => import('../providers/providers.component').then(c => c.ProvidersComponent) },
2020
{ path: 'overlay-controllers', loadComponent: () => import('../overlay-controllers/overlay-controllers.component').then(c => c.OverlayControllersComponent) },
2121
{ path: 'button', loadComponent: () => import('../button/button.component').then(c => c.ButtonComponent) },
22+
{ path: 'reorder-group', loadComponent: () => import('../reorder-group/reorder-group.component').then(c => c.ReorderGroupComponent) },
2223
{ path: 'icon', loadComponent: () => import('../icon/icon.component').then(c => c.IconComponent) },
2324
{ path: 'split-pane', redirectTo: '/standalone/split-pane/inbox', pathMatch: 'full' },
2425
{

packages/angular/test/base/src/app/standalone/home-page/home-page.component.html

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@
2828
Icon Test
2929
</ion-label>
3030
</ion-item>
31+
<ion-item routerLink="/standalone/reorder-group">
32+
<ion-label>
33+
Reorder Group Test
34+
</ion-label>
35+
</ion-item>
3136
</ion-list>
3237

3338
<ion-list>
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { Component } from "@angular/core";
2+
import { IonItem, IonLabel, IonReorder, IonReorderGroup } from '@ionic/angular/standalone';
3+
import { ReorderEndCustomEvent } from "@ionic/angular";
4+
5+
@Component({
6+
selector: 'app-reorder-group',
7+
template: `
8+
<ion-reorder-group disabled="false" (ionReorderEnd)="onReorderEnd($event)">
9+
<ion-item>
10+
<ion-reorder slot="end"></ion-reorder>
11+
<ion-label>Item 1</ion-label>
12+
</ion-item>
13+
<ion-item>
14+
<ion-reorder slot="end"></ion-reorder>
15+
<ion-label>Item 2</ion-label>
16+
</ion-item>
17+
<ion-item>
18+
<ion-reorder slot="end"></ion-reorder>
19+
<ion-label>Item 3</ion-label>
20+
</ion-item>
21+
</ion-reorder-group>
22+
`,
23+
standalone: true,
24+
imports: [IonItem, IonLabel, IonReorder, IonReorderGroup]
25+
})
26+
export class ReorderGroupComponent {
27+
onReorderEnd(event: ReorderEndCustomEvent) {
28+
if (event.detail.from !== event.detail.to) {
29+
console.log('ionReorderEnd: Dragged from index', event.detail.from, 'to', event.detail.to);
30+
} else {
31+
console.log('ionReorderEnd: No position change occurred');
32+
}
33+
34+
event.detail.complete();
35+
}
36+
}

packages/react/test/base/src/App.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import IonPopoverNested from './pages/overlay-components/IonPopoverNested';
3636
import KeepContentsMounted from './pages/overlay-components/KeepContentsMounted';
3737
import OverlayComponents from './pages/overlay-components/OverlayComponents';
3838
import OverlayHooks from './pages/overlay-hooks/OverlayHooks';
39+
import ReorderGroup from './pages/ReorderGroup';
3940

4041
setupIonicReact();
4142

@@ -67,6 +68,7 @@ const App: React.FC = () => (
6768
<Route path="/tabs-direct-navigation" component={TabsDirectNavigation} />
6869
<Route path="/icons" component={Icons} />
6970
<Route path="/inputs" component={Inputs} />
71+
<Route path="/reorder-group" component={ReorderGroup} />
7072
</IonRouterOutlet>
7173
</IonReactRouter>
7274
</IonApp>

packages/react/test/base/src/pages/Main.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ const Main: React.FC<MainProps> = () => {
4646
<IonItem routerLink="/inputs">
4747
<IonLabel>Inputs</IonLabel>
4848
</IonItem>
49+
<IonItem routerLink="/reorder-group">
50+
<IonLabel>Reorder Group</IonLabel>
51+
</IonItem>
4952
</IonList>
5053
</IonContent>
5154
</IonPage>
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import React from 'react';
2+
import {
3+
IonBackButton,
4+
IonButtons,
5+
IonContent,
6+
IonHeader,
7+
IonItem,
8+
IonLabel,
9+
IonPage,
10+
IonReorder,
11+
IonReorderGroup,
12+
IonTitle,
13+
IonToolbar,
14+
} from '@ionic/react';
15+
import type { ReorderEndCustomEvent } from '@ionic/react';
16+
17+
const ReorderGroup: React.FC = () => {
18+
const onReorderEnd = (event: ReorderEndCustomEvent) => {
19+
if (event.detail.from !== event.detail.to) {
20+
console.log('ionReorderEnd: Dragged from index', event.detail.from, 'to', event.detail.to);
21+
} else {
22+
console.log('ionReorderEnd: No position change occurred');
23+
}
24+
25+
event.detail.complete();
26+
};
27+
28+
return (
29+
<IonPage>
30+
<IonHeader>
31+
<IonToolbar>
32+
<IonButtons slot="start">
33+
<IonBackButton></IonBackButton>
34+
</IonButtons>
35+
<IonTitle>Reorder Group</IonTitle>
36+
</IonToolbar>
37+
</IonHeader>
38+
<IonContent>
39+
<IonReorderGroup disabled={false} onIonReorderEnd={onReorderEnd}>
40+
<IonItem>
41+
<IonReorder slot="end"></IonReorder>
42+
<IonLabel>Item 1</IonLabel>
43+
</IonItem>
44+
<IonItem>
45+
<IonReorder slot="end"></IonReorder>
46+
<IonLabel>Item 2</IonLabel>
47+
</IonItem>
48+
<IonItem>
49+
<IonReorder slot="end"></IonReorder>
50+
<IonLabel>Item 3</IonLabel>
51+
</IonItem>
52+
</IonReorderGroup>
53+
</IonContent>
54+
</IonPage>
55+
);
56+
};
57+
58+
export default ReorderGroup;

packages/vue/test/base/src/router/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,10 @@ const routes: Array<RouteRecordRaw> = [
8686
path: '/components/range',
8787
component: () => import('@/views/Range.vue')
8888
},
89+
{
90+
path: '/reorder-group',
91+
component: () => import('@/views/ReorderGroup.vue')
92+
},
8993
{
9094
path: '/nested',
9195
component: () => import('@/views/RouterOutlet.vue'),

packages/vue/test/base/src/views/Home.vue

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@
2929
<ion-item router-link="/navigation" id="navigation">
3030
<ion-label>Navigation</ion-label>
3131
</ion-item>
32+
<ion-item router-link="/reorder-group">
33+
<ion-label>Reorder Group</ion-label>
34+
</ion-item>
3235
<ion-item router-link="/routing" id="routing">
3336
<ion-label>Routing</ion-label>
3437
</ion-item>

0 commit comments

Comments
 (0)