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 (