13. Conclusion
We have developed the [Ionic] client for the [RdvMedecins] application. For the user, it provides the same screens as the HTML application from course [NestJS], as well as the [Vue.js], [Angular], and [React], and the [Flutter] client from the previous courses; it is a mobile app installed on the phone, and it is ALSO—without any changes—a web app.
The server, however, has not changed. Its API and JSON—whose contract (routes, bodies, codes, and error keys) was sufficient to write the client without ever reading its code—serves both a browser and a phone interchangeably. On the phone, there is no browser to store the token cookie: this is handled by the native code of [Android], via the [CapacitorHttp] plugin, that played this role, without a single line of code in the application (the [Flutter] client, on the other hand, had to do so using its [CookieClient] class). Security remains unchanged: it is still the server that authenticates users, verifies roles and management rules, and decides what a patient is authorized to view.
Readers who have taken the [Flutter] course can compare the two:
- both are based on the same idea: the interface is a function of the state. A [Flutter] widget has a [build()] method that returns a widget tree; a [Angular] component has a template that reads signals. When the state changes ([setState] / a signal), the screen is updated. With signals, [Angular] even knows exactly which parts of the template depend on which signal: it has nothing to compare;
- [Flutter] draws each pixel itself, using its own engine; [Ionic] generates HTML, which the phone’s WebView (the [Chrome] engine) renders. This results in a lightweight and intuitive web application (it’s a regular web page), development tools that are standard web tools (the [Chrome] development tools, available on both the computer and the phone), and reusable expertise (HTML, CSS, [TypeScript], [Angular]). The trade-off: the app depends on the phone’s WebView, and a highly animated or heavily loaded interface runs less smoothly there than with the [Flutter] engine;
- the components of [Ionic] mimic native components in two modes: [md] ([Android]) and [ios] ([iPhone]): the same application takes on the look and feel of each system. [Flutter] provides both widget families ([Material] and [Cupertino]), but it is up to the developer to choose;
- [Angular] provides much more than [React], and about as much as [Flutter]: router, forms, HTTP client, dependency injection, formatting; [Ionic] adds mobile components and stack navigation; [Capacitor] adds phone access. The client did not require any other libraries. Layout, on the other hand, is handled by CSS (the grids and utility classes from [Ionic]), while [Flutter] uses widgets ([Column], [Row], [Padding]...);
- [TypeScript], in strict mode, and strict template validation ([strictTemplates]) detect most of the errors that [Dart] detects at compile time: a missing [null] value, a misspelled property, or an argument of the wrong type. However, the types from [TypeScript] disappear at runtime: a malformed JSON is not detected upon reception, as it was by the filtering performed by [Dart] 3;
- In return: two files per component (the class and the template), a decorator to fill out ([imports], [templateUrl]), and, between [Angular], [Ionic] and [Capacitor], three tools—you need to understand the role of each one.
The concepts of [Ionic] and [Angular] covered in this course (components, signals, templates, inputs and outputs, lifecycle, dependency injection, directives, router and guards, reactive forms, [Promise] and [Observable], internationalization, and [Capacitor] plugins) are common to all [Ionic] applications. For further reading:
- official documentation: ionicframework.com/docs (the list of components, with their properties and examples), angular.dev (its tutorial and guides), and capacitorjs.com/docs;
- tests: the unit tests for [Angular] ([ng test], along with [Vitest]), which interact with a component without an actual browser, and the end-to-end tests ([Playwright], used to generate the screenshots in this document), which run the actual application in a browser;
- state management libraries ([NgRx] and its counterpart [SignalStore]), useful when the shared state becomes very complex;
- the [Capacitor] plugins: secure token storage, notifications, camera, geolocation, sharing, and more—one plugin per need, whether official or community-developed;
- Progressive Web Apps (PWA): the web version of the app, installable and usable offline, with the [@angular/pwa] package;
- iPhone: the same code generates an [iOS] app ([npx cap add ios]), to be built on top of [Mac] using [Xcode]; the components of [Ionic] automatically take on the appearance of [iOS] unless [md] mode is forced.