Skip to content

Commit c360903

Browse files
authored
Merge pull request #6268 from Textualize/early-loading
fix early loading issue
2 parents ad8b428 + 4471d45 commit c360903

File tree

3 files changed

+31
-2
lines changed

3 files changed

+31
-2
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1111

1212
- Added `Content.blank` https://github.com/Textualize/textual/pull/6264
1313

14+
### Fixed
15+
16+
- Fixed exception when setting `loading` attribute before mount https://github.com/Textualize/textual/pull/6268
17+
1418
## [6.7.1] - 2025-12-1
1519

1620
### Fixed

src/textual/widget.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1035,7 +1035,10 @@ def set_loading(self, loading: bool) -> None:
10351035

10361036
def _watch_loading(self, loading: bool) -> None:
10371037
"""Called when the 'loading' reactive is changed."""
1038-
self.set_loading(loading)
1038+
if not self.is_mounted:
1039+
self.call_later(self.set_loading, loading)
1040+
else:
1041+
self.set_loading(loading)
10391042

10401043
ExpectType = TypeVar("ExpectType", bound="Widget")
10411044

tests/test_loading.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from textual.app import App, ComposeResult
22
from textual.containers import VerticalScroll
3-
from textual.widgets import Label
3+
from textual.widgets import Label, Static
44

55

66
class LoadingApp(App[None]):
@@ -31,3 +31,25 @@ async def test_loading_disables_and_remove_scrollbars():
3131
await pilot.pause()
3232

3333
assert vs._check_disabled()
34+
35+
36+
async def test_premature_loading():
37+
"""Test a widget can set the `loading` attribute before mounting."""
38+
39+
# No assert, we're just expecting it to not crash
40+
41+
class LoadingWidget(Static):
42+
"""A widget that shows a loading indicator."""
43+
44+
class LoadingApp(App[None]):
45+
"""Simple app with a single loading widget."""
46+
47+
def compose(self) -> ComposeResult:
48+
"""Compose the app with the loading widget."""
49+
widget = LoadingWidget("Loading content...")
50+
widget.loading = True # Should not crash
51+
yield widget
52+
53+
app = LoadingApp()
54+
async with app.run_test() as pilot:
55+
await pilot.pause()

0 commit comments

Comments
 (0)