mirror of
https://github.com/Textualize/textual.git
synced 2025-10-17 02:38:12 +03:00
queries docs
This commit is contained in:
67
docs/guide/queries.md
Normal file
67
docs/guide/queries.md
Normal file
@@ -0,0 +1,67 @@
|
||||
# DOM Queries
|
||||
|
||||
In the previous chapter we introduced the [DOM](../guide/CSS.md#the-dom), which represents the widgets in a Textual app. We saw how you can apply styles to the DOM with CSS *selectors*.
|
||||
|
||||
Selectors are a very useful thing and can do more that apply styles. We can also modify widgets using selectors in a simple expressive way. Let's look at how!
|
||||
|
||||
## Making queries
|
||||
|
||||
Apps and widgets have a [query][textual.dom.DOMNode.query] method which finds (or queries) widgets. Calling this method will return a [DOMQuery][textual.css.query.DOMQuery] object which is a container (list-like) object with widgets you may iterate over.
|
||||
|
||||
If you call `query` with no arguments, you will get back a `DOMQuery` containing all widgets. This method is *recursive*, meaning it will return all child widgets.
|
||||
|
||||
Here's how you might iterate over all the widgets in your app:
|
||||
|
||||
```python
|
||||
for widget in self.query():
|
||||
print(widget)
|
||||
```
|
||||
|
||||
Called on the `app`, this will retrieve all widgets in the app. If you call the same method on a widget, it will return children of that widget.
|
||||
|
||||
### Query selectors
|
||||
|
||||
You can also call `query` with a CSS selector. Let's look a few examples:
|
||||
|
||||
If we want to find all the button widgets, we could do something like the following:
|
||||
|
||||
```python
|
||||
for button in self.query("Button"):
|
||||
print(button)
|
||||
```
|
||||
|
||||
Any selector that works in CSS will work. For instance, if we want to find all the disabled buttons in a Dialog widget, we could do something like the following:
|
||||
|
||||
```python
|
||||
for button in self.query("Dialog > Button.disabled"):
|
||||
print(button)
|
||||
```
|
||||
|
||||
### First and Last
|
||||
|
||||
The [first][textual.css.query.DOMQuery.first] and [last][textual.css.query.DOMQuery.last] methods will return the first and last widgets from the selector, respectively.
|
||||
|
||||
Here's how we might find the last button in an app.
|
||||
|
||||
```python
|
||||
last_button = self.query("Button").last()
|
||||
```
|
||||
|
||||
If there are no buttons, textual will raise a [NoMatchingNodesError][textual.css.query.NoMatchingNodesError] exception. Otherwise it will return a button widgets.
|
||||
|
||||
Both `first()` and `last()` accept an `expect_type` argument that should be the class of the widget you are expecting. For instance, lets say we want to get the last with class `.disabled`, and we want to check it really is a button. We could do this:
|
||||
|
||||
```python
|
||||
disabled_button = self.query(".disables").last(Button)
|
||||
```
|
||||
|
||||
The query selects all widgets with a `disabled` CSS class. The `last` method ensures that it is a `Button` and not any other kind of widget.
|
||||
|
||||
If the last widget is *not* a button, Textual will raise a [WrongType][textual.css.query.WrongType] exception.
|
||||
|
||||
!!! tip
|
||||
|
||||
Specifying the expected type allows type-checkers like MyPy to know the exact return type.
|
||||
|
||||
### Filtering
|
||||
|
||||
@@ -1 +1 @@
|
||||
::: textual.css.query.DOMQuery
|
||||
::: textual.css.query
|
||||
|
||||
@@ -14,6 +14,7 @@ nav:
|
||||
- "guide/app.md"
|
||||
- "guide/styles.md"
|
||||
- "guide/CSS.md"
|
||||
- "guide/queries.md"
|
||||
- "guide/layout.md"
|
||||
- "guide/events.md"
|
||||
- "guide/input.md"
|
||||
|
||||
@@ -31,15 +31,15 @@ if TYPE_CHECKING:
|
||||
|
||||
|
||||
class QueryError(Exception):
|
||||
pass
|
||||
"""Base class for a query related error."""
|
||||
|
||||
|
||||
class NoMatchingNodesError(QueryError):
|
||||
pass
|
||||
"""No nodes matched the query."""
|
||||
|
||||
|
||||
class WrongType(QueryError):
|
||||
pass
|
||||
"""Query result was not of the correct type."""
|
||||
|
||||
|
||||
QueryType = TypeVar("QueryType", bound="Widget")
|
||||
@@ -172,7 +172,7 @@ class DOMQuery(Generic[QueryType]):
|
||||
def first(
|
||||
self, expect_type: type[ExpectType] | None = None
|
||||
) -> QueryType | ExpectType:
|
||||
"""Get the *first* match node.
|
||||
"""Get the *first* matching node.
|
||||
|
||||
Args:
|
||||
expect_type (type[ExpectType] | None, optional): Require matched node is of this type,
|
||||
@@ -207,7 +207,7 @@ class DOMQuery(Generic[QueryType]):
|
||||
def last(
|
||||
self, expect_type: type[ExpectType] | None = None
|
||||
) -> QueryType | ExpectType:
|
||||
"""Get the *last* match node.
|
||||
"""Get the *last* matching node.
|
||||
|
||||
Args:
|
||||
expect_type (type[ExpectType] | None, optional): Require matched node is of this type,
|
||||
|
||||
Reference in New Issue
Block a user