195 lines
5.0 KiB
Markdown
195 lines
5.0 KiB
Markdown
# Global Loading State Usage Guide
|
|
|
|
This document explains how to use the global loading state system in your Vue app.
|
|
|
|
## Overview
|
|
|
|
The loading system provides multiple ways to handle loading states:
|
|
|
|
1. **Global Loading Overlay** - Shows over the entire app
|
|
2. **Component-specific Loading** - For individual components like DataTable and Form
|
|
3. **Operation-specific Loading** - For tracking specific async operations
|
|
|
|
## Loading Store
|
|
|
|
### Basic Usage
|
|
|
|
```javascript
|
|
import { useLoadingStore } from "../../stores/loading";
|
|
|
|
const loadingStore = useLoadingStore();
|
|
|
|
// Set global loading
|
|
loadingStore.setLoading(true, "Processing...");
|
|
|
|
// Set component-specific loading
|
|
loadingStore.setComponentLoading("dataTable", true, "Loading data...");
|
|
|
|
// Use async wrapper
|
|
const data = await loadingStore.withLoading(
|
|
"fetchUsers",
|
|
() => Api.getUsers(),
|
|
"Fetching user data...",
|
|
);
|
|
```
|
|
|
|
### Available Methods
|
|
|
|
- `setLoading(isLoading, message?)` - Global loading state
|
|
- `setComponentLoading(componentName, isLoading, message?)` - Component loading
|
|
- `startOperation(operationKey, message?)` - Start tracked operation
|
|
- `stopOperation(operationKey)` - Stop tracked operation
|
|
- `withLoading(operationKey, asyncFn, message?)` - Async wrapper
|
|
- `withComponentLoading(componentName, asyncFn, message?)` - Component async wrapper
|
|
|
|
### Convenience Methods
|
|
|
|
- `startApiCall(apiName?)` - Quick API loading
|
|
- `stopApiCall()` - Stop API loading
|
|
- `startDataTableLoading(message?)` - DataTable loading
|
|
- `stopDataTableLoading()` - Stop DataTable loading
|
|
- `startFormLoading(message?)` - Form loading
|
|
- `stopFormLoading()` - Stop Form loading
|
|
|
|
## DataTable Component
|
|
|
|
The DataTable component automatically integrates with the loading store:
|
|
|
|
```vue
|
|
<template>
|
|
<DataTable
|
|
:data="tableData"
|
|
:columns="columns"
|
|
tableName="clients"
|
|
:loading="customLoading"
|
|
loadingMessage="Custom loading message..."
|
|
emptyMessage="No clients found"
|
|
/>
|
|
</template>
|
|
|
|
<script setup>
|
|
// DataTable will automatically show loading when:
|
|
// 1. props.loading is true
|
|
// 2. Global loading store has loading for 'dataTable'
|
|
// 3. Global loading store has loading for props.tableName
|
|
// 4. Any global loading (if useGlobalLoading is true)
|
|
|
|
// You can also control it directly:
|
|
const tableRef = ref();
|
|
tableRef.value?.startLoading("Custom loading...");
|
|
tableRef.value?.stopLoading();
|
|
</script>
|
|
```
|
|
|
|
## Form Component
|
|
|
|
The Form component also integrates with loading:
|
|
|
|
```vue
|
|
<template>
|
|
<Form
|
|
:fields="formFields"
|
|
formName="userForm"
|
|
:loading="customLoading"
|
|
loadingMessage="Saving user..."
|
|
@submit="handleSubmit"
|
|
/>
|
|
</template>
|
|
|
|
<script setup>
|
|
// Form will disable all inputs and show loading buttons when:
|
|
// 1. props.loading is true
|
|
// 2. Global loading store has loading for 'form'
|
|
// 3. Global loading store has loading for props.formName
|
|
// 4. Internal isSubmitting is true
|
|
|
|
// Control directly:
|
|
const formRef = ref();
|
|
formRef.value?.startLoading("Processing...");
|
|
formRef.value?.stopLoading();
|
|
</script>
|
|
```
|
|
|
|
## API Integration Example
|
|
|
|
```javascript
|
|
// In your page component
|
|
import { useLoadingStore } from "../../stores/loading";
|
|
|
|
const loadingStore = useLoadingStore();
|
|
|
|
// Method 1: Manual control
|
|
const loadData = async () => {
|
|
try {
|
|
loadingStore.startDataTableLoading("Loading clients...");
|
|
const data = await Api.getClients();
|
|
tableData.value = data;
|
|
} finally {
|
|
loadingStore.stopDataTableLoading();
|
|
}
|
|
};
|
|
|
|
// Method 2: Using wrapper (recommended)
|
|
const loadData = async () => {
|
|
const data = await loadingStore.withComponentLoading(
|
|
"clients",
|
|
() => Api.getClients(),
|
|
"Loading clients...",
|
|
);
|
|
tableData.value = data;
|
|
};
|
|
|
|
// Method 3: For global overlay
|
|
const performGlobalAction = async () => {
|
|
const result = await loadingStore.withLoading(
|
|
"globalOperation",
|
|
() => Api.performHeavyOperation(),
|
|
"Processing your request...",
|
|
);
|
|
return result;
|
|
};
|
|
```
|
|
|
|
## Global Loading Overlay
|
|
|
|
The `GlobalLoadingOverlay` component shows automatically when global loading is active:
|
|
|
|
```vue
|
|
<!-- Already added to App.vue -->
|
|
<GlobalLoadingOverlay />
|
|
|
|
<!-- Customizable props -->
|
|
<GlobalLoadingOverlay
|
|
:globalOnly="false" <!-- Show for any loading, not just global -->
|
|
:minDisplayTime="500" <!-- Minimum display time in ms -->
|
|
/>
|
|
```
|
|
|
|
## Best Practices
|
|
|
|
1. **Use component-specific loading** for individual components
|
|
2. **Use global loading** for app-wide operations (login, navigation, etc.)
|
|
3. **Use operation tracking** for multiple concurrent operations
|
|
4. **Always use try/finally** when manually controlling loading
|
|
5. **Prefer async wrappers** over manual start/stop calls
|
|
6. **Provide meaningful loading messages** to users
|
|
|
|
## Error Handling
|
|
|
|
```javascript
|
|
const loadData = async () => {
|
|
try {
|
|
const data = await loadingStore.withComponentLoading(
|
|
"clients",
|
|
() => Api.getClients(),
|
|
"Loading clients...",
|
|
);
|
|
tableData.value = data;
|
|
} catch (error) {
|
|
console.error("Failed to load clients:", error);
|
|
// Show error message to user
|
|
// Loading state is automatically cleared by the wrapper
|
|
}
|
|
};
|
|
```
|