Isn’t it nice to have all the traditional backend features on the web? Appwrite cloud alleviates the need to manage a server. Appwrite cloud is a backend as a service (BaaS) with all the necessary APIs to build your modern application. These APIs assist in building client and server-side applications. A use case of Appwrite is the Database API, which assists in implementing CRUD (create, read, update, delete) features in your application.
This article will show you how to use an input element to create, store, view and delete text in Flutter using Appwrite.
Prerequisites
To follow along with this tutorial, the following are required:
- Xcode (with developer account for Mac users)
- iOS Simulator, Android Studio, or Chrome web browser to run the application
- Appwrite cloud access. It is currently in beta testing.
Creating an Appwrite project
You can apply to the Appwrite cloud to access the private beta. Once you access Appwrite’s cloud private beta, create a project and fill in the project's name and id; otherwise, use Appwrite locally with Docker or DigitalOcean droplet.
Also, you will need a database collection to perform CRUD operations. Head to Databases, select Create Database
, and fill in the database name and ID
. After, create a new collection by selecting Create collection
and filling in the subsequent name and ID
.
It is necessary to have parameters to hold data within your collection. Thus, head to the attributes section within the collection created earlier and add the attributes in the following table to the collection:
Attribute key | Attribute type |
---|---|
title | String |
subtitle | String |
Finally, head to the collection settings section and set the collection and document level permission to role:any
and check all the CRUD permissions. These permissions allow anyone to create, read, update, and delete documents from the collection.
Cloning the UI template
This section uses a UI template containing user registration and login code. Let’s clone the repository specified in the prerequisites. Check out the official GitHub docs to learn more about cloning a repository.
After cloning the UI to your local storage, open it in your preferred code editor and run the command below:
flutter pub get
This command obtains all the dependencies listed in the pubspec.yaml
file in the current working directory and their transitive dependencies. Next, run the command flutter run
, and your application should look like the image below:
The lib
directory tree should look like this:
lib/
├─ auth/
│ ├─ app_provider.dart
├─ model/
│ ├─ documentmodel.dart
├─ pages/
│ ├─ components/
│ │ ├─ add_item_modal.dart
│ │ ├─ edit_item_modal.dart
│ ├─ home.dart
├─ main.dart
Explaining the UI and functionalities
Functionalities
Before beginning, create a file app_constants.dart
to store important constants from Appwrite. Update the app_constants.dart
with the code below:
javascript
class Appconstants {
static const String projectid = "<projectID>";
static const String endpoint = "<cloud endpoint>";
static const String dbID = "<database ID>";
static const String collectionID = "<collection ID>";
}
The project utilizes the Provider package for its state management purposes. Thus, the app_provider.dart
file defines a class named AppProvider
that is implementing ChangeNotifier
. The AppProvider
class contains various methods for creating, listing, updating, and removing documents in a database using the Appwrite
package.
In the code above, the AppProvider
class implements the ChangeNotifier
class to handle changes in your application’s state. The Client
class instance, named client
, is tasked with communicating with the Appwrite API.
The Account
and Databases
instances communicate with the account and database API. This allows you to create a user account on the client side and perform the CRUD operations.
The code above uses the initialize
method to set up the client
instance by setting the endpoint and project and creating an anonymous session for the user.
To utilize the CRUD operations in Appwrite, here is a summary of the document-based methods in the code:
-
createDocument
method takes innewTitle
,newSubtitle
, andcontext
parameters to create a new document in the specified database and collection. It then adds the new document to the list of documents and closes the add document screen. -
listDocument
method lists all the documents in the specified database and collection. It maps the returned list of documents to a list ofListItem
objects and sets the_listItem
variable to this list.
You can use a model class to map the JSON when getting a list of documents from Appwrite. Thus, add the code below in documentmodel.dart
file
javascript
class UserFields {
static const String id = "\$id";
static const String title = "title";
static const String subtitle = "subtitle";
}
class ListItem {
String? id;
String? title;
String? subtitle;
ListItem({
required this.id,
required this.title,
required this.subtitle,
});
ListItem.fromJson(Map<String, dynamic> json) {
id = json[UserFields.id];
title = json[UserFields.title];
subtitle = json[UserFields.subtitle];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data[UserFields.id] = id;
data[UserFields.title] = title;
data[UserFields.subtitle] = subtitle;
return data;
}
}
- the
updateDocument
method takes indocumentId
,updateTitle
, andupdateSubtitle
parameters to update the specified document in the database with the new title and subtitle. - the
removeDocument
method takes indocumentId
andindex
parameters to delete the specified document from the database and remove it from the list of documents.
Overall, the AppProvider
class provides a way to manage documents in an Appwrite database in a Flutter application.
UI (User interface)
The pages folder consists of the entirety of the user interface. The user interface consists of a centered container whose primary action is to display a list of created items. The Container has an ElevatedButton
widget with an onPressed
action displaying a modal. This displayed modal consists of a formfield (input and button) that takes values to create an item.
To perform an update action, wrap the list in an Inkwell
widget and attach an onTap
property that shows an editable modal that updates the list and the document on Appwrite.
javascript
//Home.dart
Widget appContainer(BuildContext context, state) {
return Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
margin: const EdgeInsets.only(left: 50, right: 50, top: 50),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(25.0),
color: const Color.fromARGB(238, 238, 232, 198),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.all(20.0),
child: ElevatedButton.icon(
onPressed: () {
// Handle the tap event by displaying a dialog box where the user can edit the data
showDialog(
context: context,
builder: (BuildContext context) {
// Return the dialog widget
return const AddItemDialog();
},
);
},
icon: const Icon(
Icons.add,
size: 24.0,
),
label: const Text("Add Item"),
),
),
items(state)
],
));
}
Widget items(state) {
return Expanded(
child: Container(
child: state.listItem.isEmpty
? const Center(
child: Text(
"No items found",
style: TextStyle(fontWeight: FontWeight.w800),
),
)
: listContainer(state)));
}
Widget listContainer(state) {
return ListView.builder(
itemCount: state.listItem.length,
itemBuilder: (BuildContext context, int index) {
return InkWell(
onTap: () {
// Handle the tap event by displaying a dialog box where the user can edit the data
showDialog(
context: context,
builder: (BuildContext context) {
// Return the dialog widget
return EditListItemDialog(
item: state.listItem[index],
onSave: (ListItem editedItem) {
// Update the item in the list with the edited data
state.listItem[index] = editedItem;
// Rebuild the UI to reflect the updated data
setState(() {});
},
);
},
);
},
child: ListTile(
title: Text(state.listItem[index].title),
subtitle: Text(state.listItem[index].subtitle),
trailing: IconButton(
icon: const Icon(Icons.delete),
onPressed: () =>
state.removeReminder(state.listItem[index].id, index),
),
),
);
},
);
}
Add item AlertDialog
Edit/Update item AlertDialog
When you run the application, your result should look like the GIF below:
Conclusion
Though still in beta testing, Appwrite Cloud is a game-changer, enabling the creation of backend functionalities swiftly and easily while providing the same benefits as using Appwrite locally. This tutorial has shown how to create CRUD features using the Appwrite cloud and Flutter.