Skip to content

Commit c2e70df

Browse files
committed
Merge changes from master
1 parent 9abbf8a commit c2e70df

File tree

61 files changed

+554
-273
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+554
-273
lines changed

docs/angular/performance.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,37 @@ sidebar_label: Performance
44

55
# Angular Performance
66

7+
## *ngFor with Ionic Components
8+
9+
When using `*ngFor` with Ionic components, we recommend using Angular's `trackBy` option. This allows Angular to manage change propagation in a much more efficient way and only update the content inside of the component rather than re-create the component altogether.
10+
11+
By using `trackBy` you can provide a stable identity for each loop element so Angular can track insertions and deletions within the iterator. Below is an example of how to use `trackBy`:
12+
13+
**home.page.html**
14+
```html
15+
<ion-item *ngFor="let item of items; trackBy:trackItems">
16+
<ion-label>{{ item.value }}</ion-label>
17+
</ion-item>
18+
```
19+
20+
**home.component.ts**
21+
```typescript
22+
23+
items = [
24+
{ id: 0, value: 'Item 0' },
25+
{ id: 1, value: 'Item 1' },
26+
...
27+
]
28+
29+
trackItems(index: number, itemObject: any) {
30+
return itemObject.id;
31+
}
32+
```
33+
34+
In this example, we have an array of objects called `items`. Each object contains a `value` and an `id`. Using `trackBy`, we pass a `trackItems` function which returns the `id` of each object. This `id` is used to provide a stable identity for each loop element.
35+
36+
For more information on how Angular manages change propagation with `ngFor` see https://angular.io/api/common/NgForOf#change-propagation.
37+
738
## From the Ionic Team
839

940
[How to Lazy Load in Ionic Angular](https://ionicframework.com/blog/how-to-lazy-load-in-ionic-angular/)

docs/angular/your-first-app.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ Highlights include:
2121
* Deployed as a native iOS and Android mobile app using [Capacitor](https://capacitor.ionicframework.com), Ionic's official native app runtime.
2222
* Photo Gallery functionality powered by the Capacitor [Camera](https://capacitor.ionicframework.com/docs/apis/camera), [Filesystem](https://capacitor.ionicframework.com/docs/apis/filesystem), and [Storage](https://capacitor.ionicframework.com/docs/apis/storage) APIs.
2323

24-
It’s easy to get started. Find the complete app code referenced in this guide [on GitHub](https://github.com/ionic-team/photo-gallery-capacitor-ng).
24+
Find the complete app code referenced in this guide [on GitHub](https://github.com/ionic-team/photo-gallery-capacitor-ng).
2525

2626
## Download Required Tools
2727

@@ -60,6 +60,12 @@ Next, change into the app folder:
6060
$ cd photo-gallery
6161
```
6262

63+
Next we'll need to install the necessary Capacitor plugins to make the app's native functionality work:
64+
65+
```shell
66+
npm install @capacitor/camera @capacitor/storage @capacitor/filesystem
67+
```
68+
6369
### PWA Elements
6470

6571
Some Capacitor plugins, including the Camera API, provide the web-based functionality and UI via the Ionic [PWA Elements library](https://github.com/ionic-team/ionic-pwa-elements).

docs/angular/your-first-app/2-taking-photos.md

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,9 @@ $ ionic g service services/photo
1717
Open the new `services/photo.service.ts` file, and let’s add the logic that will power the camera functionality. First, import Capacitor dependencies and get references to the Camera, Filesystem, and Storage plugins:
1818

1919
```typescript
20-
import { Plugins, CameraResultType, Capacitor, FilesystemDirectory,
21-
CameraPhoto, CameraSource } from '@capacitor/core';
22-
23-
const { Camera, Filesystem, Storage } = Plugins;
20+
import { Camera, CameraResultType, CameraSource, Photo } from '@capacitor/camera';
21+
import { Filesystem, Directory } from '@capacitor/filesystem';
22+
import { Storage } from '@capacitor/storage';
2423
```
2524

2625
Next, define a new class method, `addNewToGallery`, that will contain the core logic to take a device photo and save it to the filesystem. Let’s start by opening the device camera:
@@ -29,14 +28,14 @@ Next, define a new class method, `addNewToGallery`, that will contain the core l
2928
public async addNewToGallery() {
3029
// Take a photo
3130
const capturedPhoto = await Camera.getPhoto({
32-
resultType: CameraResultType.Uri,
33-
source: CameraSource.Camera,
34-
quality: 100
31+
resultType: CameraResultType.Uri,
32+
source: CameraSource.Camera,
33+
quality: 100
3534
});
3635
}
3736
```
3837

39-
Notice the magic here: there's no platform-specific code (web, iOS, or Android)! The Capacitor Camera plugin abstracts that away for us, leaving just one method call - `Camera.getPhoto()` - that will open up the device's camera and allow us to take photos.
38+
Notice the magic here: there's no platform-specific code (web, iOS, or Android)! The Capacitor Camera plugin abstracts that away for us, leaving just one method call - `Camera.getPhoto()` - that will open up the device's camera and allow us to take photos.
4039

4140
Next, open up `tab2.page.ts` and import the PhotoService class and add a method that calls the `addNewToGallery` method on the imported servce:
4241

@@ -50,7 +49,7 @@ addPhotoToGallery() {
5049
}
5150
```
5251

53-
Then, open `tab2.page.html` and call the `addPhotoToGallery()` function when the FAB is tapped/clicked:
52+
Then, open `tab2.page.html` and call the `addPhotoToGallery()` function when the FAB is tapped/clicked:
5453

5554
```html
5655
<ion-content>
@@ -81,7 +80,7 @@ export interface Photo {
8180
}
8281
```
8382

84-
Back at the top of the file, define an array of Photos, which will contain a reference to each photo captured with the Camera.
83+
Back at the top of the file, define an array of Photos, which will contain a reference to each photo captured with the Camera.
8584

8685
```typescript
8786
export class PhotoService {
@@ -91,13 +90,13 @@ export class PhotoService {
9190
}
9291
```
9392

94-
Over in the `addNewToGallery` function, add the newly captured photo to the beginning of the Photos array.
93+
Over in the `addNewToGallery` function, add the newly captured photo to the beginning of the Photos array.
9594

9695
```typescript
9796
const capturedPhoto = await Camera.getPhoto({
98-
resultType: CameraResultType.Uri,
99-
source: CameraSource.Camera,
100-
quality: 100
97+
resultType: CameraResultType.Uri,
98+
source: CameraSource.Camera,
99+
quality: 100
101100
});
102101

103102
this.photos.unshift({
@@ -113,17 +112,19 @@ Next, move over to `tab2.page.html` so we can display the image on the screen. A
113112
<ion-content>
114113
<ion-grid>
115114
<ion-row>
116-
<ion-col size="6"
117-
*ngFor="let photo of photoService.photos; index as position">
115+
<ion-col
116+
size="6"
117+
*ngFor="let photo of photoService.photos; index as position"
118+
>
118119
<ion-img [src]="photo.webviewPath"></ion-img>
119-
</ion-col>
120+
</ion-col>
120121
</ion-row>
121122
</ion-grid>
122123

123124
<!-- ion-fab markup -->
124125
</ion-content>
125126
```
126127

127-
Save all files. Within the web browser, click the Camera button and take another photo. This time, the photo is displayed in the Photo Gallery!
128+
Save all files. Within the web browser, click the Camera button and take another photo. This time, the photo is displayed in the Photo Gallery!
128129

129130
Up next, we’ll add support for saving the photos to the filesystem, so they can be retrieved and displayed in our app at a later time.

docs/angular/your-first-app/3-saving-photos.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ public async addNewToGallery() {
2424
source: CameraSource.Camera, // automatically take a new photo with the camera
2525
quality: 100 // highest quality (0 to 100)
2626
});
27-
27+
2828
// Save the picture and add it to photo collection
2929
const savedImageFile = await this.savePicture(capturedPhoto);
3030
this.photos.unshift(savedImageFile);
@@ -43,7 +43,7 @@ private async savePicture(cameraPhoto: CameraPhoto) {
4343
const savedFile = await Filesystem.writeFile({
4444
path: fileName,
4545
data: base64Data,
46-
directory: FilesystemDirectory.Data
46+
directory: Directory.Data
4747
});
4848

4949
// Use webPath to display the new image instead of base64 since it's
@@ -63,7 +63,7 @@ private async readAsBase64(cameraPhoto: CameraPhoto) {
6363
const response = await fetch(cameraPhoto.webPath!);
6464
const blob = await response.blob();
6565

66-
return await this.convertBlobToBase64(blob) as string;
66+
return await this.convertBlobToBase64(blob) as string;
6767
}
6868

6969
convertBlobToBase64 = (blob: Blob) => new Promise((resolve, reject) => {

docs/angular/your-first-app/4-loading-photos.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ sidebar_label: Loading Photos
66

77
We’ve implemented photo taking and saving to the filesystem. There’s one last piece of functionality missing: the photos are stored in the filesystem, but we need a way to save pointers to each file so that they can be displayed again in the photo gallery.
88

9-
Fortunately, this is easy: we’ll leverage the Capacitor [Storage API](https://capacitor.ionicframework.com/docs/apis/storage) to store our array of Photos in a key-value store.
9+
Fortunately, this is easy: we’ll leverage the Capacitor [Storage API](https://capacitor.ionicframework.com/docs/apis/storage) to store our array of Photos in a key-value store.
1010

1111
## Storage API
1212

@@ -50,7 +50,7 @@ for (let photo of this.photos) {
5050
// Read each saved photo's data from the Filesystem
5151
const readFile = await Filesystem.readFile({
5252
path: photo.filepath,
53-
directory: FilesystemDirectory.Data
53+
directory: Directory.Data
5454
});
5555

5656
// Web platform only: Load the photo as base64 data

docs/angular/your-first-app/5-adding-mobile.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ Next, update the `savePicture()` method. When running on mobile, set `filepath`
6666
const savedFile = await Filesystem.writeFile({
6767
path: fileName,
6868
data: base64Data,
69-
directory: FilesystemDirectory.Data
69+
directory: Directory.Data
7070
});
7171

7272
if (this.platform.is('hybrid')) {
@@ -104,7 +104,7 @@ public async loadSaved() {
104104
// Read each saved photo's data from the Filesystem
105105
const readFile = await Filesystem.readFile({
106106
path: photo.filepath,
107-
directory: FilesystemDirectory.Data
107+
directory: Directory.Data
108108
});
109109

110110
// Web platform only: Load the photo as base64 data

docs/angular/your-first-app/6-deploying-mobile.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,13 @@ In order for some native plugins to work, user permissions must be configured. I
5353

5454
![Xcode Custom iOS Target Properties](/img/guides/first-app-cap-ng/xcode-info-plist.png)
5555

56-
5756
Each setting in `Info.plist` has a low-level parameter name and a high-level name. By default, the property list editor shows the high-level names, but it's often useful to switch to showing the raw, low-level names. To do this, right-click anywhere in the property list editor and toggle "Raw Keys/Values."
5857

59-
Locate the `NSCameraUsageDescription` Key (it should exist already if you followed along with this tutorial) and set the Value to something that describes why the app needs to use the camera, such as "To Take Photos." The Value field is displayed to the app user when the permission prompt opens.
58+
Add the `NSCameraUsageDescription` Key and set the Value to something that describes why the app needs to use the camera, such as "To Take Photos." The Value field is displayed to the app user when the permission prompt opens.
59+
60+
Follow the same process to add the other two Keys required of the Camera plugin: `NSPhotoLibraryAddUsageDescription` and `NSPhotoLibraryUsageDescription`.
6061

61-
Next, click on `App` in the Project Navigator on the left-hand side, then within the `Signing & Capabilities` section, select your Development Team.
62+
Next, click on `App` in the Project Navigator on the left-hand side, then within the `Signing & Capabilities` section, select your Development Team.
6263

6364
![Xcode - Selecting Development Team](/img/guides/first-app-cap-ng/xcode-signing.png)
6465

docs/angular/your-first-app/7-live-reload.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@ sidebar_label: Live Reload
44

55
# Rapid App Development with Live Reload
66

7-
So far, we’ve seen how easy it is to develop a cross-platform app that works everywhere. The development experience is pretty quick, but what if I told you there was a way to go faster?
7+
So far, we’ve seen how easy it is to develop a cross-platform app that works everywhere. The development experience is pretty quick, but what if I told you there was a way to go faster?
88

9-
We can use the Ionic CLI’s [Live Reload functionality](https://ionicframework.com/docs/cli/livereload) to boost our productivity when building Ionic apps. When active, Live Reload will reload the browser and/or WebView when changes in the app are detected.
9+
We can use the Ionic CLI’s [Live Reload functionality](https://ionicframework.com/docs/cli/livereload) to boost our productivity when building Ionic apps. When active, Live Reload will reload the browser and/or WebView when changes in the app are detected.
1010

1111
## Live Reload
1212

13-
Remember `ionic serve`? That was Live Reload working in the browser, allowing us to iterate quickly.
13+
Remember `ionic serve`? That was Live Reload working in the browser, allowing us to iterate quickly.
1414

1515
We can also use it when developing on iOS and Android devices. This is particularly useful when writing code that interacts with native plugins - we must run it on a device to verify that it works. Therefore, being able to quickly write, build, test, and deploy code is crucial to keeping up our development speed.
1616

@@ -29,9 +29,9 @@ The Live Reload server will start up, and the native IDE of choice will open if
2929
With Live Reload running and the app open on your device, let’s implement photo deletion functionality. Open `tab2.page.html` and add a new click handler to each `<ion-img>` element. When the app user taps on a photo in our gallery, we’ll display an [Action Sheet](https://ionicframework.com/docs/api/action-sheet) dialog with the option to either delete the selected photo or cancel (close) the dialog.
3030

3131
```html
32-
<ion-col size="6"
32+
<ion-col size="6"
3333
*ngFor="let photo of photoService.photos; index as position">
34-
<ion-img [src]="photo.webviewPath"
34+
<ion-img [src]="photo.webviewPath"
3535
(click)="showActionSheet(photo, position)"></ion-img>
3636
</ion-col>
3737
```
@@ -41,7 +41,7 @@ Over in `tab2.page.ts`, import Action Sheet and add it to the constructor:
4141
```typescript
4242
import { ActionSheetController } from '@ionic/angular';
4343

44-
constructor(public photoService: PhotoService,
44+
constructor(public photoService: PhotoService,
4545
public actionSheetController: ActionSheetController) {}
4646
```
4747

@@ -98,7 +98,7 @@ public async deletePicture(photo: Photo, position: number) {
9898

9999
await Filesystem.deleteFile({
100100
path: filename,
101-
directory: FilesystemDirectory.Data
101+
directory: Directory.Data
102102
});
103103
}
104104
```

docs/components.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
---
2+
title: UI Components | User Interface Application Building Components
3+
description: Ionic Framework comes stock with a number of high-level UI components, including cards, lists, and tabs to quickly and easily build your app's user interface.
24
hide_table_of_contents: true
35
---
46

@@ -50,7 +52,7 @@ import DocsCards from '@site/src/components/DocsCards';
5052
<p>Floating action buttons are circular buttons that perform a primary action on a screen.</p>
5153
</DocsCard>
5254

53-
<DocsCard header="Icons" href="https://ionicons.com" img="/icons/feature-component-icons-icon.png">
55+
<DocsCard header="Icons" href="https://ionic.io/ionicons" img="/icons/feature-component-icons-icon.png">
5456
<p>Beautifully designed icons for use in web, iOS, Android, and desktop apps.</p>
5557
</DocsCard>
5658

docs/intro/cdn.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,4 +159,4 @@ Ionicons is packaged by default with the Ionic Framework, so no installation is
159159
<script nomodule src="https://cdn.jsdelivr.net/npm/ionicons/dist/ionicons/ionicons.js"></script>
160160
```
161161

162-
> See [Ionicons usage](https://ionicons.com/usage) for more information on using Ionicons.
162+
> See [Ionicons usage](https://ionic.io/ionicons/usage) for more information on using Ionicons.

0 commit comments

Comments
 (0)