Retool Cheat Blatt¶
Überblick¶
Retool ist eine Low-Code-Plattform für den Aufbau von internen Werkzeugen schnell. Es ermöglicht Entwicklern, benutzerdefinierte Anwendungen zu erstellen, indem sie mit Datenbanken, APIs und Dienstleistungen über eine Drag-and-Drop-Schnittstelle kombiniert mit JavaScript-Code verbinden, wodurch schnelle Entwicklung von Admin-Panels, Dashboards und Business-Anwendungen ermöglicht wird.
ZEIT Anmerkung: Free tier für bis zu 5 Benutzer verfügbar. Bezahlte Pläne starten bei $10/Benutzer/Monat für Teams.
Erste Schritte¶
Kontoaufbau¶
```bash
Sign up process:¶
1. Visit retool.com¶
2. Create account with email or Google/GitHub¶
3. Choose organization name¶
4. Set up first application¶
5. Connect data sources¶
Organization setup:¶
- Configure SSO (optional)¶
- Set up user groups and permissions¶
- Configure environment variables¶
- Set up version control¶
- Configure deployment settings¶
```_
Erste Anwendung¶
```bash
Create new app:¶
1. Click "Create new" → "App"¶
2. Choose template or start blank¶
3. Name your application¶
4. Select starting components¶
5. Configure data connections¶
Basic app structure:¶
- Components: UI elements (tables, forms, buttons)¶
- Queries: Data operations (API calls, database queries)¶
- JavaScript: Custom logic and transformations¶
- State: Application data and variables¶
```_
Schnittstellenübersicht¶
```bash
Main interface areas:¶
- Component Library: Drag-and-drop UI elements¶
- Canvas: Visual app builder¶
- Query Editor: Data operations panel¶
- State Inspector: Variable and data viewer¶
- Code Editor: JavaScript and SQL editor¶
- Resource Manager: Data source connections¶
```_
Komponenten¶
Daten anzeigen Komponenten¶
```bash
Table component:¶
- Display tabular data¶
- Sorting and filtering¶
- Pagination¶
- Row selection¶
- Inline editing¶
- Custom columns¶
Table configuration:¶
table1.data = {{ query1.data }} table1.columns = [ { "id": "name", "label": "Name", "type": "string" }, { "id": "email", "label": "Email", "type": "email" } ] ```_
Eingangskomponenten¶
```bash
Text Input:¶
textInput1.value # Get current value textInput1.setValue("text") # Set value programmatically
Select component:¶
select1.value # Selected value select1.selectedItem # Selected item object select1.data = {{ query1.data }} select1.valueKey = "id" select1.labelKey = "name"
Date Picker:¶
datePicker1.value # Selected date datePicker1.formattedValue # Formatted date string ```_
Aktionskomponenten¶
```bash
Button component:¶
button1.click() # Trigger click programmatically button1.loading = {{ query1.isFetching }} button1.disabled = {{ !form1.isValid }}
Button event handlers:¶
// onClick event if (textInput1.value) { query1.trigger(); } else { utils.showNotification({ title: "Error", description: "Please enter a value", notificationType: "error" }); } ```_
Aufbaukomponenten¶
```bash
Container:¶
- Group related components¶
- Apply consistent styling¶
- Control visibility and layout¶
Tabs:¶
- Organize content into sections¶
- Dynamic tab creation¶
- Conditional tab visibility¶
Modal:¶
modal1.open() # Open modal modal1.close() # Close modal modal1.opened # Check if open ```_
Datenquellen¶
Datenbankverbindungen¶
```bash
Supported databases:¶
- PostgreSQL¶
- MySQL¶
- MongoDB¶
- Redis¶
- Elasticsearch¶
- BigQuery¶
- Snowflake¶
- Microsoft SQL Server¶
Connection setup:¶
1. Go to Resources tab¶
2. Click "Create new resource"¶
3. Select database type¶
4. Enter connection details¶
5. Test connection¶
6. Save resource¶
```_
REST API Integration¶
```bash
REST API resource:¶
1. Create new REST API resource¶
2. Set base URL¶
3. Configure authentication¶
4. Add headers if needed¶
5. Test connection¶
API query example:¶
// GET request return await api1.run({ url: "/users", method: "GET", params: { page: table1.pageIndex + 1, limit: table1.pageSize } });
// POST request return await api1.run({ url: "/users", method: "POST", body: { name: textInput1.value, email: textInput2.value } }); ```_
Integration von GraphQL¶
```bash
GraphQL setup:¶
1. Create GraphQL resource¶
2. Set endpoint URL¶
3. Configure authentication¶
4. Add headers if needed¶
GraphQL query:¶
query GetUsers($limit: Int!) { users(limit: $limit) { id name email createdAt } }
Variables:¶
{ "limit": {{ table1.pageSize }} } ```_
Quer- und Transformer¶
SQL Quers¶
```sql -- Basic SELECT query SELECT * FROM users WHERE created_at >= {{ datePicker1.value }} ORDER BY created_at DESC LIMIT {{ table1.pageSize }} OFFSET {{ table1.pageIndex * table1.pageSize }};
-- Parameterized query SELECT * FROM orders WHERE user_id = {{ select1.value }} AND status = {{ textInput1.value || 'active' }} AND created_at BETWEEN {{ startDate.value }} AND {{ endDate.value }};
-- Insert query INSERT INTO users (name, email, department) VALUES ( {{ textInput1.value }}, {{ textInput2.value }}, {{ select1.value }} ); ```_
JavaScript Transformers¶
``javascript
// Transform API response
const transformedData = query1.data.map(item => ({
id: item.id,
fullName:${item.firstName} ${item.lastName}`,
email: item.email,
status: item.isActive ? 'Active' : 'Inactive',
joinDate: new Date(item.createdAt).toLocaleDateString()
}));
return transformedData;
// Aggregate data const summary = query1.data.reduce((acc, item) => { acc.totalRevenue += item.revenue; acc.totalOrders += 1; acc.averageOrderValue = acc.totalRevenue / acc.totalOrders; return acc; }, { totalRevenue: 0, totalOrders: 0, averageOrderValue: 0 });
return summary; ```_
Querverkettung¶
```javascript // Sequential queries const userData = await query1.trigger(); const userOrders = await query2.trigger({ additionalScope: { userId: userData.id } });
return { user: userData, orders: userOrders };
// Parallel queries const [users, orders, products] = await Promise.all([ query1.trigger(), query2.trigger(), query3.trigger() ]);
return { users, orders, products }; ```_
JavaScript in Retool¶
Globale Funktionen¶
```javascript // Utility functions utils.showNotification({ title: "Success", description: "Record saved successfully", notificationType: "success", duration: 3000 });
utils.openUrl("https://example.com", { newTab: true });
utils.copyToClipboard(textInput1.value);
utils.downloadPage("report.pdf");
utils.goToApp("app-uuid", { userId: select1.value }); ```_
Staatliche Verwaltung¶
```javascript // Set temporary state tempState.setValue({ selectedUser: table1.selectedRow.data, editMode: true, originalData: { ...table1.selectedRow.data } });
// Get state values const currentUser = tempState.value.selectedUser; const isEditing = tempState.value.editMode;
// Clear state tempState.setValue({});
// Local storage localStorage.setValue("userPreferences", { theme: "dark", language: "en" });
const preferences = localStorage.getValue("userPreferences"); ```_
Event Handling¶
```javascript // Component event handlers // Button onClick async function handleSubmit() { try { button1.setLoading(true);
const result = await query1.trigger();
utils.showNotification({
title: "Success",
description: "Data saved successfully"
});
modal1.close();
table1.refresh();
} catch (error) { utils.showNotification({ title: "Error", description: error.message, notificationType: "error" }); } finally { button1.setLoading(false); } }
// Table row selection function handleRowSelect() { const selectedData = table1.selectedRow.data;
textInput1.setValue(selectedData.name); textInput2.setValue(selectedData.email); select1.setValue(selectedData.department); } ```_
Erweiterte Funktionen¶
Benutzerdefinierte Komponenten¶
```javascript // Custom React component const CustomChart = ({ data, title }) => { const chartData = data.map(item => ({ name: item.month, value: item.revenue }));
return (
{title}
// Use custom component
Workflows und Automatisierung¶
```javascript // Workflow example: User onboarding async function onboardNewUser() { try { // Step 1: Create user account const user = await createUserQuery.trigger({ additionalScope: { name: nameInput.value, email: emailInput.value, department: departmentSelect.value } });
// Step 2: Send welcome email
await sendEmailQuery.trigger({
additionalScope: {
to: user.email,
template: "welcome",
variables: { name: user.name }
}
});
// Step 3: Create default permissions
await createPermissionsQuery.trigger({
additionalScope: {
userId: user.id,
role: "employee"
}
});
// Step 4: Add to team
await addToTeamQuery.trigger({
additionalScope: {
userId: user.id,
teamId: teamSelect.value
}
});
utils.showNotification({
title: "Success",
description: "User onboarded successfully"
});
} catch (error) { console.error("Onboarding failed:", error); utils.showNotification({ title: "Error", description: "Failed to onboard user", notificationType: "error" }); } } ```_
Berechtigungen und Sicherheit¶
```javascript // Role-based access control const userRole = current_user.groups[0];
// Hide components based on role if (userRole !== 'admin') { deleteButton.hidden = true; editButton.hidden = true; }
// Conditional queries if (userRole === 'admin') { return await adminQuery.trigger(); } else { return await userQuery.trigger({ additionalScope: { userId: current_user.id } }); }
// Data filtering by user SELECT * FROM orders WHERE user_id = {{ current_user.id }} OR {{ current_user.groups.includes('admin') }} ```_
Mobile Verantwortung¶
Responsive Design¶
```javascript // Screen size detection const isMobile = window.innerWidth < 768; const isTablet = window.innerWidth >= 768 && window.innerWidth < 1024; const isDesktop = window.innerWidth >= 1024;
// Conditional styling if (isMobile) { container1.style = { padding: "10px", flexDirection: "column" }; } else { container1.style = { padding: "20px", flexDirection: "row" }; } ```_
Mobile-spezifische Komponenten¶
```javascript // Mobile navigation const MobileNav = () => { const [isOpen, setIsOpen] = useState(false);
return (
); }; ```_Einsatz und Umwelt¶
Umweltmanagement¶
```bash
Environment types:¶
- Development: Testing and development¶
- Staging: Pre-production testing¶
- Production: Live application¶
Environment variables:¶
{{ retool.environment }} - Current environment¶
{{ retool.configVars.API_URL }} - Environment-specific config¶
```_
Versionskontrolle¶
```bash
Git integration:¶
1. Connect to GitHub/GitLab repository¶
2. Configure branch protection¶
3. Set up pull request workflow¶
4. Enable automatic deployments¶
Branching strategy:¶
- main: Production code¶
- staging: Pre-production testing¶
- feature/*: Feature development¶
- hotfix/*: Critical bug fixes¶
```_
Release Management¶
```javascript // Release checklist automation const releaseChecklist = [ { task: "Run tests", completed: false }, { task: "Update documentation", completed: false }, { task: "Review security", completed: false }, { task: "Performance testing", completed: false }, { task: "Stakeholder approval", completed: false } ];
// Deployment script async function deployToProduction() { const incompleteItems = releaseChecklist.filter(item => !item.completed);
if (incompleteItems.length > 0) {
utils.showNotification({
title: "Deployment Blocked",
description: Complete: ${incompleteItems.map(i => i.task).join(', ')},
notificationType: "warning"
});
return;
}
// Proceed with deployment await deployQuery.trigger(); } ```_
Leistungsoptimierung¶
Queroptimierung¶
```javascript // Debounced search let searchTimeout;
function handleSearchInput() { clearTimeout(searchTimeout); searchTimeout = setTimeout(() => { searchQuery.trigger({ additionalScope: { searchTerm: searchInput.value } }); }, 500); }
// Cached queries const cachedData = localStorage.getValue("userList"); const cacheExpiry = localStorage.getValue("userListExpiry");
if (cachedData && cacheExpiry > Date.now()) { return cachedData; } else { const freshData = await userQuery.trigger(); localStorage.setValue("userList", freshData); localStorage.setValue("userListExpiry", Date.now() + 300000); // 5 minutes return freshData; } ```_
Komponentenoptimierung¶
```javascript // Lazy loading const LazyTable = React.lazy(() => import('./HeavyTable'));
function DataView() { const [showTable, setShowTable] = useState(false);
return (