Skip to content

fix(reorder-group): add children fallback for framework compatibility #30593

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Aug 5, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions core/src/components/reorder-group/reorder-group.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ export class ReorderGroup implements ComponentInterface {
const heights = this.cachedHeights;
heights.length = 0;
const el = this.el;
const children: any = el.__children;
const children: any = el.__children || el.children;
if (!children || children.length === 0) {
return;
}
Expand Down Expand Up @@ -259,7 +259,7 @@ export class ReorderGroup implements ComponentInterface {
private completeReorder(listOrReorder?: boolean | any[]): any {
const selectedItemEl = this.selectedItemEl;
if (selectedItemEl && this.state === ReorderGroupState.Complete) {
const children: any = this.el.__children;
const children: any = this.el.__children || this.el.children;
const len = children.length;
const toIndex = this.lastToIndex;
const fromIndex = indexForItem(selectedItemEl);
Expand Down Expand Up @@ -309,7 +309,7 @@ export class ReorderGroup implements ComponentInterface {
/********* DOM WRITE ********* */
private reorderMove(fromIndex: number, toIndex: number) {
const itemHeight = this.selectedItemHeight;
const children: any = this.el.__children;
const children: any = this.el.__children || this.el.children;
for (let i = 0; i < children.length; i++) {
const style = (children[i] as any).style;
let value = '';
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { expect } from '@playwright/test';
import { test } from '@playwright/test';
import { dragElementBy } from '../../utils/drag-utils';

test.describe('reorder-group: angular standalone', () => {
test('should reorder the items', async ({ page }) => {
await page.goto('/standalone/reorder-group');

// Get initial order
const initialItems = await page.locator('ion-item').allTextContents();
expect(initialItems).toEqual(['Item 1', 'Item 2', 'Item 3']);

const reorderGroup = page.locator('ion-reorder-group');

// Drag the first item down to move it to the end (below Item 3)
await dragElementBy(reorderGroup.locator('ion-reorder').first(), page, 0, 300);

// Wait for the reorder to complete
await page.waitForTimeout(500);

// Verify the new order - Item 1 should now be at the end
const finalItems = await page.locator('ion-item').allTextContents();
expect(finalItems).toEqual(['Item 2', 'Item 3', 'Item 1']);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export const routes: Routes = [
{ path: 'providers', loadComponent: () => import('../providers/providers.component').then(c => c.ProvidersComponent) },
{ path: 'overlay-controllers', loadComponent: () => import('../overlay-controllers/overlay-controllers.component').then(c => c.OverlayControllersComponent) },
{ path: 'button', loadComponent: () => import('../button/button.component').then(c => c.ButtonComponent) },
{ path: 'reorder-group', loadComponent: () => import('../reorder-group/reorder-group.component').then(c => c.ReorderGroupComponent) },
{ path: 'icon', loadComponent: () => import('../icon/icon.component').then(c => c.IconComponent) },
{ path: 'split-pane', redirectTo: '/standalone/split-pane/inbox', pathMatch: 'full' },
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@
Icon Test
</ion-label>
</ion-item>
<ion-item routerLink="/standalone/reorder-group">
<ion-label>
Reorder Group Test
</ion-label>
</ion-item>
</ion-list>

<ion-list>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { Component } from "@angular/core";
import { IonItem, IonLabel, IonReorder, IonReorderGroup } from '@ionic/angular/standalone';
import { ReorderEndCustomEvent } from "@ionic/angular";

@Component({
selector: 'app-reorder-group',
template: `
<ion-reorder-group disabled="false" (ionReorderEnd)="onReorderEnd($event)">
<ion-item>
<ion-reorder slot="end"></ion-reorder>
<ion-label>Item 1</ion-label>
</ion-item>
<ion-item>
<ion-reorder slot="end"></ion-reorder>
<ion-label>Item 2</ion-label>
</ion-item>
<ion-item>
<ion-reorder slot="end"></ion-reorder>
<ion-label>Item 3</ion-label>
</ion-item>
</ion-reorder-group>
`,
standalone: true,
imports: [IonItem, IonLabel, IonReorder, IonReorderGroup]
})
export class ReorderGroupComponent {
onReorderEnd(event: ReorderEndCustomEvent) {
if (event.detail.from !== event.detail.to) {
console.log('ionReorderEnd: Dragged from index', event.detail.from, 'to', event.detail.to);
} else {
console.log('ionReorderEnd: No position change occurred');
}

event.detail.complete();
}
}
2 changes: 2 additions & 0 deletions packages/react/test/base/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import IonPopoverNested from './pages/overlay-components/IonPopoverNested';
import KeepContentsMounted from './pages/overlay-components/KeepContentsMounted';
import OverlayComponents from './pages/overlay-components/OverlayComponents';
import OverlayHooks from './pages/overlay-hooks/OverlayHooks';
import ReorderGroup from './pages/ReorderGroup';

setupIonicReact();

Expand Down Expand Up @@ -67,6 +68,7 @@ const App: React.FC = () => (
<Route path="/tabs-direct-navigation" component={TabsDirectNavigation} />
<Route path="/icons" component={Icons} />
<Route path="/inputs" component={Inputs} />
<Route path="/reorder-group" component={ReorderGroup} />
</IonRouterOutlet>
</IonReactRouter>
</IonApp>
Expand Down
3 changes: 3 additions & 0 deletions packages/react/test/base/src/pages/Main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ const Main: React.FC<MainProps> = () => {
<IonItem routerLink="/inputs">
<IonLabel>Inputs</IonLabel>
</IonItem>
<IonItem routerLink="/reorder-group">
<IonLabel>Reorder Group</IonLabel>
</IonItem>
</IonList>
</IonContent>
</IonPage>
Expand Down
58 changes: 58 additions & 0 deletions packages/react/test/base/src/pages/ReorderGroup.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import React from 'react';
import {
IonBackButton,
IonButtons,
IonContent,
IonHeader,
IonItem,
IonLabel,
IonPage,
IonReorder,
IonReorderGroup,
IonTitle,
IonToolbar,
} from '@ionic/react';
import type { ReorderEndCustomEvent } from '@ionic/react';

const ReorderGroup: React.FC = () => {
const onReorderEnd = (event: ReorderEndCustomEvent) => {
if (event.detail.from !== event.detail.to) {
console.log('ionReorderEnd: Dragged from index', event.detail.from, 'to', event.detail.to);
} else {
console.log('ionReorderEnd: No position change occurred');
}

event.detail.complete();
};

return (
<IonPage>
<IonHeader>
<IonToolbar>
<IonButtons slot="start">
<IonBackButton></IonBackButton>
</IonButtons>
<IonTitle>Reorder Group</IonTitle>
</IonToolbar>
</IonHeader>
<IonContent>
<IonReorderGroup disabled={false} onIonReorderEnd={onReorderEnd}>
<IonItem>
<IonReorder slot="end"></IonReorder>
<IonLabel>Item 1</IonLabel>
</IonItem>
<IonItem>
<IonReorder slot="end"></IonReorder>
<IonLabel>Item 2</IonLabel>
</IonItem>
<IonItem>
<IonReorder slot="end"></IonReorder>
<IonLabel>Item 3</IonLabel>
</IonItem>
</IonReorderGroup>
</IonContent>
</IonPage>
);
};

export default ReorderGroup;
4 changes: 4 additions & 0 deletions packages/vue/test/base/src/router/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,10 @@ const routes: Array<RouteRecordRaw> = [
path: '/components/range',
component: () => import('@/views/Range.vue')
},
{
path: '/reorder-group',
component: () => import('@/views/ReorderGroup.vue')
},
{
path: '/nested',
component: () => import('@/views/RouterOutlet.vue'),
Expand Down
3 changes: 3 additions & 0 deletions packages/vue/test/base/src/views/Home.vue
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@
<ion-item router-link="/navigation" id="navigation">
<ion-label>Navigation</ion-label>
</ion-item>
<ion-item router-link="/reorder-group">
<ion-label>Reorder Group</ion-label>
</ion-item>
<ion-item router-link="/routing" id="routing">
<ion-label>Routing</ion-label>
</ion-item>
Expand Down
78 changes: 78 additions & 0 deletions packages/vue/test/base/src/views/ReorderGroup.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<template>
<ion-page>
<ion-header :translucent="true">
<ion-toolbar>
<ion-buttons slot="start">
<ion-back-button></ion-back-button>
</ion-buttons>
<ion-title>Reorder Group</ion-title>
</ion-toolbar>
</ion-header>

<ion-content :fullscreen="true">
<ion-reorder-group :disabled="false" @ion-reorder-end="onReorderEnd">
<ion-item>
<ion-reorder slot="end"></ion-reorder>
<ion-label>Item 1</ion-label>
</ion-item>
<ion-item>
<ion-reorder slot="end"></ion-reorder>
<ion-label>Item 2</ion-label>
</ion-item>
<ion-item>
<ion-reorder slot="end"></ion-reorder>
<ion-label>Item 3</ion-label>
</ion-item>
</ion-reorder-group>
</ion-content>
</ion-page>
</template>

<script lang="ts">
import {
IonButtons,
IonBackButton,
IonContent,
IonHeader,
IonItem,
IonLabel,
IonPage,
IonReorder,
IonReorderGroup,
IonTitle,
IonToolbar,
} from "@ionic/vue";
import { defineComponent } from "vue";
import type { ReorderEndCustomEvent } from "@ionic/vue";

export default defineComponent({
components: {
IonButtons,
IonBackButton,
IonContent,
IonHeader,
IonItem,
IonLabel,
IonPage,
IonReorder,
IonReorderGroup,
IonTitle,
IonToolbar,
},
setup() {
const onReorderEnd = (event: ReorderEndCustomEvent) => {
if (event.detail.from !== event.detail.to) {
console.log('ionReorderEnd: Dragged from index', event.detail.from, 'to', event.detail.to);
} else {
console.log('ionReorderEnd: No position change occurred');
}

event.detail.complete();
};

return {
onReorderEnd,
};
},
});
</script>
Loading