View Story. View Comments. User Management. Manage Favorites. Share Stories. Common Components. Advanced Topics. End-to-End Test and Build. Back Matter Pages It's organized around implementing different user stories. For each story, this book not only talks about how to implement it but also explains related Ionic and Firebase concepts in detail. Using Apache Cordova, developers can create a new type of mobile app—a hybrid mobile app.
Ionic Firebase mobile app development hybrid mobile app cordova phone development. Authors and affiliations Fu Cheng 1 1.
Sandringham New Zealand. About the authors Fu Cheng is a full-stack software developer living in Auckland, New Zealand with rich experience in appling best practices in real product development and strong problem solving skill. He is the author of the book Understanding Java 7: The Core Techniques and Best Practices Simplified Chinese edition , which covers the new features of Java SE 7 and provides a deep dive of Java platform core features, including JVM internals, byte code manipulation, class loader, generics, security, concurrent programming and serialization.
For this app, we choose blank as the starter template. We use the following command to create the basic code structure of this app. We also enabled Cordova integration for this app. This is a very important step for us to know where to add new code. These config files are used by different libraries or tools.
This file contains various metadata of this project, including name, description, version, license, and other information. The value of this property is a JavaScript object with other configuration values. For example, plugins specifies the installed plugins for this app, while platforms specifies supported platforms. The content of package. The content of this file is usually managed by Cordova CLI. For example, compilerOptions specifies the compiler options.
In these compiler options, emitDecoratorMetadata and experimentalDecorators must be enabled to use Angular decorators. More details about tsconfig. From this file, we can see the app is an Ionic 4 project with Cordova integration.
Because the project is created from an Ionic starter template, it also has the file ionic. The file ionic. Ionic 4 provides a default configuration. This app has subdirectories ios and android for iOS and Android platforms, respectively.
These files are generated by Cordova and should not be edited manually. The directory resources contains the image files for the app icons and the splash screen. The index. The markup in index. The file variables. Development and production environments are defined by default.
Listing shows the content of the file environment. We can add extra environment-specific configurations into these two files. Each page has its own subdirectory. It has only one page. This file contains only a single empty class AppModule. Most of the code is using NgModule decorator to annotate the class AppModule. The imported module IonicModule. The method IonicModule. These components and directives can be used anywhere in the module. The property declarations contains only the AppComponent, while entryComponents is an empty array.
StatusBar and SplashScreen in the property providers are used by Cordova. Here the path home points to the HomePageModule. In the decorator Component, the property templateUrl is set to the file app. The constructor function declares a public parameter platform of type Platform. Angular injector creates the instance of Platform and provides it when this component is instantiated. The method ready of Platform returns a promise that is resolved when the Cordova platform is ready to use. Here it set the styles of the status bar and hide the splash screen.
The component ion-router-outlet is the Ionic Angular integration of Angular Router. This file can also be used as the entry point to import other Sass files. Each component has five files with similar names. This is the common code convention when developing components in Ionic 4.
Some of these polyfills are commented out. You can selectively enable them based on the browser compatibility requirements for your apps. This file is referenced in angular. We went through the skeleton code to understand how the code of an Ionic 4 app is organized. This skeleton code is the starting point of the example app. Because this is the first chapter about implementing user stories, some common concepts are introduced in this chapter.
We are going to cover the following topics in this long chapter. This chapter also shows how to gradually improve the implementation of a user story to make it more user friendly and reliable, which is a recommended practice in actual product development.
The API is actually a public Firebase database. We should start from the user experience that we want to provide. After the app starts, the user is presented with a list of top stories on Hacker News.
The user can see basic information of each story in the list, including title, URL, author, published time, and score. The information for each story should be declared in the model. Each story has these properties: id, title, url, by, time, and score. We declare the model as a TypeScript interface in Listing Here we use a more general model name Item instead of Story because comments and replies to comments are also items and can share the same model.
However, we define a type Items in Listing to represent a list of items. Even though Items is currently just an alias of Item[], declaring a dedicated type Items enables potential future improvements without changing existing code. For example, the list of items may only represent a paginated subset of all items, so properties related to pagination like limit, offset, or total may need to be added to the model Items in the future.
All the existing code can still use the same type Items. We can use the Ionic component ion-list. The component ion- list is a generic container of an array of items. Items in the list can be text only or text with icons, avatars, or thumbnails. Items can be a single line or multiple lines. We can use the component ion-list to display top stories. Let's start with the introduction of the component ion-list. The component ion-list is the container of items, while the component ion-item represents a single item in the list.
The component ion-item has three slots. The default slot is for content displayed in the item. The slots with name start and end appear at the start or end position of the item, respectively. Items in the list can be separated using the component ion- item-divider. In Listing , a title is added to the list and a divider separates two items. The component ion-list-divider has three slots. The default slot is for content displayed in the divider.
The slots with name start and end appear at the start or end position of the divider, respectively. Grouping of items can be done using the component ion-item-group. Listing is an example of the simple contacts list. We use the component ion-item-divider to show the name of each group. These icons can be displayed using the component ion-icon with the name of the icon. For example, the icon book has three variations with names ios-book, ios-book-outline, and md-book. If the name book is used, the displayed icon is auto-selected based on the current platform.
We can also use the property ios and md to explicitly set the icon for different platforms. The second ion-item has the icon build at both sides of the text, but the icon on the left side is inactive.
The last ion-item shows the icon ios- happy on iOS, but shows the icon md-sad on Android. In Ionic Core, avatars are created by using the component ion-avatar to wrap img elements.
In Ionic Core, thumbnails are created by using the component ion-thumnail to wrap img elements. This is made clear by checking the position of the bottom line that separates each item. We need to create a component for the list of items and another component for each item in the list. These two components are added to the module components that are created using the following command.
The option --flat false means generating a separate directory for the module. We can use the following command to generate the component to display items. The option --flat false means the components files will be put into its own directory. In Listing , class ItemComponent is decorated with Component. The property item is the Item object to display. The type of the property item is the model interface Item we defined in Listing The Input decorator factory of the class instance property item means the value of this property is bound to the value of the property item in its parent component.
The Input decorator factory can take an optional argument that specifies a different name of the bound property in the parent component: for example, Input 'myItem' binds to the property myItem in the parent component.
In the template, we can use item. The layout of the item is simple. The title is displayed in an HTML h2 element. The score, author, and published time are displayed in the same row after the title. The URL is displayed at the bottom. The implementation of timeAgo uses the moment.
The styles in Listing only apply to ItemComponent. The scoped CSS is supported by Angular by default. The pseudo- class selector :host targets styles in the element that hosts the component. In Listing of its main TypeScript file items. It also has the property items of type Items.
The Angular directive ngFor is used to loop through the array of items. We can use the directive ngIf to display different views based on the length of the list; see Listing So far, we only need to add unit tests for the component ItemsComponent. Jasmine is used to write test specs, while Karma is used to run tests on different browsers. Listing shows the partial configuration related to testing. Here we use Jasmine and Angular devkit.
Here we use plugins for Jasmine, Chrome launcher, Angular devkit, and different reporters. Here we only use Chrome. The file test. After Angular core testing modules are imported, we initialize the test bed for component testing, then start the testing.
All test spec files with suffix. A test suite file uses the same name as the component it describes but with a different suffix. For example, items. The method beforeEach is used to add code to execute before execution of each spec. TestUtils used in beforeEach is an important utility class; see Listing The method beforeEachCompiler takes a list of components and providers as the input arguments and uses the method configureIonicTestingModule to configure the testing module.
The testing module imports Ionic modules and adds Ionic providers. This is required to set up the runtime environment for Ionic. After the testing module is configured, the components are compiled. After the compilation, the method TestBed. In the test suite, the returned test fixture and component instance are used for verifications.
The first spec is to test that the list component can display a list of items. The fixture. The By. We can use the property nativeElement to get the native DOM element from the query result. The second spec is to test that the list component displays correct message when no items are in the list. The property items is set to an empty array, so there should be a p element with text No items. Karma launches the Chrome browser and runs the tests inside of the browser.
The testing results will also be reported in the console. In this page, we can see the results of all specs. We can also use Chrome Developer Tools to debug errors in the test scripts. Below are some tips to make debugging of unit tests easier. If you want to run a single test spec, just change the method describe to fdescribe, then only this test spec will be executed. This is good for testing since we can easily verify the test results.
Now we are going to use real data to render the items list. In Angular apps, code logic that deals with external resources should be encapsulated in services. Before creating the service, we need to create a new module for all services. This can be done by using Angular CLI with the following command. The command g is a shorthand of generate, which can generate different kinds of objects in Angular.
Then we need to modify file app. After creating the module, we can continue to use the command g to generate the service itself. The file services. ItemService in Listing has a single method load offset, limit to load a list of items. Because there can be many items, the method load only loads a subset of items.
For example, load 0, 10 means loading the first 10 items. Items is the model type we defined in Listing It used to be just an alias of Item[], but now we update it to include more information related to pagination; see Listing The type Items now has both properties offset and limit that match the parameters in the method load. It also has the property total that represents the total number of items. The property total is optional, because in some cases the total number may not be available.
The property results represents the actual array of items. This page is also the new index page. We continue to use Angular CLI for components generation.
In Listing , we generate the module top-stories for the top stories page and the component top-stories for this page. You may notice the option --routing when creating the module top-stories. This option is for routing support with Angular Router.
We start from the file top-stories. By implementing this interface, when TopStoriesComponent finishes initialization, the method ngOnInit will be invoked automatically. We use ItemService to load items and use ItemsComponent to display them. TopStoriesPage class has a property items of type Items.
The value of this property is passed to the ItemsComponent for rendering. In the method ngOnInit , the method load of ItemService is invoked. When the loading is finished, loaded items is set as the value of the property items. TopStoriesComponent class also implements the interface OnDestroy. In the method ngOnDestroy , we use the method unsubscribe of the Observable subscription to make sure resources are released.
Because loading items is asynchronous, the value of items is undefined until the loading is finished successfully. The component app-items already handles the case when the property is undefined.
The best solution is to create a service mock. The implementation of the method load in ItemServiceMock creates items based on input arguments offset and limit. With this service mock, we can generate any number of items. We can use this spec file top-stories. When using the method TestUtils. Here we use the Angular class provider. This is because TopStoriesPage uses an asynchronous service ItemService that makes testing more complicated.
At first, we need to use the method async from Angular to wrap the testing function. The first fixture. In the resolve callback of the promise returned by whenStable , the second fixture. At last, we verify the rendered DOM structure matches the expected result. We start from the Firebase basics. To create new Firebase projects, you need to have a Google account. Firebase offers two products for data persistence. These two products have different data models for persistence.
Cloud Firestore offers richer features, better performance, and scalability. But Cloud Firestore is currently in beta. If you want to have a stable solution, Realtime Database is a better choice. If you want to try new features and a new data model, Cloud Firestore should be the choice. This book covers both products. Hacker News data is stored in the Realtime Database, so we use it to retrieve the data. We start from the Realtime Database. This tree structure is very flexible for all kinds of data.
For an e-commerce app, its database can be organized as in Listing The property products is a map of product id to its properties. The property customers is a map of customer id to its properties. The property orders is a map of order id to its properties. If you think of the whole JSON object as a file directory, then the path describes how to navigate from the root to a data value. The path is used when reading or writing data, as well as configuring security rules. The Firebase web SDK is a general library for all kinds of web apps.
For Angular apps, AngularFire2 is a better choice that offers tight integration with Angular. In this section, we only discuss the usage of the general web SDK, which is very important to understand how Firebase works. AngularFire2 is used in the Ionic app and will be discussed later. This is done by calling the method database of the global object firebase. The return result is an instance of class firebase. The return result ref is an instance of the class firebase.
After adding a listener of a certain event to the object ref, when the event is triggered, the listener will be invoked with related data. In Listing , a listener of the event value is added to the object ref using the method on eventType, callback.
The event listener will also be triggered when the listener is attached to get the initial data. DataSnapshot object. It represents the snapshot of data at the given path when the event occurs.
This DataSnapshot object is only used for retrieving data. Table This method should be used instead of checking val! The function receives the DataSnapshot object of each child as the argument. After an event listener of a Reference object is added, we can use the method off eventType, callback to remove the listener. To make sure all event listeners are correctly removed, for a certain event type on a certain reference, the number of invocation times of the method on should match the number of invocation times of the method off.
Event listeners are not inherited. Each event listener should be removed individually. Listing shows three different ways to remove event listeners. The method set value, onComplete replaces the data at the path of the current reference object. The method set will override all data under that path, so be careful when using it.
The method update values, onComplete selectively updates children data specified by relative paths in the value. Only children listed in the values will be replaced. The method update supports updating multiple values.
If you prefer to use Promise instead of callback functions, the return value of set or update is a firebase. Promise object that is similar to the standard Promise object. If the data to store is a list of objects without meaningful business ids, we should use the method push value, onComplete to add a new object to the list. The method push creates a unique value as the key of the object to add. The return value of the method push is a new Reference object points to the newly created path.
Listing shows two different ways to use push. This could affect performance for large objects or arrays. Sorting also cannot be done either. To filter and sort data under a given path, we can use other methods in the Reference object that return firebase.
Query objects. Listing shows an example of sorting the products by price. In Listing , we sort the products by price first, then filter it to only return the first child. Only items with a value greater than or equal to the specified value or key will be included. Only items with a value less than or equal to the specified value or key will be included. Only items with a value equal to the specified value or key will be included. Login Sign up. Building mobile apps with ionic 2 pdf download.
Nov 24th, Not a member of Pastebin yet? Sign Up , it unlocks many cool features!
0コメント