Skip to content

bug: When dynamically updating the <ion-item> within the <ion-radio-group>, you encounter the error "NotFoundError: Failed to execute 'insertBefore' on 'Node': The node before which the new node is to be inserted is not a child of this node." #30343

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

Closed
3 tasks done
fcl999 opened this issue Apr 8, 2025 · 6 comments
Labels
ionitron: needs reproduction a code reproduction is needed from the issue author

Comments

@fcl999
Copy link

fcl999 commented Apr 8, 2025

Prerequisites

Ionic Framework Version

v8.x

Current Behavior

ionic v8.5.1
An error occurs when using v-for to render within , and an error also occurs when performing hot updates on child nodes.

<template>
  <ion-radio-group v-model="selectedUnitId" allow-empty-selection="true">
    <ion-item v-for="unit in units" :key="unit.id">
      <ion-radio :value="unit.id" label-placement="end" justify="start">
        {{ unit.name }}
      </ion-radio>
    </ion-item>
  </ion-radio-group>
</template>

<script setup>
import { ref, onMounted } from "vue";
const selectedUnitId = ref("");
// const units = ref([
//   { id: 1, name: "111" },
//   { id: 2, name: "222" },
// ]);
const units = ref([])

onMounted(() => {
  setTimeout(() => {
    units.value = [
      { id: 1, name: "111" },
      { id: 2, name: "222" },
    ];
  }, 5000);
});
</script>


Expected Behavior

not error

Steps to Reproduce

Run

Code Reproduction URL

look Current Behavior

Ionic Info

[WARN] Multi-app workspace detected, but cannot determine which project to use.

   Please set a defaultProject in .\ionic.config.json or specify the project using the global --project option.
   Read the documentation[1] for more information.
   
   [1]: https://ion.link/multi-app-docs

Ionic:

Ionic CLI : 7.2.1 (C:\Users\Admin\AppData\Local\pnpm\global\5.pnpm@[email protected]\node_modules@ionic\cli)

Utility:

cordova-res : not installed globally
native-run : not installed globally

System:

NodeJS : v18.16.1 (C:\Program Files\nodejs\node.exe)
npm : 9.5.1
OS : Windows 10

Additional Information

No response

@ionitron-bot ionitron-bot bot added the triage label Apr 8, 2025
@gitMarksa
Copy link

+1

@thetaPC
Copy link
Contributor

thetaPC commented Apr 8, 2025

Thank you for submitting the issue!

Unfortunately, I was unable to reproduce this in the latest version and on v8.5.1. Please include a minimal repro for us to proceed.

@thetaPC thetaPC added the ionitron: needs reproduction a code reproduction is needed from the issue author label Apr 8, 2025
Copy link

ionitron-bot bot commented Apr 8, 2025

Thanks for the issue! This issue has been labeled as needs reproduction. This label is added to issues that need a code reproduction.

Please reproduce this issue in an Ionic starter application and provide a way for us to access it (GitHub repo, StackBlitz, etc). Without a reliable code reproduction, it is unlikely we will be able to resolve the issue, leading to it being closed.

If you have already provided a code snippet and are seeing this message, it is likely that the code snippet was not enough for our team to reproduce the issue.

For a guide on how to create a good reproduction, see our Contributing Guide.

@ionitron-bot ionitron-bot bot removed the triage label Apr 8, 2025
@fcl999
Copy link
Author

fcl999 commented Apr 9, 2025

ionic.zip

Image

@thetaPC
Copy link
Contributor

thetaPC commented Apr 9, 2025

I was able to determine that the issue is coming from the setTimeout and how Vue renders. I was able to solve it through two solutions.

Solution 1: causes a re-render on the radio group

<template>
  <ion-app mode="ios">
    <ion-page>
      <ion-header>
        <ion-toolbar>
          <ion-title>test</ion-title>
        </ion-toolbar>
      </ion-header>
      <ion-content>
        <ion-radio-group v-model="selectedUnitId" allow-empty-selection="true" :key="radioGroupKey">
          <ion-item v-for="unit in units" :key="unit.id">
            <ion-radio :value="unit.id">{{ unit.name }}</ion-radio>
          </ion-item>
        </ion-radio-group>
      </ion-content>
    </ion-page>
  </ion-app>
</template>

<script setup lang="ts">
  import {
    IonApp,
    IonContent,
    IonHeader,
    IonItem,
    IonRadioGroup,
    IonRadio,
    IonPage,
    IonTitle,
    IonToolbar,
  } from "@ionic/vue";

  import { ref, onMounted } from "vue";

  const radioGroupKey = ref(0);
  const selectedUnitId = ref("");
  const units = ref([
    { id: 1, name: "111" },
    { id: 2, name: "222" },
  ]);
  onMounted(() => {
    console.log("onMounted");
    setTimeout(() => {
      units.value = [
        { id: 1, name: "111" },
        { id: 2, name: "222" },
        { id: 3, name: "333" },
        { id: 4, name: "333" },
      ];
      radioGroupKey.value++; // Trigger re-render only for the ion-radio-group
    }, 5000);
  });
</script>

Solution 2: Uses the Traditional Composition API setup

<template>
  <ion-app mode="ios">
    <ion-page>
      <ion-header>
        <ion-toolbar>
          <ion-title>test</ion-title>
        </ion-toolbar>
      </ion-header>
      <ion-content>
        <ion-radio-group v-model="selectedUnitId" allow-empty-selection="true">
          <ion-item v-for="unit in units" :key="unit.id">
            <ion-radio :value="unit.id" label-placement="end" justify="start">
              {{ unit.name }}
            </ion-radio>
          </ion-item>
        </ion-radio-group>
      </ion-content>
    </ion-page>
  </ion-app>
</template>

<script lang="ts">
import { IonRadio, IonRadioGroup, IonItem, IonTitle, IonToolbar, IonHeader, IonContent, IonPage, IonApp } from '@ionic/vue';
import { defineComponent, ref, onMounted } from 'vue';

export default defineComponent({
  components: { IonRadio, IonRadioGroup, IonItem, IonTitle, IonToolbar, IonHeader, IonContent, IonPage, IonApp },
  setup() {
    const selectedUnitId = ref<string | null>(null);
    const units = ref([
      { id: 1, name: "111" },
      { id: 2, name: "222" },
    ]);

    onMounted(() => {
      console.log('Component mounted!');
      units.value = [
        { id: 1, name: "111" },
        { id: 2, name: "222" },
        { id: 3, name: "333" },
        { id: 4, name: "333" },
      ];
    });

    return {
      selectedUnitId,
      units,
    };
  }
});
</script>

I'll be closing this issue as it's not related to the Ionic Framework. Thanks!

Copy link

ionitron-bot bot commented May 9, 2025

Thanks for the issue! This issue is being locked to prevent comments that are not relevant to the original issue. If this is still an issue with the latest version of Ionic, please create a new issue and ensure the template is fully filled out.

@ionitron-bot ionitron-bot bot locked and limited conversation to collaborators May 9, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
ionitron: needs reproduction a code reproduction is needed from the issue author
Projects
None yet
Development

No branches or pull requests

3 participants