Files

68 lines
1.9 KiB
Cheetah

---
description: "GetX conventions for {{PROJECT_NAME}} (legacy — migration available)"
alwaysApply: true
---
# GetX Standards — {{PROJECT_NAME}}
> ⚠️ This project uses GetX. See `migration-agent` for incremental migration to Riverpod.
## Controller structure
```dart
class ProductsController extends GetxController {
final ProductRepository _repo;
ProductsController(this._repo);
final RxList<Product> products = <Product>[].obs;
final RxBool isLoading = false.obs;
final Rx<String?> error = Rx(null);
@override
void onInit() {
super.onInit();
fetchProducts();
}
Future<void> fetchProducts() async {
isLoading.value = true;
error.value = null;
try {
products.value = await _repo.getProducts();
} catch (e) {
error.value = e.toString();
} finally {
isLoading.value = false;
}
}
}
```
## View pattern
```dart
// Views extend GetView<Controller> — never GetWidget or raw StatelessWidget
class ProductsView extends GetView<ProductsController> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Obx(() {
if (controller.isLoading.value) return const ProductShimmer();
if (controller.error.value != null) return ErrorWidget(controller.error.value!);
return ProductList(controller.products);
}),
);
}
}
```
## Rules
- **NEVER** pass `BuildContext` into a controller
- Use `Binding` classes for dependency injection — never `Get.put()` in a widget
- Use `.obs` for all reactive state — never call `update()` on non-observable state
- Use `Get.find<Controller>()` only in `Binding` classes, not in widgets
- **No business logic in Views** — controllers handle all logic
## File locations in {{PROJECT_NAME}}
- `lib/features/[feature]/views/[feature]_view.dart`
- `lib/features/[feature]/controllers/[feature]_controller.dart`
- `lib/features/[feature]/bindings/[feature]_binding.dart`
- `lib/features/[feature]/models/[feature]_model.dart`