Skip to content

Commit 8dce9fc

Browse files
PoojaB26pinkeshmarsleighajarett
authored
Common Custom Code Examples (#200)
* add new diagrams and fix docs * Add new custom code common examples and update positions of pages * add import info * renaming header to match what is in the app * fix anchors * add firebase auth reference example * Apply suggestions from code review Fixes from code suggestions Co-authored-by: pinkeshmars <[email protected]> * add disclaimer about custom functions * change code example for update object property example * add info about static vs dynamic content * call out custom colors and text styles from theme * add example for checking if field exists * add FFclass examples --------- Co-authored-by: pinkeshmars <[email protected]> Co-authored-by: Leigha Jarett <[email protected]>
1 parent f476a83 commit 8dce9fc

17 files changed

+431
-43
lines changed

docs/ff-concepts/adding-customization/cloud-functions.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ slug: /concepts/custom-code/cloud-functions
33
title: Cloud Functions
44
description: Learn how to use Cloud Functions in your FlutterFlow app for serverless backend functionality.
55
tags: [Cloud Functions, Serverless, Integration]
6-
sidebar_position: 6
6+
sidebar_position: 7
77
keywords: [FlutterFlow, Cloud Functions, Serverless, Integration]
88
---
99

Lines changed: 348 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,348 @@
1+
---
2+
slug: /concepts/custom-code/common-examples
3+
title: Common Examples
4+
description: Learn about the common custom code examples and use it directly in your project.
5+
tags: [Custom Actions, Custom Code]
6+
sidebar_position: 6
7+
keywords: [FlutterFlow, Custom Actions, Customizations, Flutter, Dart, Pub.dev, Examples]
8+
---
9+
10+
# Common Code Examples
11+
12+
The custom code feature in FlutterFlow allows you to extend functionality by accessing generated classes and modifying global variables like App States and FlutterFlow themes. This guide covers common scenarios where you can leverage custom code to enhance your project by working directly with data models and other resources within your code.
13+
14+
:::warning[Disclaimer]
15+
Custom Functions cannot import new files or packages outside of the default dedicated imports. Therefore, most of the suggestions below that involve adding a new import will not work in Custom Functions due to this restriction. However, they will work for Custom Widgets and Custom Actions.
16+
17+
For example, a new [**Custom Function**](custom-functions.md) typically includes the following packages and files. Your custom function code changes should use only these packages & files:
18+
19+
```js
20+
import 'dart:convert';
21+
import 'dart:math' as math;
22+
23+
import 'package:flutter/material.dart';
24+
import 'package:google_fonts/google_fonts.dart';
25+
import 'package:intl/intl.dart';
26+
import 'package:timeago/timeago.dart' as timeago;
27+
import 'lat_lng.dart';
28+
import 'place.dart';
29+
import 'uploaded_file.dart';
30+
import '/backend/backend.dart';
31+
import 'package:cloud_firestore/cloud_firestore.dart';
32+
import '/backend/schema/structs/index.dart';
33+
import '/backend/schema/enums/enums.dart';
34+
import '/auth/firebase_auth/auth_util.dart';
35+
```
36+
37+
:::
38+
### Accessing FlutterFlow Generated Classes
39+
40+
FlutterFlow generates a complete Flutter codebase for you as you build apps in its platform. Part of this code includes custom classes that are designed to streamline common tasks and encapsulate reusable properties or logic.
41+
42+
For example:
43+
44+
- **Button Widgets:** FlutterFlow provides custom button classes like `FFButton` that come with built-in styling and behaviors.
45+
- **Google Places:** The `FFPlace` class encapsulates properties of a Google Place, such as name, address, and coordinates.
46+
- **File Uploads:** The `FFUploadedFile` class represents files uploaded to your app, encapsulating properties like the file name, bytes, and URL.
47+
48+
49+
:::tip[What is a Class?]
50+
In programming, a class is a blueprint for creating objects. It defines properties (data) and methods (functions) that belong to objects of that type.
51+
52+
For example,
53+
54+
- A `Car` class might have properties like `color` and `speed` and methods like `drive()` and `stop()`.
55+
- In FlutterFlow, a class like `FFPlace` might have properties like `address` and `latLng`, and methods to manipulate or retrieve these values.
56+
:::
57+
58+
These custom FlutterFlow classes in the generated code are mostly prefixed with `FF<ClassName>` or `FlutterFlow<ClassName>`. If you need to access these classes in your custom code, simply type "FF" or "FlutterFlow" in the code editor to locate them quick.
59+
60+
61+
![suggestions-dropdown.png](imgs/suggestions-dropdown.png)
62+
63+
### Leveraging Components in Custom Widget
64+
65+
:::warning[Static Components vs Dynamic]
66+
Use this approach only when the component is a fixed element that does not change across different use cases. If the child component needs to change based on user choices, pass it directly [**as a parameter**](custom-widgets.md#creating-a-new-custom-widget).
67+
:::
68+
69+
In a **[Custom Widget](custom-widgets.md)**, you can integrate a previously built **[FlutterFlow Component](../../resources/ui/components/intro-components.md)** directly, saving you from recreating child content in code. For example, if you’re building a Custom Widget to display custom dialog boxes or bottom sheets using a package from
70+
[pub.dev](custom-code.md#pubdev), you can simply return an existing Component created on the canvas, rather than coding a new one from scratch.
71+
72+
:::tip[Imports]
73+
When referencing a Component class in your code, FlutterFlow will automatically add the necessary import statement.
74+
:::
75+
76+
77+
78+
![return-widget-custom-code.png](imgs/return-widget-custom-code.png)
79+
80+
81+
### Accessing FlutterFlow Theme in Custom Widget
82+
83+
When building custom widgets, you often need to style parts of the widget, such as setting colors. Instead of using hardcoded color values, you can directly access the **FlutterFlow Theme**. This theme provides consistent styling across your app and reflects colors set by you or your project developer.
84+
85+
To access theme colors in your custom widget, use the `FlutterFlowTheme.of(context)` method. This allows you to retrieve any theme property, such as the default `primary`, `primaryBackground`, or other custom-created colors, as well as text styles like `bodyLarge` or `bodyMedium`, ensuring that your custom widget aligns with the app’s overall theme.
86+
87+
Here’s an example of how to use the primary color from FlutterFlow Theme in a custom widget:
88+
89+
:::tip[Imports]
90+
Ensure you import `import '../flutter_flow/flutter_flow_theme.dart';` when accessing `FlutterFlowTheme` in your custom widgets.
91+
:::
92+
93+
94+
```js
95+
class CustomButton extends StatefulWidget {
96+
final String label;
97+
98+
CustomButton({required this.label});
99+
100+
@override
101+
_CustomButtonState createState() => _CustomButtonState();
102+
}
103+
104+
class _CustomButtonState extends State<CustomButton> {
105+
bool isPressed = false;
106+
107+
void toggleButton() {
108+
setState(() {
109+
isPressed = !isPressed;
110+
});
111+
}
112+
113+
@override
114+
Widget build(BuildContext context) {
115+
return ElevatedButton(
116+
style: ElevatedButton.styleFrom(
117+
backgroundColor: isPressed
118+
? FlutterFlowTheme.of(context).primary // Primary color when pressed
119+
: FlutterFlowTheme.of(context).secondaryBackground, // Default color
120+
foregroundColor: FlutterFlowTheme.of(context).secondaryText, // Text color
121+
),
122+
onPressed: toggleButton,
123+
child: Text(
124+
widget.label,
125+
style: FlutterFlowTheme.of(context).bodyText1, // Themed text style
126+
),
127+
);
128+
}
129+
}
130+
```
131+
:::info
132+
Find the list of colors,
133+
134+
### Manipulating AppState from Custom Code
135+
136+
In FlutterFlow, you can access or update AppState directly from the Action Flow Editor. However, certain scenarios may require you to access or modify AppState within custom code for more control over the operation flow. The FFAppState class also provides additional helper functions to manipulate AppState variables. Let’s look at some examples:
137+
138+
:::tip[Imports]
139+
Ensure you import `import '../../flutter_flow/flutter_flow_util.dart';` when accessing `FFAppState` in custom code resources.
140+
:::
141+
142+
- **Accessing AppState in Custom Code**
143+
144+
```js
145+
146+
Future getCartItems() async {
147+
// Retrieve the current cart items from AppState
148+
final currentCartItems = FFAppState().cartItems;
149+
print('Current Cart Items: $currentCartItems');
150+
}
151+
```
152+
153+
- **Updating AppState Values in Custom Code**
154+
155+
```js
156+
Future enableDarkMode() async {
157+
// Enable dark mode in AppState
158+
FFAppState().update(() {
159+
FFAppState().enableDarkMode = true;
160+
});
161+
print('Dark mode enabled');
162+
}
163+
```
164+
165+
- **Modifying a List in AppState Using Helper Functions**
166+
167+
The `FFAppState` class offers a variety of helper functions to easily manage list variables in AppState. For a detailed overview of this generated class, check out **[this guide](../../generated-code/ff-app-state.md#managing-appstatelist)**. Here are some examples of how to use these helper functions to modify an AppState list variable:
168+
169+
```js
170+
Future addLocation(LatLng value) async {
171+
// Add a new location to the LatLng list
172+
FFAppState().addToLatLngList(value);
173+
}
174+
175+
Future removeLocation(LatLng value) async {
176+
// Remove a specific location from the LatLng list
177+
FFAppState().removeFromLatLngList(value);
178+
}
179+
180+
Future removeLocationAtIndex(int index) async {
181+
// Remove a location at a specific index from the LatLng list
182+
FFAppState().removeAtIndexFromLatLngList(index);
183+
}
184+
185+
Future updateLocationAtIndex(int index, LatLng Function(LatLng) updateFn) async {
186+
// Update a location at a specific index in the LatLng list
187+
FFAppState().updateLatLngListAtIndex(index, updateFn);
188+
}
189+
190+
Future insertLocationAtIndex(int index, LatLng value) async {
191+
// Insert a new location at a specific index in the LatLng list
192+
FFAppState().insertAtIndexInLatLngList(index, value);
193+
}
194+
```
195+
196+
197+
### Leverage Custom Data Types
198+
When you create a custom data type in FlutterFlow, it **[generates a corresponding `<Name>Struct` class](../../generated-code/custom-data-type-gen.md)**. In FlutterFlow's custom code, you can create new instances of such data types, pass instances back into an action, or manipulate and retrieve information from existing objects. Here are some examples to help illustrate working with an example `ProductStruct` class.
199+
200+
#### Example 1: Creating a new Instance of `ProductStruct`
201+
To create a new `ProductStruct` instance, initialize it with the required properties:
202+
203+
```js
204+
// Create a new instance of ProductStruct
205+
final newProduct = ProductStruct(
206+
productId: '123',
207+
name: 'Example Product',
208+
description: 'A sample product description.',
209+
category: 'Electronics',
210+
subCategory: 'Mobile Phones',
211+
price: PriceStruct(amount: 299.99, currency: 'USD'),
212+
sizes: ['Small', 'Medium', 'Large'],
213+
colors: [ColorsStruct(colorName: 'Red', colorHex: '#FF0000')],
214+
images: [ImagesStruct(thumbnail: 'https://example.com/image.jpg')],
215+
stockStatus: StockStatusStruct(xs: 0, small: 2),
216+
reviews: [ReviewsStruct(rating: 4, comment: 'Great product!')],
217+
);
218+
219+
```
220+
221+
#### Example 2: Accessing Properties of an Existing `ProductStruct` object
222+
223+
If you have an existing `ProductStruct` object (e.g., retrieved from a list of products), you can access its properties or return specific values back to the calling Action.
224+
225+
Let's assume you have an Action that calls a Custom Action to retrieve a field value from the provided `ProductStruct` object.
226+
227+
- **Returning a Single Field from ProductStruct**
228+
229+
This function retrieves and returns the product's name. The return type is `String?` to account for the possibility of a null value.
230+
```js
231+
// Function to return the product name from a ProductStruct instance
232+
String? getProductName(ProductStruct product) {
233+
// Access and return the product name
234+
return product.name;
235+
}
236+
```
237+
238+
- **Checking if a Field Exists in a `ProductStruct` Object**
239+
This function determines whether the `ProductStruct` object contains a non-null value for a specific field, such as `description`. It returns `true` if the field exists and is not null, and `false` otherwise.
240+
241+
```js
242+
// Function to check if the description field exists in a ProductStruct instance
243+
bool hasDescription(ProductStruct product) {
244+
// Return true if the description is not null, false otherwise
245+
return product.description != null;
246+
}
247+
```
248+
249+
- **Returning a List of Review Comments from ProductStruct**
250+
251+
This function retrieves a list of review comments from the reviews field in the `ProductStruct`. The return type is `List<String>` as it returns a list of comments (or an empty list if there are no reviews).
252+
253+
```js
254+
// Function to return a list of review comments from a ProductStruct instance
255+
List<String> getProductReviewComments(ProductStruct product) {
256+
// Check if reviews are present and return a list of review comments
257+
return product.reviews?.map((review) => review.comment ?? '').toList() ?? [];
258+
}
259+
```
260+
261+
#### Example 3: Modifying Properties of an Existing `ProductStruct` Object
262+
You can also modify the properties of an existing `ProductStruct` object. This can be helpful if you want to update a field before saving the data back to Firebase or passing it into an action.
263+
264+
- **Simple Property Modification**
265+
In this example, we’ll modify a single property, like `productName`, of an existing `ProductStruct` object. This example is straightforward and demonstrates how to update a basic field in the object.
266+
267+
```js
268+
// Function to update the product name of a ProductStruct instance
269+
Future updateProductName(ProductStruct product, String newProductName) {
270+
// Update the product name with the new value
271+
product.productName = newProductName;
272+
}
273+
```
274+
275+
- **Complex Property Modification - Nested Object Update**
276+
In this more complex example, we’ll modify a nested property within the `ProductStruct`, such as updating the price (which itself is a `PriceStruct` object). This shows how to update a property that itself contains multiple fields.
277+
278+
```js
279+
// Function to update the price of a ProductStruct instance
280+
Future updateProductPrice(ProductStruct product, double newAmount, String currency) {
281+
// Check if price is not null
282+
if (product.price != null) {
283+
// Update only the amount field
284+
product.price!.amount = newAmount;
285+
} else {
286+
// If price is null, optionally initialize it if needed
287+
product.price = PriceStruct(
288+
amount: newAmount,
289+
currency: currency,
290+
);
291+
}
292+
}
293+
```
294+
295+
- **Complex Property Modification - Updating a List Property**
296+
In this example, we’ll add new items to a list property, like adding new review comments to the `reviews` list in `ProductStruct`. This example shows how to work with a list of nested objects.
297+
298+
```js
299+
Future addNewReviews(ProductStruct product) {
300+
product.reviews ??= []; // Initialize the reviews list if it's null
301+
product.reviews!.addAll([
302+
ReviewStruct(rating: 5, comment: 'Excellent product!'),
303+
ReviewStruct(rating: 4, comment: 'Good quality, but a bit expensive.'),
304+
ReviewStruct(rating: 3, comment: 'Satisfactory, meets expectations.'),
305+
]);
306+
}
307+
```
308+
309+
or if the new list of reviews is being provided to the Custom Action, then:
310+
311+
```js
312+
Future addDynamicReviews(ProductStruct product, List<ReviewStruct> newReviews) {
313+
product.reviews ??= []; // Initialize the reviews list if it's null
314+
product.reviews!.addAll(newReviews); // Add the new reviews
315+
}
316+
317+
```
318+
319+
320+
### Using Firebase Auth Variables in Custom Code
321+
322+
When using Firebase Authentication for your app, FlutterFlow provides access to key authentication data, such as `currentUserDisplayName`, `currentUserUid`, and more. These variables can be used in your Custom Actions to build additional features that require such common data from authenticated users.
323+
324+
For example, you can check if a user’s email is verified before proceeding with certain actions:
325+
326+
```js
327+
if (currentUserEmailVerified) {
328+
// Perform action for verified users
329+
}
330+
```
331+
332+
Or, if you need to create a directory path that includes the user’s unique ID:
333+
```js
334+
String directoryPath = '/users/' + currentUserUid + '/files';
335+
```
336+
337+
Here’s a list of other Firebase Auth variables that can be referenced in Custom Code:
338+
339+
- `currentUserEmail` – The email address of the current user.
340+
- `currentUserUid` – The unique ID of the current user.
341+
- `currentUserDisplayName` – The display name set by the user.
342+
- `currentUserPhoto` – The profile photo URL of the current user.
343+
- `currentPhoneNumber` – The user’s phone number, if available.
344+
- `currentJwtToken` – The current user’s JWT token for secure requests.
345+
- `currentUserEmailVerified` – Boolean indicating if the user’s email is verified.
346+
347+
- These variables make it easy to integrate Firebase Auth data into custom functionality, enhancing the user experience.
348+

docs/ff-concepts/adding-customization/custom-actions.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ Flow.
123123
To learn more about Custom Action settings, such as the
124124
[**Exclude From Compilation toggle**](custom-code.md#exclude-from-compilation),
125125
[**Include Build Context toggle**](custom-code.md#include-buildcontext),
126-
and other properties like [**Callback Actions**](custom-code.md#add-a-callback-action),
126+
and other properties like [**Callback Actions**](custom-code.md#callback-action-as-parameter),
127127
[**Pubspec Dependencies**](custom-code.md#adding-a-pubspec-dependency), please check out this
128128
[**comprehensive guide**](custom-code.md).
129129
:::

0 commit comments

Comments
 (0)