-
Notifications
You must be signed in to change notification settings - Fork 106
Common Custom Code Examples #200
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 6 commits
8eb272d
1ee8c21
3a14489
527a2b5
e2abf07
17f396b
6009bbb
7e1c0ab
ff2c00b
9cfbd43
13260f3
6e5d1de
0e56def
343c144
2c4f7e9
5d7fa60
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,284 @@ | ||
--- | ||
slug: /concepts/custom-code/common-examples | ||
title: Common Examples | ||
description: Learn about the common custom code examples and use it directly in your project. | ||
tags: [Custom Actions, Custom Code] | ||
sidebar_position: 6 | ||
keywords: [FlutterFlow, Custom Actions, Customizations, Flutter, Dart, Pub.dev, Examples] | ||
--- | ||
|
||
# Common Code Examples | ||
|
||
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. | ||
|
||
### Accessing FlutterFlow Generated Classes | ||
|
||
Most custom FlutterFlow classes are 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 easily. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would recommend specifying what classes means here. In this case it sounds like widgets we use under the hood, as opposed to components which are also FlutterFlow Generated Classes. Suggest putting a one liner like "In the generated code, FlutterFlow uses a combination of widgets from the Flutter framework, popular pub.dev packages and custom widgets created by the FlutterFlow team. You may want to reference widgets created by the FlutterFlow team in your own generated code, such as FFDropdown or ..... these widgets are usually prefixed...." There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually this is not limited to widgets or components only. It could be other classes like FFUploadedFile or FFPlace or FFRoute, basically any FlutterFlow class exposed to users. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. thats why it is helpful to explain what a class means in this context :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Makes sense! Done!
PoojaB26 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
 | ||
|
||
### Returning Component from Custom Widget | ||
PoojaB26 marked this conversation as resolved.
Show resolved
Hide resolved
PoojaB26 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
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 | ||
PoojaB26 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
[pub.dev](custom-code.md#pubdev), you can simply return an existing Component created on the canvas, rather than coding the content from scratch. | ||
PoojaB26 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
:::tip[Imports] | ||
When referencing a Component class in your code, FlutterFlow will automatically add the necessary import statement. | ||
::: | ||
|
||
 | ||
|
||
|
||
### Accessing FlutterFlow Theme in Custom Widget | ||
|
||
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. | ||
|
||
To access theme colors in your custom widget, use the `FlutterFlowTheme.of(context)` method. This allows you to retrieve any theme color, such as the **primary color, accent color**, or **background color**, ensuring that your custom widget aligns with the app’s overall theme. | ||
PoojaB26 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
Here’s an example of how to use the primary color from FlutterFlow Theme in a custom widget: | ||
|
||
:::tip[Imports] | ||
Ensure you import `import '../flutter_flow/flutter_flow_theme.dart';` when accessing `FlutterFlowTheme` in your custom widgets. | ||
::: | ||
|
||
|
||
```js | ||
class CustomButton extends StatefulWidget { | ||
final String label; | ||
|
||
CustomButton({required this.label}); | ||
|
||
@override | ||
_CustomButtonState createState() => _CustomButtonState(); | ||
} | ||
|
||
class _CustomButtonState extends State<CustomButton> { | ||
bool isPressed = false; | ||
|
||
void toggleButton() { | ||
setState(() { | ||
isPressed = !isPressed; | ||
}); | ||
} | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return ElevatedButton( | ||
style: ElevatedButton.styleFrom( | ||
primary: isPressed | ||
? FlutterFlowTheme.of(context).primary // Primary color when pressed | ||
: FlutterFlowTheme.of(context).secondaryBackground, // Default color | ||
onPrimary: FlutterFlowTheme.of(context).secondaryText, // Text color | ||
), | ||
onPressed: toggleButton, | ||
child: Text( | ||
widget.label, | ||
style: FlutterFlowTheme.of(context).bodyText1, // Themed text style | ||
), | ||
); | ||
} | ||
} | ||
``` | ||
|
||
|
||
### Manipulating AppState from Custom Code | ||
|
||
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: | ||
|
||
:::tip[Imports] | ||
Ensure you import `import '../../flutter_flow/flutter_flow_util.dart';` when accessing `FFAppState` in custom code resources. | ||
::: | ||
|
||
- **Accessing AppState in Custom Code** | ||
|
||
```js | ||
|
||
Future getCartItems() async { | ||
// Retrieve the current cart items from AppState | ||
final currentCartItems = FFAppState().cartItems; | ||
print('Current Cart Items: $currentCartItems'); | ||
} | ||
``` | ||
|
||
- **Updating AppState Values in Custom Code** | ||
|
||
```js | ||
Future enableDarkMode() async { | ||
// Enable dark mode in AppState | ||
FFAppState().update(() { | ||
FFAppState().enableDarkMode = true; | ||
}); | ||
print('Dark mode enabled'); | ||
} | ||
``` | ||
|
||
- **Modifying a List in AppState Using Helper Functions** | ||
|
||
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’s some examples of how to use these helper functions to modify an AppState list variable: | ||
PoojaB26 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
```js | ||
Future addLocation(LatLng value) async { | ||
// Add a new location to the LatLng list | ||
FFAppState().addToLatLngList(value); | ||
} | ||
|
||
Future removeLocation(LatLng value) async { | ||
// Remove a specific location from the LatLng list | ||
FFAppState().removeFromLatLngList(value); | ||
} | ||
|
||
Future removeLocationAtIndex(int index) async { | ||
// Remove a location at a specific index from the LatLng list | ||
FFAppState().removeAtIndexFromLatLngList(index); | ||
} | ||
|
||
Future updateLocationAtIndex(int index, LatLng Function(LatLng) updateFn) async { | ||
// Update a location at a specific index in the LatLng list | ||
FFAppState().updateLatLngListAtIndex(index, updateFn); | ||
} | ||
|
||
Future insertLocationAtIndex(int index, LatLng value) async { | ||
// Insert a new location at a specific index in the LatLng list | ||
FFAppState().insertAtIndexInLatLngList(index, value); | ||
} | ||
``` | ||
|
||
|
||
### Manipulate Custom Data Types | ||
PoojaB26 marked this conversation as resolved.
Show resolved
Hide resolved
PoojaB26 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
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. | ||
|
||
#### Example 1: Creating a new Instance of `ProductStruct` | ||
To create a new `ProductStruct` instance, initialize it with the required properties: | ||
|
||
```js | ||
// Create a new instance of ProductStruct | ||
final newProduct = ProductStruct( | ||
productId: '123', | ||
name: 'Example Product', | ||
description: 'A sample product description.', | ||
category: 'Electronics', | ||
subCategory: 'Mobile Phones', | ||
price: PriceStruct(amount: 299.99, currency: 'USD'), | ||
sizes: ['Small', 'Medium', 'Large'], | ||
colors: [ColorsStruct(colorName: 'Red', colorHex: '#FF0000')], | ||
images: [ImagesStruct(thumbnail: 'https://example.com/image.jpg')], | ||
stockStatus: StockStatusStruct(xs: 0, small: 2), | ||
reviews: [ReviewsStruct(rating: 4, comment: 'Great product!')], | ||
); | ||
|
||
``` | ||
|
||
#### Example 2: Accessing Properties of an Existing `ProductStruct` object | ||
|
||
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. Let's assume you have an Action that calls a Custom Action to retrieve a field value from the provided `ProductStruct` object. | ||
|
||
- **Returning a Single Field from ProductStruct** | ||
|
||
This function retrieves and returns the product's name. The return type is `String?` to account for the possibility of a null value. | ||
```js | ||
PoojaB26 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// Function to return the product name from a ProductStruct instance | ||
String? getProductName(ProductStruct product) { | ||
// Access and return the product name | ||
return product.name; | ||
} | ||
``` | ||
- **Returning a List of Review Comments from ProductStruct** | ||
|
||
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). | ||
|
||
```js | ||
// Function to return a list of review comments from a ProductStruct instance | ||
List<String> getProductReviewComments(ProductStruct product) { | ||
// Check if reviews are present and return a list of review comments | ||
return product.reviews?.map((review) => review.comment ?? '').toList() ?? []; | ||
} | ||
``` | ||
|
||
#### Example 3: Modifying Properties of an Existing `ProductStruct` Object | ||
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. | ||
|
||
- **Simple Property Modification** | ||
In this example, we’ll modify a single property, like `productId`, of an existing `ProductStruct` object. This example is straightforward and demonstrates how to update a basic field in the object. | ||
|
||
```js | ||
// Function to update the product ID of a ProductStruct instance | ||
Future updateProductId(ProductStruct product, String newProductId) { | ||
PoojaB26 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// Update the product ID with the new value | ||
product.productId = newProductId; | ||
} | ||
``` | ||
|
||
- **Complex Property Modification - Nested Object Update** | ||
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. | ||
|
||
```js | ||
// Function to update the price of a ProductStruct instance | ||
Future updateProductPrice(ProductStruct product, double newAmount, String currency) { | ||
// Check if price is not null | ||
if (product.price != null) { | ||
// Update only the amount field | ||
product.price!.amount = newAmount; | ||
} else { | ||
// If price is null, optionally initialize it if needed | ||
product.price = PriceStruct( | ||
amount: newAmount, | ||
currency: currency, | ||
); | ||
} | ||
} | ||
``` | ||
|
||
- **Complex Property Modification - Updating a List Property** | ||
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. | ||
|
||
```js | ||
Future addNewReviews(ProductStruct product) { | ||
product.reviews ??= []; // Initialize the reviews list if it's null | ||
product.reviews!.addAll([ | ||
ReviewStruct(rating: 5, comment: 'Excellent product!'), | ||
ReviewStruct(rating: 4, comment: 'Good quality, but a bit expensive.'), | ||
ReviewStruct(rating: 3, comment: 'Satisfactory, meets expectations.'), | ||
]); | ||
} | ||
``` | ||
|
||
or if the new list of reviews are being provided to the Custom Action, then: | ||
PoojaB26 marked this conversation as resolved.
Show resolved
Hide resolved
PoojaB26 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
```js | ||
Future addDynamicReviews(ProductStruct product, List<ReviewStruct> newReviews) { | ||
product.reviews ??= []; // Initialize the reviews list if it's null | ||
product.reviews!.addAll(newReviews); // Add the new reviews | ||
} | ||
|
||
``` | ||
|
||
|
||
### Using Firebase Auth Variables in Custom Code | ||
|
||
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. | ||
|
||
For example, you can check if a user’s email is verified before proceeding with certain actions: | ||
|
||
```js | ||
if (currentUserEmailVerified) { | ||
// Perform action for verified users | ||
} | ||
``` | ||
|
||
Or, if you need to create a directory path that includes the user’s unique ID: | ||
```js | ||
String directoryPath = '/users/' + currentUserUid + '/files'; | ||
``` | ||
|
||
Here’s a list of other Firebase Auth variables that can be referenced in Custom Code: | ||
|
||
- `currentUserEmail` – The email address of the current user. | ||
- `currentUserUid` – The unique ID of the current user. | ||
- `currentUserDisplayName` – The display name set by the user. | ||
- `currentUserPhoto` – The profile photo URL of the current user. | ||
- `currentPhoneNumber` – The user’s phone number, if available. | ||
- `currentJwtToken` – The current user’s JWT token for secure requests. | ||
- `currentUserEmailVerified` – Boolean indicating if the user’s email is verified. | ||
|
||
- These variables make it easy to integrate Firebase Auth data into custom functionality, enhancing the user experience. | ||
|
Uh oh!
There was an error while loading. Please reload this page.