# File picker

> A path field with a button that opens the system's file or folder dialog. A Pyzed component for Python desktop GUIs, with examples and its API.

Source: https://albakore.github.io/pyzed/library/file-input/

:::tip[In plain words]
A box with the location of a file and a button that opens the usual window to look for it.
:::

`ui.file_input` shows a path and a browse button. The button opens the operating system's own dialog to open a file (`mode="open"`), several (`"open_many"`), a folder (`"folder"`) or to choose where to save (`"save"`), and `on_change` receives what the user chose: a path, or a list of paths with `open_many`. The path can also be typed or pasted. `filters` limits the file types (`"Images: png, jpg"`).

`ui.file_input` · Category: [System](https://albakore.github.io/pyzed/library/#system) · [Full reference →](https://albakore.github.io/pyzed/reference/ui/#file_input)

**Code:**

```python
pz.column([
    ui.field("Project folder", ui.file_input("~/projects/notes", on_change, mode="folder")),
    ui.field("Logo", ui.file_input("", on_change, filters="Images: png, jpg, svg", placeholder="Choose an image")),
    ui.field("Export to", ui.file_input("report.pdf", on_change, mode="save", button="Browse…")),
], spacing=12, width=420)
```

:::note[New]
This component was added recently. Tell us how it works for you in the [issue tracker](https://github.com/albakore/pyzed/issues).
:::

## When to use

- For settings that point to a file or folder: a project folder, a log file, an export target.
- `button="Browse…"` shows text instead of the folder icon.
- `ui.system.pick(then, mode=...)` returns the same dialog as a `Command`, for your own buttons.

## Usage

```python
import pyzed as pz
from pyzed import ui

class Export(pz.App):
    def __init__(self):
        self.target = ""

    def view(self):
        return ui.file_input(self.target, lambda path: setattr(self, "target", path),
                             mode="save", file_name="report.pdf", filters="PDF: pdf")
```

## Variants

:::note[About these captures]
Each capture is recorded by pyzed itself, off-screen at 2x, in One Dark or One Light to match this site's theme, and cropped to the component so it shows at its real size. The pointer hovers, presses or types into it; a component that does not react to the pointer cycles through a few themes. With reduced motion you see the first frame. Open **Code** under a capture to see the snippet that draws it; free names such as `on_save` stand for your own callbacks.
:::

### Mode

```python
ui.file_input("~/notes/todo.md", on_change, width=320)
```

```python
ui.file_input(["a.png", "b.png"], on_change, mode="open_many", width=320)
```

```python
ui.file_input("~/projects", on_change, mode="folder", width=320)
```

```python
ui.file_input("report.pdf", on_change, mode="save", width=320)
```

### States

```python
ui.file_input("", on_change, button="Browse…", width=320)
```

```python
ui.file_input("~/notes/todo.md", on_change, editable=False, width=320)
```

```python
ui.file_input("~/missing.txt", on_change, invalid=True, width=320)
```

```python
ui.file_input("~/notes/todo.md", on_change, disabled=True, width=320)
```

## Events

File picker has **1 event of its own**, listed below. Like every widget it also has the **18 common events** (`click`, `double_click`, `right_click`, `mouse_enter`, `drag`, `key_down`, `resize`…), attached with `.on(...)`: see [Events](https://albakore.github.io/pyzed/guides/events/) and [Events of every component](https://albakore.github.io/pyzed/library/events/).

| Event | Of | Handler gets | When |
| --- | --- | --- | --- |
| `on_change` | `ui.file_input`, `ui.path_input` | `(value)` | Receives the path (a list with `"open_many"`). |

**Handler gets** is what Pyzed passes to your callable: `()` means nothing. Any handler can also be a message (a value that is not callable), which goes to `update()`.

### Handling the events

The same events written three ways. **Imperative**: methods of the app change `self`. **Declarative**: the handlers produce messages and one `update()` decides. **Functional**: a pure function draws an immutable state and asks for changes with `set_state(...)`. See [Imperative, declarative and functional](https://albakore.github.io/pyzed/guides/code-styles/).

**Imperative:**

```python
class Export(pz.App):
    def __init__(self):
        self.folder = ""

    def chosen(self, path):              # on_change: the path (a list with mode="open_many")
        self.folder = path

    def view(self):
        return pz.column([
            ui.file_input(self.folder, self.chosen, mode="folder", placeholder="Choose a folder"),
            ui.label(f"Saving to {self.folder or '…'}"),
        ], spacing=8, width=360)
```

**Declarative:**

```python
from dataclasses import dataclass

@dataclass
class Chosen:
    path: str

class Export(pz.App):
    path = ""

    def update(self, message):
        match message:
            case Chosen(path):
                self.path = path

    def view(self):
        return ui.file_input(self.path, lambda path: Chosen(path), mode="save", file_name="report.pdf")
```

**Functional:**

```python
from dataclasses import dataclass

@dataclass(frozen=True)
class State:
    image: str = ""

def view(state, set_state):
    return ui.file_input(state.image, lambda path: set_state(image=path), filters="Images: png, jpg")
```

## Properties and API

### `ui.file_input`

```python
file_input(
    value,
    on_change=None,
    *,
    mode='open',
    filters=None,
    title=None,
    directory=None,
    file_name='',
    placeholder=None,
    button=None,
    editable=True,
    disabled=False,
    invalid=False,
    id=None,
    width='fill',
    theme=None,
)
```

A path field with a button that opens the system's file dialog, so nobody types a path by hand. See the [File picker](https://albakore.github.io/pyzed/library/file-input/) page.

| Property | Default | Description |
| --- | --- | --- |
| `value` | *required* | Current value. |
| `mode` | `"open"` | `"open"` (a file), `"open_many"` (a list), `"save"` or `"folder"`. |
| `filters` | `None` | Files shown: `{"Images": "png jpg"}` or `"Images: png, jpg"`. |
| `title` | `None` | The dialog's title. |
| `directory` | `None` | Where the dialog opens (default: the folder of the current path). |
| `file_name` | `""` | The name suggested when saving. |
| `placeholder` | `None` | Hint text shown when empty. |
| `button` | `None` | Text for the button instead of a folder icon. |
| `editable` | `True` | `False` keeps the path from being typed. |
| `disabled` | `False` | Disables it (ignores clicks). |
| `invalid` | `False` | Paints the border in the error color. |
| `id` | `None` | Stable identifier used to focus or scroll it with a `Command`. |
| `width` | `"fill"` | Width: pixels, `"fill"`, `"shrink"` or `"fill:N"` (proportion). |
| `theme` | `None` | Theme to use instead of the current one (`pyzed.theme.current()`). |

Events: `on_change` ([events](#events)).

[Full reference →](https://albakore.github.io/pyzed/reference/ui/#file_input)

### `ui.path_input`

```python
path_input(
    value,
    on_change=None,
    *,
    folder=False,
    save=False,
    filters=None,
    kind=None,
    directory=None,
    relative_to=None,
    title=None,
    placeholder=None,
    size='md',
    mono=True,
    disabled=False,
    invalid=False,
    theme=None,
)
```

A text field for a file or folder path with a button that opens the system's file dialog, so the path never has to be typed (it still can be).

| Property | Default | Description |
| --- | --- | --- |
| `value` | *required* | Current path. |
| `folder` | `False` | Picks a folder instead of a file. |
| `save` | `False` | Shows the "Save as" dialog. |
| `filters` | `None` | `(name, extensions)` pairs: `[("Images", ["png", "jpg"])]`. |
| `kind` | `None` | Common filters by name: `"image"`, `"audio"`, `"video"`, `"font"`, `"shader"` or `"data"`. |
| `directory` | `None` | Folder the dialog opens in (by default, the current path's). |
| `relative_to` | `None` | A chosen path inside this folder is given relative to it. |
| `title` | `None` | Title of the dialog. |
| `placeholder` | `None` | Text shown while it is empty. |
| `size` | `"md"` | `"sm"`, `"md"` or `"lg"`. |
| `mono` | `True` | Monospaced text. |
| `disabled` | `False` | Greys it out. |
| `invalid` | `False` | Paints the border in the error color. |
| `theme` | `None` | Theme to use instead of the current one (`pyzed.theme.current()`). |

Events: `on_change` ([events](#events)).

[Full reference →](https://albakore.github.io/pyzed/reference/ui/#path_input)

### `ui.system.pick`

```python
pick(then, *, mode='open', title=None, filters=None, directory=None, file_name='')
```

The system's file dialog as a `Command`: return it from a callback and `then` receives what the user chose (a path, a list of paths with `"open_many"`, or `None` when they cancel). `ui.file_input` uses it.

| Property | Default | Description |
| --- | --- | --- |
| `then` | *required* | Called with the result. |
| `mode` | `"open"` | `"open"`, `"open_many"`, `"save"` or `"folder"`. |
| `title` | `None` | The dialog's title. |
| `filters` | `None` | Files shown: `{"Images": "png jpg"}` or `"Images: png, jpg"`. |
| `directory` | `None` | Where the dialog opens. |
| `file_name` | `""` | The name suggested when saving. |

[Full reference →](https://albakore.github.io/pyzed/reference/ui/#pick)

## Related

- [Drop zone](https://albakore.github.io/pyzed/library/drop-zone/): An area that takes files dragged from the desktop or the file manager.
- [Input](https://albakore.github.io/pyzed/library/input/): A controlled text field with icon, placeholder and password mode.
- [Field](https://albakore.github.io/pyzed/library/field/): A settings row: title and description left, control right.
