Front-End Web & Mobile
Announcing Flutter Web and Desktop support for AWS Amplify Storage, Analytics and API libraries
Earlier this year, AWS Amplify announced a Developer Preview for web and desktop support for its Flutter libraries in the Auth category and Amplify UI Authenticator for creating authentication flows. Today, the Amplify Flutter team is announcing web and desktop support for REST and GraphQL APIs, Analytics, and Storage categories. These categories were written fully in Dart, allowing you to have a consistent experience when using them across all your target platforms. The next milestone for the Amplify Flutter team is expanding Web and Desktop support for the Datastore category.
In this blog post, you will learn how to use AWS Amplify GraphQL API and Storage libraries by creating a grocery list application with Flutter that targets iOS, Android, Web, and Desktop.
By the end of this blog post, you will create a Flutter application that can:
- Sign up and sign in a user
- Create grocery items for a grocery list
- Save the grocery list with uploading an invoice of it
- See previous groceries
Requirements
- Flutter SDK version 3.0.0 or higher
- An AWS Account with AWS Amplify CLI setup, you can follow this documentation
- Clone of the starter project from GitHub
Minimum project requirements are added to the starter project. Depending on the target, you need to do the platform setup for Flutter.
Getting Started
Open the starter project at the IDE of your choice. The project contains:
- UI and libraries for the project
- Minimum project setup
- “TODO” comments to show where you are going to add features in order.
If you run the starter project you should see the following:
With the example app users can:
- Add an item to the grocery list shopping cart
- Select an invoice file
- Upload the files
- Submit the grocery shopping list
- Review previously submitted grocery shopping lists
Initialize Amplify and Add Authentication
You will start off by initializing the Amplify project. Go to the terminal and write the following on the base directory of your cloned project:
Enter a name for your Amplify project, accept the default configuration, select your AWS profile, and let the Amplify CLI do the rest for you.
Once it is done, you will see the following message:
Next step is to add the authentication to the project. Write amplify add auth
to the terminal and:
- Select Default Configuration from the list of configurations
- Select username from the sign in method
- Select No, I am done.
Now you added the authentication capabilities. Now it is time to push the changes to the cloud. Write amplify push
to the terminal.
With each push, this table will show you the status of your added resources and what the effect of pushing your changes will be. Continue with the push. This should take a few minutes.
The next step is to add the Authenticator library to your project. The Authenticator library is a UI library to handle authentication flows for you.
Go to pubspec.yaml file in the project and find TODO(1)
. Remove that and add the following and run flutter pub get
:
- This will add the Amplify libraries for authentication to your project.
Now go to the main.dart file and update the TODO(2)
part:
Now, go to TODO(3)
in the main.dart file and update the build
method with:
- The Authenticator library is wrapping the material app. This way it can show the home page when the user logs in.
Finally, time to add log out functionality. Go to TODO(4)
at current_grocery_list_page.dart file and add the following instead of the TODO
comment:
Now if you run the application, you can create an account, log in and log out:
Adding GraphQL API
Even though you have authentication, the data is still local and limited to each session. Add the API category to store your data in cloud for each user.
Run the command amplify add api
in the terminal.
- Select GraphQL as the service
- Change Authorization Mode to Amazon Cognito User Pool instead of an API KEY
- Select Continue to go to the next step
- Select One-to-many relationship as the schema template (Don’t worry about your selection, you will update the schema later on)
- Say No to the editing question.
Now go to your project folder and fine schema.graphql file under amplify/backend/api/<yourappname> and update it with:
Grocery
is your model to save grocery items and other previous grocery information:groceryItems
: Links to the Grocery items model for individual grocery items that users addtitle
: title for the grocery listfileKey
: File key for the uploaded filefinalizationDate
: Date of groceriestotalAmount
: Total amount spent for groceries
GroceryItem
is the model for each grocery item added to the grocery listname
: Name of the itemisBought
: The flag to keep track of bought itemscount
: Count of itemsgroceryID
: The grocery id of this item belongs to
Now run amplify push
to update your changes to the backend of your Amplify project.
Once the deployment is done, you need to add the API library to the pubspec.yaml file. Go to TODO (5)
inside the pubspec.yaml file and paste the following in place of the TODO
and run flutter pub get.
Now it is time to generate the models from the GraphQL API and remove the previous ones. Run amplify codegen models
to regenerate the GraphQL API models for your application. This should generate the model files for your groceries under lib/models.
After you add the API library and generate the models, go to the project and find the main.dart file, then the TODO(5)
and update the _configureAmplify
function to include the API plugin:
Now you can remove the temporary_grocery_item.dart and temporary_previous_grocery.dart files. Now follow the steps below to update each reference with the new models.
- Go to add_grocery_item_view.dart and update the constructor as:
This will keep a reference to the current grocery id while adding a new grocery item.
Now go to utils/helpers.dart file and find TODO(8)
there. Remove comments from the commented out code. This function is created to run your GraphQL mutations. GraphQL mutations can be in create, update or delete format and each mutation can have an error scenario. runMutation function either returns the saved element or throws an exception.
- Go to
TODO(9):
update theonItemAdded
callback as following:
Now use the GroceryItem
model instead of the temporary item while adding new items.
Go to finalize_grocery_view.dart
and update the constructor:
You are adding the current grocery to submit the open grocery items including setting a title and a uploading an invoice
- Go to
TODO(10)
remove thepreviousGroceries
callback:
- Remove
previousGroceries
list on the previous_groceries_page.dart. Because you will use the data from your backend. - Change every
TemporaryGroceryItem
withGroceryItem
andTemporaryPreviousGrocery
withGrocery
Now you should have three types of errors left:
groceryId
is required errorcurrentGrocery
is required errorpreviousGrocery
is undefined error
Start off by fixing the previousGrocery
error. For that, you need to fetch the submitted grocery lists. Go to previous_groceries_page.dart and add the below function to bottom of the class:
- This function checks the submission date and brings the ones that are not null. This way we only fetch the submitted grocery lists.
Update the body
property of the Scaffold
with the following to call the groceries function:
- This implementation gets the previous groceries and shows the list with the received items.
Now it is time to fix the groceryId
and currentGrocery
errors. For fixing them, you need to either create a grocery list or use the current grocery list.
Also, GraphQL API allows user to subscribe to the changes on items. Once the item is added, you would want to show it on all devices immediately.
For implementing these behaviors, add the following to the current_grocery_list_page.dart at the end of the class:
In the code above you:
- Created a new grocery item addition with
ModelMutations
- Sent the mutation to the API to create the grocery item entry in the backend
Lastly, update the build function to fetch the grocery information.
- Also, be sure to update
AddGroceryItemView
andFinalizeGroceryView
as shown:
Now it is time to add the comments to the previous grocery’s detail page. Go to previous_grocery_detail.dart. Add the following function:
- This function will fetch the grocery items for the current grocery id.
Lastly, update the Expanded
widget as follows, this way you can fetch the changes.
Adding Amplify Storage
To upload your invoices to the cloud, add Amplify Storage to the project.
For adding storage to your project, type amplify add storage
in your terminal and:
- Select Content (Images, audio, video, etc.) option
- Provide a friendly name or accept provided label
- Provide a bucket name or accept provided name
- Select Auth and guest users for the access
- Auth users could create, delete and read
- Guests could read
- No need to add a lambda function
Now you can run amplify push
to push your changes to the cloud.
Once it is pushed, add the storage library to the pubspec.yaml file and run flutter pub get
:
Now, go to main.dart to update _configureAmplify
:
Now go to the finalize_grocery_view.dart and update the TODO(11)
with:
Now if you run your application you should be able to see that the app can upload a receipt and finalize the groceries. Let’s add a code to show the image.
Now go to previous_grocery_details.dart file and add the following method to the end of the class to generate a URL to show the images or download them:
Afterwards, go to TODO(12)
to show the image by using the retrieved URL:
Right now the users can see the uploaded image on the detail page.
Conclusion
AWS Amplify’s update to its API, Storage and Analytics libraries will give developers a chance to expand their Flutter application’s support on web and desktop. This update will allow you to create Flutter application using the AWS Amplify libraries on iOS, Android, Web, and Desktop. As you build with AWS Amplify, please give us feedback over GitHub or Discord.