fix(core): detach SegmentedBar/TabView items from a previous parent before adopting them - #11353
Merged
Merged
Conversation
…ng them `onItemsChanged` adopted every new item with `_addView`, which throws "View already has a parent" when the item is still parented elsewhere. Nothing ever un-parents items: `disposeNativeView` leaves `items` untouched, so items keep pointing at a SegmentedBar even after it is destroyed. Binding one `SegmentedBarItem[]` to a SegmentedBar inside a ListView item template therefore crashed on the second cell, since every cell got a fresh bar bound to the same array. Items are now detached through `_removeView` before being adopted, so the item is properly unloaded and torn down and can be re-attached to the new parent's native visual tree.
`onItemsChanged` adopted every new item with `_addView`, which throws "View already has a parent" when the item is still parented elsewhere, and nothing ever un-parents items when a TabView is destroyed. Binding one `TabViewItem[]` array to more than one TabView therefore crashed. Items are now detached through `_removeView` before being adopted, so they are unloaded and torn down properly and can be re-attached to the new parent's native visual tree.
|
View your CI Pipeline Execution ↗ for commit 682aeba
💡 Verify your cache is correct by running tasks in a sandbox. Read docs ↗ ☁️ Nx Cloud last updated this comment at |
farfromrefug
approved these changes
Aug 17, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
PR Checklist
What is the current behavior?
SegmentedBarBase.onItemsChangedandTabViewBase.onItemsChangedadopt each new item by callingthis._addView(item), which throws when the item already has a parent:Nothing ever un-parents those items.
parentis only cleared by_removeView, and neither widget touches itsitemswhen it is destroyed —SegmentedBar.disposeNativeViewonly clears the tab listener / selection handler. So once aSegmentedBaris torn down, its items keep pointing at the dead bar forever.The practical consequence: a component that holds a
SegmentedBarItem[]field and binds it to aSegmentedBarinside aListViewitem template crashes.ListViewcreates a freshSegmentedBarper cell, all bound to the same array, so the second cell throws.Originally reported as NativeScript/nativescript-angular#900.
@nativescript/angularcurrently works around this in its renderer by reaching in and assigningitem.parent = undefinedon every array-valued binding. That bypasses_removeViewentirely, so_tearDownUI/_parentChangednever run and_contextstays set — which makes_setupUIhit itsthis._context === contextearly return, and the item is never added to the new parent's native visual tree. Fixing it here lets that workaround go away.What is the new behavior?
onItemsChangednow detaches an item from its previous parent through the public API before adopting it:Applied identically in
segmented-bar-common.tsandtab-view-common.ts(the latter keeps its existing "TabViewItem must have a view" check ahead of the detach). Because the detach goes through_removeView, the item is unloaded and torn down properly,_contextis cleared, and_addViewon the new parent can add it to the native visual tree.Re-binding a shared item array no longer throws, and the items end up parented to the widget they were last assigned to.
Known and accepted limitation
If the previous parent is still alive, this steals the item from it, and that parent's
itemsarray will still list the now-detached item. This is inherent: aViewhas exactly one parent, so sharing a single item array between two live hosts cannot work. The goal here is "don't crash, last binding wins", not multi-parent support.Tests
Added to
apps/automated/src/ui/segmented-bar/segmented-bar-tests.tsandapps/automated/src/ui/tab-view/tab-view-tests.ts:parentbecomes the second widget;item.parent = undefinedworkaround got wrong).All four new tests pass. The full
apps/automatedsuite was run on an iOS 26 simulator against bothmainand this branch: 1800 → 1804 passing, with an identical set of 12 pre-existingSAFEAREALAYOUT*_tab_bar_flatinset failures on both, so this change introduces no regressions.