41
loading...
This website collects cookies to deliver better user experience
ionic serve
, you'll have a really simple task management web application. You can register (using any user/password combination, Realm takes care of your onboarding needs). You can log in, have a look at your tasks, and add new tasks.Login in the Web App | Browsing Tasks |
---|---|
![]() |
![]() |
npm install -g @ionic/cli
src/App.tsx
, in the line:export const APP_ID = '<Put your Realm App Id here>';
APP_ID
is set, run:$ npm run build
$ ionic cap add ios
package.json
and ran npm install
to update Capacitor.package.json
fragment:...
"dependencies": {
"@apollo/client": "^3.4.5",
"@capacitor/android": "3.2.2",
"@capacitor/app": "1.0.2",
"@capacitor/core": "3.2.0",
"@capacitor/haptics": "1.0.2",
"@capacitor/ios": "3.2.2",
...
ios
directory. If we enter that folder, we’ll see an App
directory that has a CocoaPods-powered iOS app. To run this iOS app, we need to:cd ios
. You’ll find an App
directory. cd App
pod repo update && pod install
, as usual in a native iOS project. This updates all libraries’ caches for CocoaPods and then installs the required libraries and dependencies in your project.App.xcworkspace
file with Xcode. From Terminal, you can just type open App.xcworkspace
.Login in the iOS App | Browsing Tasks |
---|---|
![]() |
![]() |
cd
back to the root of the project and type in a terminal:ionic cap android
ionic capacitor run android -l --host=10.0.1.81
10.0.1.81
is my own IP address. As you can see, if you have more than one Emulator or even a plugged-in Android phone, you can select where you want to run the Ionic app.Adding a task in Android | Browsing Tasks in Android |
---|---|
![]() |
![]() |
pollInterval
argument. I told you it was awesome. You set the time interval in milliseconds to refresh the data.useTasks.ts
, our function to get all tasks will look like this, auto-refreshing our data every half second.function useAllTasksInProject(project: any) {
const { data, loading, error } = useQuery(
gql`
query GetAllTasksForProject($partition: String!) {
tasks(query: { _partition: $partition }) {
_id
name
status
}
}
`,
{ variables: { partition: project.partition }, pollInterval: 500 }
);
if (error) {
throw new Error(`Failed to fetch tasks: ${error.message}`);
}
// If the query has finished, return the tasks from the result data
// Otherwise, return an empty list
const tasks = data?.tasks ?? [];
return { tasks, loading };
}
IonRefresher
to our Home component:<IonPage>
<IonHeader>
<IonToolbar>
<IonTitle>Tasks</IonTitle>
<IonButtons slot="end">
<IonButton onClick={addNewTask}>
<IonIcon slot="icon-only" icon={add}></IonIcon>
</IonButton>
</IonButtons>
</IonToolbar>
</IonHeader>
<IonContent fullscreen>
<IonRefresher slot="fixed" onIonRefresh={doRefresh}>
<IonRefresherContent></IonRefresherContent>
</IonRefresher>
<IonHeader collapse="condense">
<IonToolbar>
<IonTitle size="large">Tasks</IonTitle>
</IonToolbar>
</IonHeader>
<IonList>
{loading ? <IonLoading isOpen={loading} /> : null}
{tasks.map((task: any) => (
<TaskItem key={parseInt(task._id)} {...task}></TaskItem>
))}
</IonList>
</IonContent>
</IonPage>
IonRefresher
component will add the pull-to-refresh functionality with an included loading indicator tailored for each platform.<IonRefresher slot="fixed" onIonRefresh={doRefresh}>
<IonRefresherContent></IonRefresherContent>
</IonRefresher>
doRefresh
and there, we just reload the whole page.const doRefresh = (event: CustomEvent<RefresherEventDetail>) => {
window.location.reload(); // reload the whole page
event.detail.complete(); // we signal the loading indicator to hide
};
IonItemSliding
control. In this case, we want a swipe from the start of the control. This way, we avoid any ambiguities with right-to-left vs. left-to-right languages. When the user taps on the new “Delete” button (which will appear red as we’re using the danger color), deleteTaskSelected
is called.<IonItemSliding ref={slidingRef} className={'status-' + task.status}>
<IonItem>
<IonLabel>{task.name}</IonLabel>
</IonItem>
<IonItemOptions side="end">
<IonItemOption onClick={toggleStatus}>Status</IonItemOption>
</IonItemOptions>
<IonItemOptions side="start">
<IonItemOption onClick={deleteTaskSelected} color="danger">Delete</IonItemOption>
</IonItemOptions>
</IonItemSliding>
useTaskMutations.ts
:const deleteTaskSelected = () => {
slidingRef.current?.close(); // close sliding menu
deleteTask(task); // delete task
};
$ git clone https://github.com/mongodb-developer/ionic-realm-demo
$ git checkout observe-changes