Saisie d’étiquettes pour Slint
KitTagInput · Slint Kit 0.3.0
Saisie de nouvelles étiquettes avec liste de puces contrôlée.

Essayer le composant
Télécharger le projet complet, le décompresser et lancer cargo run --locked dans son dossier. Rust 1.92+ ; Slint Kit 0.3.0 depuis crates.io. Vous pouvez aussi copier les quatre fichiers ci-dessous.
Tapez Research et appuyez sur Entrée pour ajouter une étiquette. Retirez une pastille avec sa croix ; Rust conserve des TagId stables.
ui/app.slint
export { KitFormValidation, HtmlInputKind, NumberInputFormat, KitInputConstraints, KitValidationResult, KitValidityState } from "@kit/kit.slint";
// SPDX-License-Identifier: GPL-3.0-or-later
import { KitTagInput, ChipRow, KitTheme, KitThemes } from "@kit/kit.slint";
export component App inherits Window {
title: "KitTagInput example";
preferred-width: 520px;
preferred-height: 300px;
max-width: 100000px;
max-height: 100000px;
background: root.theme.canvas;
in-out property <KitTheme> theme: KitThemes.light;
in property <[ChipRow]> chips;
in-out property <string> draft;
in property <string> error;
callback create(string);
callback remove(int);
VerticalLayout {
padding: 24px;
spacing: 16px;
alignment: start;
control := KitTagInput {
theme: root.theme; label: "Project tags"; chips: root.chips; text <=> root.draft; error: root.error;
create-requested(text) => { root.create(text); }
remove-requested(token) => { root.remove(token); }
}
result := Text { text: root.chips.length + (root.chips.length == 1 ? " tag" : " tags"); color: root.theme.text-primary; }
}
}
src/main.rs
// SPDX-License-Identifier: GPL-3.0-or-later
use slint::{ComponentHandle, ModelRc, VecModel};
use std::{cell::{Cell, RefCell}, rc::Rc};
mod ui { slint::include_modules!(); }
#[derive(Clone, Copy, PartialEq, Eq)]
struct TagId(i32);
#[derive(Clone)]
struct Tag { id: TagId, label: String }
fn publish(app: &ui::App, tags: &[Tag]) {
app.set_chips(ModelRc::new(VecModel::from(tags.iter().map(|tag| ui::ChipRow { token: tag.id.0, label: tag.label.as_str().into(), removable: true }).collect::<Vec<_>>())));
}
fn main() -> Result<(), slint::PlatformError> {
let app = ui::App::new()?;
slint_kit::init_form_validation!(ui, app);
let tags = Rc::new(RefCell::new(vec![Tag { id: TagId(1), label: "Design".into() }]));
let next = Cell::new(2_i32);
publish(&app, &tags.borrow());
let weak = app.as_weak();
let state = tags.clone();
app.on_create(move |draft| { if let Some(app) = weak.upgrade() {
let label = draft.trim();
if label.is_empty() || label.chars().count() > 40 { app.set_error("Use 1 to 40 characters".into()); return; }
if state.borrow().iter().any(|tag| tag.label == label) { app.set_error("Tag already exists".into()); return; }
let token = next.get();
next.set(token.checked_add(1).expect("tag identity capacity"));
state.borrow_mut().push(Tag { id: TagId(token), label: label.into() });
let snapshot = state.borrow().clone();
publish(&app, &snapshot); app.set_draft("".into()); app.set_error("".into());
} });
let weak = app.as_weak();
app.on_remove(move |token| { if let Some(app) = weak.upgrade() {
tags.borrow_mut().retain(|tag| tag.id != TagId(token));
let snapshot = tags.borrow().clone(); publish(&app, &snapshot);
} });
app.run()
}
Cargo.toml et build.rs
Cargo.toml
[package]
name = "slint-kit-tag-input-example"
version = "0.1.0"
edition = "2024"
rust-version = "1.92"
license = "GPL-3.0-or-later"
publish = false
[dependencies]
slint-kit = "=0.3.0"
slint = { version = "=1.18.1", default-features = false, features = ["std", "compat-1-18", "backend-winit", "renderer-skia", "accessibility"] }
[build-dependencies]
slint-kit-build = "=0.3.0"
[workspace]
build.rs
fn main() { slint_kit_build::compile("ui/app.slint").expect("compile component example"); }
Fichiers : Cargo.toml · build.rs · ui/app.slint · src/main.rs
Liez text, fournissez chips et traitez create-requested(string) pour valider puis créer une étiquette. Traitez remove-requested(token) pour retirer un élément existant.
Entrée transmet le brouillon au contrôleur sans ajouter de puce localement. Les erreurs restent visibles près de l’éditeur et les actions respectent FieldAccess.
Choisir entre une option intégrée et une composition personnalisée
Options partagées
label— propriété intégrée ; exemple de composition personnaliséerror— propriété intégrée ; exemple de composition personnalisé
Composition visuelle
Le fichier ci-dessous produit la capture. Pour les composants pilotés par un contrôleur, il montre l’état affiché sans fournir le branchement Rust. Créer un projet.
Afficher le fichier de la capture

// Public label overrides localize this fixture; toolkit/host defaults keep their language.
// SPDX-License-Identifier: GPL-3.0-or-later
import { KitTagInput, KitTheme, KitThemes } from "@kit/kit.slint";
export component Example inherits Window {
title: "KitTagInput — exemple";
preferred-width: 420px;
preferred-height: 220px;
max-width: 100000px;
max-height: 100000px;
background: root.theme.canvas;
in-out property <KitTheme> theme: KitThemes.light;
in-out property <string> status;
VerticalLayout {
padding: 24px; spacing: 16px; alignment: start;
Text { text: "Saisie d’étiquettes"; color: root.theme.text-primary; font-size: 20px * root.theme.text-scale; font-weight: 600; }
KitTagInput { theme: root.theme; label: "Étiquettes du projet"; chips: [{ token: 11, label: "Design", removable: true }, { token: 23, label: "Recherche", removable: true }]; text: ""; create-requested(value) => { root.status = "Créer une étiquette : " + value; } }
if root.status != "": Text { text: root.status; color: root.theme.text-secondary; font-size: 12px * root.theme.text-scale; wrap: word-wrap; }
}
}
API publique
Hérite de Rectangle.
Propriétés
| Nom | Type | Sens |
|---|---|---|
required |
bool |
in |
required-message |
string |
in |
custom-validity |
string |
in-out |
validity |
KitValidityState |
out |
will-validate |
bool |
out |
validation-message |
string |
out |
theme |
KitTheme |
in |
control-size |
ControlSize |
in |
access |
FieldAccess |
in |
chips |
[ChipRow] |
in |
label |
string |
in |
error |
string |
in |
text |
string |
in-out |
Types et variantes
| Type | Déclaration |
|---|---|
struct ChipRow |
token: int, label: string, removable: bool |
enum ControlSize |
compact, medium, comfortable |
enum FieldAccess |
editable, read-only, disabled |
struct KitValidityState |
valid: bool, value-missing: bool, type-mismatch: bool, pattern-mismatch: bool, too-long: bool, too-short: bool, range-underflow: bool, range-overflow: bool, step-mismatch: bool, bad-input: bool, custom-error: bool, |
Signaux
invalid()edited(string)create-requested(string)remove-requested(int)
Fonctions
check-validity() → boolreport-validity() → boolset-custom-validity(message: string)reset-validation()take-focus()