diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/README.md b/i18n/ja/docusaurus-plugin-content-docs/current/README.md new file mode 100644 index 00000000000..12005305278 --- /dev/null +++ b/i18n/ja/docusaurus-plugin-content-docs/current/README.md @@ -0,0 +1,17 @@ +# Docs folder + +The `/docs` folder houses all markdown files. The page structure loosely maps to the routing on the site since paths can be changed in the frontmatter. + +## Versioning + +This folder can also contain components, assets, and whatever else is meant to be versioned when the docusaurus versioning script is run. For example, if there is a page component that is only relevant to the `layout` section in the current version of Ionic, it could be added to a `_components/` folder in `docs/layout/`. When the versioning script is run, the component will be copied to `versioned_docs/version-{X}/layout/_components/` and there will now be a separate component in `docs/layout/_components/` that can be deleted or updated to the latest version. The same concept applies to images and other files. + +If components are meant to be shared across versions, they can be put in `src/components/`. If images and other served files are meant to be shared across versions they can be put in `static/`. + +## Auto Generated Files + +All markdown files in these directories are generated from [scripts](/scripts): + +- `docs/api/` +- `docs/cli/commands/` +- `docs/native/` diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/angular/build-options.md b/i18n/ja/docusaurus-plugin-content-docs/current/angular/build-options.md new file mode 100644 index 00000000000..04a9946739b --- /dev/null +++ b/i18n/ja/docusaurus-plugin-content-docs/current/angular/build-options.md @@ -0,0 +1,720 @@ +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Build Options + +Developers have two options for using Ionic components: Standalone or Modules. This guide covers both options as well as the benefits and downsides of each approach. + +While the Standalone approach is newer and makes use of more modern Angular APIs, the Modules approach will continue to be supported in Ionic. Most of the Angular examples on this documentation website use the Modules approach. + +## Standalone + +:::info +Ionic UI components as Angular standalone components is supported starting in Ionic v7.5. +::: + +### Overview + +Developers can use Ionic components as standalone components to take advantage of treeshaking and newer Angular features. This option involves importing specific Ionic components in the Angular components you want to use them in. Developers can use Ionic standalone components even if their Angular application is NgModule-based. + +See the [Standalone Migration Guide](#migrating-from-modules-to-standalone) for instructions on how to update your Ionic app to make use of Ionic standalone components. + +**Benefits** + +1. Enables treeshaking so the final build output only includes the code necessary to run your app which reduces overall build size. +2. Avoids the use of NgModules to streamline the development experience and make your code easier to understand. +3. Allows developers to also use newer Angular features such as [ESBuild](https://angular.io/guide/esbuild). + +**Drawbacks** + +1. Ionic components need to be imported into every Angular component they are used in which can be time consuming to set up. + +### Usage with Standalone-based Applications + +:::warning +All Ionic imports should be imported from the `@ionic/angular/standalone` submodule. This includes imports such as components, directives, providers, and types. Importing from `@ionic/angular` may pull in lazy loaded Ionic code which can interfere with treeshaking. +::: + +**Bootstrapping and Configuration** + +Ionic Angular needs to be configured when the Angular application calls `bootstrapApplication` using the `provideIonicAngular` function. Developers can pass any [IonicConfig](../developing/config#ionicconfig) values as an object in this function. Note that `provideIonicAngular` needs to be called even if no custom config is passed. + +```typescript title="main.ts" +import { enableProdMode, importProvidersFrom } from '@angular/core'; +import { bootstrapApplication } from '@angular/platform-browser'; +import { RouteReuseStrategy, provideRouter } from '@angular/router'; +import { provideIonicAngular, IonicRouteStrategy } from '@ionic/angular/standalone'; + +import { routes } from './app/app.routes'; +import { AppComponent } from './app/app.component'; +import { environment } from './environments/environment'; + +if (environment.production) { + enableProdMode(); +} + +bootstrapApplication(AppComponent, { + providers: [ + { provide: RouteReuseStrategy, useClass: IonicRouteStrategy }, + provideIonicAngular({ mode: 'ios' }), + provideRouter(routes), + ], +}); +``` + +**Components** + +In the example below, we are importing `IonContent` and `IonButton` from `@ionic/angular/standalone` and passing them to `imports` for use in the component template. We would get a compiler error if these components were not imported and provided to the `imports` array. + +```typescript title="home.page.ts" +import { Component } from '@angular/core'; +import { IonButton, IonContent } from '@ionic/angular/standalone'; + +@Component({ + selector: 'app-home', + templateUrl: 'home.page.html', + styleUrls: ['home.page.scss'], + standalone: true, + imports: [IonButton, IonContent], +}) +export class HomePage { + constructor() {} +} +``` + +**Icons** + +The icon SVG data needs to be defined in the Angular component so it can be loaded correctly. Developers can use the `addIcons` function from `ionicons` to map the SVG data to a string name. Developers can then reference the icon by its string name using the `name` property on `IonIcon`. + +We recommend calling `addIcons` in the Angular component `constructor` so the data is only added if the Angular component is being used. + +For developers using Ionicons 7.2 or newer, passing only the SVG data will cause the string name to be automatically generated. + +```typescript title="home.page.ts" +import { Component } from '@angular/core'; +import { IonIcon } from '@ionic/angular/standalone'; +import { addIcons } from 'ionicons'; +import { logoIonic } from 'ionicons/icons'; + +@Component({ + selector: 'app-home', + templateUrl: 'home.page.html', + styleUrls: ['home.page.scss'], + standalone: true, + imports: [IonIcon], +}) +export class HomePage { + constructor() { + /** + * On Ionicons 7.2+ this icon + * gets mapped to a "logo-ionic" key. + * Alternatively, developers can do: + * addIcons({ 'logo-ionic': logoIonic }); + */ + addIcons({ logoIonic }); + } +} +``` + +Icons can also be registered in entry points such as `app.component.ts` to avoid the need to call `addIcons` multiple times. Developers should be aware that the initial application chunk may increase because the registered icons will need to be loaded at application start. However, if your application uses a small number of icons the impact of this may be minimal. + +```typescript title="app.component.ts" +import { Component } from '@angular/core'; +import { addIcons } from 'ionicons'; +import { logoIonic } from 'ionicons/icons'; + +@Component({ + selector: 'app-root', + templateUrl: 'app.component.html', + styleUrls: ['app.component.scss'], + standalone: true, +}) +export class AppComponent { + constructor() { + /** + * Any icons you want to use in your application + * can be registered in app.component.ts and then + * referenced by name anywhere in your application. + */ + addIcons({ logoIonic }); + } +} +``` + +Icons registered in an application entry point can then be referenced by name anywhere in the application. + +```html title="home.page.html" + + +``` + +**Routing** + +Developers who wish to use `routerLink`, `routerAction`, or `routerDirection` on Ionic components should import the `IonRouterLink` directive. Developers who wish to use these routing features on anchor (``) elements should import `IonRouterLinkWithHref` instead. + +```typescript title="home.page.ts" +import { Component } from '@angular/core'; +import { RouterLink } from '@angular/router'; +import { IonButton, IonRouterLink } from '@ionic/angular/standalone'; + +@Component({ + selector: 'app-home', + templateUrl: 'home.page.html', + styleUrls: ['home.page.scss'], + standalone: true, + imports: [ + IonButton, + RouterLink, // required to get base routerLink behavior for @angular/router + IonRouterLink, // use IonRouterLinkWithHref if you are using an element instead + ], +}) +export class HomePage {} +``` + +```html title="home.page.html" +Go to Foo Page +``` + +**Testing** + +Ionic Angular's standalone components use ES Modules. As a result, developers using Jest should ensure that ES Modules are transpiled to a format that Jest can use. Developers using Jest should add the following to their Jest config: + + + + +```json + +"transformIgnorePatterns": ["/node_modules/(?!(@ionic/angular|@ionic/core|ionicons|@stencil/core|@angular/*)/)"] +``` + + + + +```json + +"transformIgnorePatterns": ["/node_modules/.pnpm/(?!(@ionic/angular|@ionic/core|ionicons|@stencil/core|@angular/*)@)"] +``` + + + + +### Usage with NgModule-based Applications + +:::warning +All Ionic imports should be imported from the `@ionic/angular/standalone` submodule. This includes imports such as components, directives, providers, and types. Importing from `@ionic/angular` may pull in lazy loaded Ionic code which can interfere with treeshaking. +::: + +**Bootstrapping and Configuration** + +Ionic Angular needs to be configured in the `providers` array of `app.module.ts` using the `provideIonicAngular` function. Developers can pass any [IonicConfig](../developing/config#ionicconfig) values as an object in this function. Note that `provideIonicAngular` needs to be called even if no custom config is passed. + +```typescript title="app.module.ts" +import { NgModule } from '@angular/core'; +import { BrowserModule } from '@angular/platform-browser'; +import { RouteReuseStrategy } from '@angular/router'; + +import { IonicRouteStrategy, provideIonicAngular } from '@ionic/angular/standalone'; + +import { AppComponent } from './app.component'; +import { AppRoutingModule } from './app-routing.module'; + +@NgModule({ + declarations: [AppComponent], + imports: [BrowserModule, AppRoutingModule], + providers: [provideIonicAngular(), { provide: RouteReuseStrategy, useClass: IonicRouteStrategy }], + bootstrap: [AppComponent], +}) +export class AppModule {} +``` + +**Components** + +In the example below, we are importing `IonContent` and `IonButton` from `@ionic/angular/standalone` and passing them to `imports` array in the Angular component's NgModule for use in the component template. We would get a compiler error if these components were not imported and provided to the `imports` array. + +```typescript title="home.module.ts" +import { NgModule } from '@angular/core'; +import { IonButton, IonContent } from '@ionic/angular/standalone'; +import { HomePage } from './home.page'; + +import { HomePageRoutingModule } from './home-routing.module'; + +@NgModule({ + imports: [IonButton, IonContent, HomePageRoutingModule], + declarations: [HomePage], +}) +export class HomePageModule {} +``` + +**Icons** + +The icon SVG data needs to be defined in the Angular component so it can be loaded correctly. Developers can use the `addIcons` function from `ionicons` to map the SVG data to a string name. Developers can then reference the icon by its string name using the `name` property on `IonIcon`. The `IonIcon` component should be added in `app.module.ts` just like the other Ionic components. + +We recommend calling `addIcons` in the Angular component `constructor` so the data is only added if the Angular component is being used. + +For developers using Ionicons 7.2 or newer, passing only the SVG data will cause the string name to be automatically generated. + +```typescript title="home.page.ts" +import { Component } from '@angular/core'; +import { addIcons } from 'ionicons'; +import { logoIonic } from 'ionicons/icons'; + +@Component({ + selector: 'app-home', + templateUrl: 'home.page.html', + styleUrls: ['home.page.scss'], +}) +export class HomePage { + constructor() { + /** + * On Ionicons 7.2+ this icon + * gets mapped to a "logo-ionic" key. + * Alternatively, developers can do: + * addIcons({ 'logo-ionic': logoIonic }); + */ + addIcons({ logoIonic }); + } +} +``` + +Icons can also be registered in entry points such as `app.component.ts` to avoid the need to call `addIcons` multiple times. Developers should be aware that the initial application chunk may increase because the registered icons will need to be loaded at application start. However, if your application uses a small number of icons the impact of this may be minimal. + +```typescript title="app.component.ts" +import { Component } from '@angular/core'; +import { addIcons } from 'ionicons'; +import { logoIonic } from 'ionicons/icons'; + +@Component({ + selector: 'app-root', + templateUrl: 'app.component.html', + styleUrls: ['app.component.scss'], +}) +export class AppComponent { + constructor() { + /** + * Any icons you want to use in your application + * can be registered in app.component.ts and then + * referenced by name anywhere in your application. + */ + addIcons({ logoIonic }); + } +} +``` + +Icons registered in an application entry point can then be referenced by name anywhere in the application. + +```html title="home.page.html" + + +``` + +**Routing** + +Developers who wish to use `routerLink`, `routerAction`, or `routerDirection` on Ionic components should import the `IonRouterLink` directive. Developers who wish to use these routing features on anchor (``) elements should import `IonRouterLinkWithHref` instead. + +```typescript title="home.module.ts" +import { NgModule } from '@angular/core'; +import { RouterLink } from '@angular/router'; +import { IonButton, IonRouterLink } from '@ionic/angular/standalone'; +import { HomePage } from './home.page'; + +import { HomePageRoutingModule } from './home-routing.module'; + +@NgModule({ + imports: [ + IonButton, + RouterLink, // required to get base routerLink behavior for @angular/router + IonRouterLink, // use IonRouterLinkWithHref if you are using an element instead + HomePageRoutingModule, + ], + declarations: [HomePage], +}) +export class HomePageModule {} +``` + +```html title="home.page.html" +Go to Foo Page +``` + +**Testing** + +Ionic Angular's standalone components use ES Modules. As a result, developers using Jest should ensure that ES Modules are transpiled to a format that Jest can use. Developers using Jest should add the following to their Jest config: + + + + +```json + +"transformIgnorePatterns": ["/node_modules/(?!(@ionic/angular|@ionic/core|ionicons|@stencil/core|@angular/*)/)"] +``` + + + + +```json + +"transformIgnorePatterns": ["/node_modules/.pnpm/(?!(@ionic/angular|@ionic/core|ionicons|@stencil/core|@angular/*)@)"] +``` + + + + +## Modules + +### Overview + +Developers can also use the Modules approach by importing `IonicModule` and calling `IonicModule.forRoot()` in the `imports` array in `app.module.ts`. This registers a version of Ionic where Ionic components will be lazily loaded at runtime. + +**Benefits** + +1. Since components are lazily loaded as needed, developers do not need to spend time manually importing and registering each Ionic component. + +**Drawbacks** + +1. Lazily loading Ionic components means that the compiler does not know which components are needed at build time. This means your final application bundle may be much larger than it needs to be. +2. Developers are unable to use newer Angular features such as [ESBuild](https://angular.io/guide/esbuild). + +### Usage + +In the example below, we are using `IonicModule` to create a lazily loaded version of Ionic. We can then reference any Ionic component without needing to explicitly import it. + +```typescript +import { NgModule } from '@angular/core'; +import { BrowserModule } from '@angular/platform-browser'; + +import { IonicModule } from '@ionic/angular'; + +import { AppComponent } from './app.component'; + +@NgModule({ + declarations: [AppComponent], + imports: [BrowserModule, IonicModule.forRoot()], + bootstrap: [AppComponent], +}) +export class AppModule {} +``` + +## Migrating from Modules to Standalone + +:::tip +Try our automated utility for migrating to standalone! + +See https://github.com/ionic-team/ionic-angular-standalone-codemods for instructions on how to get started. All issues related to the migration utility should be filed on the linked repo. +::: + +The Standalone option is newer than the Modules option, so developers may wish to switch during the development of their application. This guide details the steps needed to migrate. + +Migrating to Ionic standalone components must be done all at the same time and cannot be done gradually. The Modules and Standalone approaches use two different build systems of Ionic that cannot be used at the same time. + +Developers are encouraged to try the [automated migration utility](https://github.com/ionic-team/ionic-angular-standalone-codemods), though they can also follow the steps below if they would like to manually migrate their applications. + +### Standalone-based Applications + +Follow these steps if your Angular application is already using the standalone architecture, and you want to use Ionic UI components as standalone components too. + +1. Run `npm install @ionic/angular@latest` to ensure you are running the latest version of Ionic. Ionic UI Standalone Components is supported in Ionic v7.5 or newer. + +2. Run `npm install ionicons@latest` to ensure you are running the latest version of Ionicons. Ionicons v7.2 brings usability improvements that reduce the code boilerplate needed to use icons with standalone components. + +3. Remove the `IonicModule` call in `main.ts` in favor of `provideIonicAngular` imported from `@ionic/angular/standalone`. Any config passed to `IonicModule.forRoot` can be passed as an object to this new function. + +```diff title="main.ts" +import { enableProdMode, importProvidersFrom } from '@angular/core'; +import { bootstrapApplication } from '@angular/platform-browser'; +import { RouteReuseStrategy, provideRouter } from '@angular/router'; +- import { IonicModule, IonicRouteStrategy } from '@ionic/angular'; ++ import { provideIonicAngular, IonicRouteStrategy } from '@ionic/angular/standalone'; + +import { routes } from './app/app.routes'; +import { AppComponent } from './app/app.component'; +import { environment } from './environments/environment'; + +if (environment.production) { + enableProdMode(); +} + +bootstrapApplication(AppComponent, { + providers: [ + { provide: RouteReuseStrategy, useClass: IonicRouteStrategy }, + /** + * The custom config serves as an example + * of how to pass a config to provideIonicAngular. + * You do not need to set "mode: 'ios'" to + * use Ionic standalone components. + */ +- importProvidersFrom(IonicModule.forRoot({ mode: 'ios' })), ++ provideIonicAngular({ mode: 'ios' }), + provideRouter(routes), + ], +}); +``` + +4. Remove any references to `IonicModule` found elsewhere in your application. + +5. Update any existing imports from `@ionic/angular` to import from `@ionic/angular/standalone` instead. + +```diff +- import { Platform } from '@ionic/angular'; ++ import { Platform } from '@ionic/angular/standalone'; +``` + +6. Add imports for each Ionic component in the Angular component where they are used. Be sure to pass the imports to the `imports` array on your Angular component. + +```diff title="app.component.ts" +import { Component } from '@angular/core'; ++ import { IonApp, IonRouterOutlet } from '@ionic/angular/standalone'; + +@Component({ + selector: 'app-root', + templateUrl: 'app.component.html', + styleUrls: ['app.component.scss'], + standalone: true, ++ imports: [IonApp, IonRouterOutlet], +}) +export class AppComponent { + constructor() {} +} +``` + +7. If you are using Ionicons, define the icon SVG data used in each Angular component using `addIcons`. This allows you to continue referencing icons by string name in your component template. Note that you will need to do this for any additional icons added. + +```diff title="test.component.ts" +import { Component } from '@angular/core'; ++ import { IonIcon } from '@ionic/angular/standalone'; ++ import { addIcons } from 'ionicons'; ++ import { alarm, logoIonic } from 'ionicons/icons'; + +@Component({ + selector: 'app-root', + templateUrl: 'app.component.html', + styleUrls: ['app.component.scss'], + standalone: true, ++ imports: [IonIcon], +}) +export class TestComponent { + constructor() { ++ addIcons({ alarm, logoIonic }); + } +} +``` + +8. Remove the following code from your `angular.json` file if present. Note that it may appear multiple times. + +```diff title="angular.json" +- { +- "glob": "**/*.svg", +- "input": "node_modules/ionicons/dist/ionicons/svg", +- "output": "./svg" +- } +``` + +9. If you are using `routerLink`, `routerDirection`, or `routerAction` be sure to import the `IonRouterLink` directive for Ionic components or `IonRouterLinkWithHref` directive for `` elements. + +```diff title="test.component.ts" +import { Component } from '@angular/core'; +- import { IonButton } from '@ionic/angular/standalone'; ++ import { IonButton, IonRouterLink } from '@ionic/angular/standalone'; + +@Component({ + selector: 'app-root', + templateUrl: 'app.component.html', + styleUrls: ['app.component.scss'], + standalone: true, + imports: [ + IonButton, ++ IonRouterLink + ], +}) +export class TestComponent {} +``` + +10. If you are using VSCode it is recommended to ignore the `@ionic/angular/common` and `@ionic/angular` module specifiers for import recommendations. + +```json title=".vscode/settings.json" +{ + "typescript.preferences.autoImportFileExcludePatterns": ["@ionic/angular/common", "@ionic/angular"] +} +``` + +### NgModule-based Applications + +Follow these steps if your Angular application is still using the NgModule architecture, but you want to adopt Ionic UI components as standalone components now. + +1. Run `npm install @ionic/angular@latest` to ensure you are running the latest version of Ionic. Ionic UI Standalone Components is supported in Ionic v7.5 or newer. + +2. Run `npm install ionicons@latest` to ensure you are running the latest version of Ionicons. Ionicons v7.2 brings usability improvements that reduce the code boilerplate needed to use icons with standalone components. + +3. Remove the `IonicModule` call in `app.module.ts` in favor of `provideIonicAngular` imported from `@ionic/angular/standalone`. Any config passed to `IonicModule.forRoot` can be passed as an object to this new function. + +```diff title="app.module.ts" +import { enableProdMode, importProvidersFrom } from '@angular/core'; +import { bootstrapApplication } from '@angular/platform-browser'; +import { RouteReuseStrategy, provideRouter } from '@angular/router'; +- import { IonicModule, IonicRouteStrategy } from '@ionic/angular'; ++ import { provideIonicAngular, IonicRouteStrategy } from '@ionic/angular/standalone'; + +import { routes } from './app/app.routes'; +import { AppComponent } from './app/app.component'; +import { environment } from './environments/environment'; + +if (environment.production) { + enableProdMode(); +} + +@NgModule({ + declarations: [AppComponent], +- imports: [BrowserModule, IonicModule.forRoot({ mode: 'ios' }), AppRoutingModule], ++ imports: [BrowserModule, AppRoutingModule], + providers: [ + { provide: RouteReuseStrategy, useClass: IonicRouteStrategy }, + /** + * The custom config serves as an example + * of how to pass a config to provideIonicAngular. + * You do not need to set "mode: 'ios'" to + * use Ionic standalone components. + */ ++ provideIonicAngular({ mode: 'ios' }), + ], + bootstrap: [AppComponent], +}) +export class AppModule {} +``` + +4. Remove any references to `IonicModule` found elsewhere in your application. + +5. Update any existing imports from `@ionic/angular` to import from `@ionic/angular/standalone` instead. + +```diff +- import { Platform } from '@ionic/angular'; ++ import { Platform } from '@ionic/angular/standalone'; +``` + +6. Add imports for each Ionic component in the NgModule for the Angular component where they are used. Be sure to pass the components to the `imports` array on the module. + +```diff title="app.module.ts" +import { enableProdMode, importProvidersFrom } from '@angular/core'; +import { bootstrapApplication } from '@angular/platform-browser'; +import { RouteReuseStrategy, provideRouter } from '@angular/router'; +- import { provideIonicAngular, IonicRouteStrategy } from '@ionic/angular/standalone'; ++ import { provideIonicAngular, IonicRouteStrategy, IonApp, IonRouterOutlet } from '@ionic/angular/standalone'; + +import { routes } from './app/app.routes'; +import { AppComponent } from './app/app.component'; +import { environment } from './environments/environment'; + +if (environment.production) { + enableProdMode(); +} + +@NgModule({ + declarations: [AppComponent], +- imports: [BrowserModule, AppRoutingModule], ++ imports: [BrowserModule, AppRoutingModule, IonApp, IonRouterOutlet], + providers: [ + { provide: RouteReuseStrategy, useClass: IonicRouteStrategy }, + provideIonicAngular({ mode: 'ios' }) + ], + bootstrap: [AppComponent], +}) +export class AppModule {} +``` + +For example, all modules that are using Ionic components need to have the Ionic components imported in their component module. + +```diff title="home.module.ts" +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { FormsModule } from '@angular/forms'; +import { HomePage } from './home.page'; + +import { HomePageRoutingModule } from './home-routing.module'; + ++ import { IonContent, IonHeader, IonTitle, IonToolbar } from '@ionic/angular/standalone'; + +@NgModule({ + imports: [ + CommonModule, + FormsModule, + HomePageRoutingModule, ++ IonContent, ++ IonHeader, ++ IonTitle, ++ IonToolbar + ], + declarations: [HomePage] +}) +export class HomePageModule {} +``` + +7. If you are using Ionicons, define the icon SVG data used in each Angular component using `addIcons`. This allows you to continue referencing icons by string name in your component template. Note that you will need to do this for any additional icons added. The `IonIcon` component should still be provided in the NgModule. + +```diff title="test.component.ts" +import { Component } from '@angular/core'; ++ import { addIcons } from 'ionicons'; ++ import { alarm, logoIonic } from 'ionicons/icons'; + +@Component({ + selector: 'app-root', + templateUrl: 'app.component.html', + styleUrls: ['app.component.scss'], +}) +export class TestComponent { + constructor() { ++ addIcons({ alarm, logoIonic }); + } +} +``` + +```diff title="test.module.ts" +import { NgModule } from '@angular/core'; +import { TestComponent } from './test.component'; ++ import { IonIcon } from '@ionic/angular/standalone'; + +@NgModule({ + imports: [ ++ IonIcon, + ], + declarations: [TestComponent] +}) +export class TestComponentModule {} +``` + +8. Remove the following code from your `angular.json` file if present. Note that it may appear multiple times. + +```diff title="angular.json" +- { +- "glob": "**/*.svg", +- "input": "node_modules/ionicons/dist/ionicons/svg", +- "output": "./svg" +- } +``` + +9. If you are using `routerLink`, `routerDirection`, or `routerAction` be sure to import the `IonRouterLink` directive for Ionic components or `IonRouterLinkWithHref` directive for `` elements. + +```diff title="test.module.ts" +import { NgModule } from '@angular/core'; +import { TestComponent } from './test.component'; +- import { IonButton } from '@ionic/angular/standalone'; ++ import { IonButton, IonRouterLink } from '@ionic/angular/standalone'; + +@NgModule({ + imports: [ + IonButton, ++ IonRouterLink, + ], + declarations: [TestComponent] +}) +``` + +10. If you are using VSCode it is recommended to ignore the `@ionic/angular/common` and `@ionic/angular` module specifiers for import recommendations. + +```json title=".vscode/settings.json" +{ + "typescript.preferences.autoImportFileExcludePatterns": ["@ionic/angular/common", "@ionic/angular"] +} +``` diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/angular/lifecycle.md b/i18n/ja/docusaurus-plugin-content-docs/current/angular/lifecycle.md new file mode 100644 index 00000000000..007cdd56667 --- /dev/null +++ b/i18n/ja/docusaurus-plugin-content-docs/current/angular/lifecycle.md @@ -0,0 +1,103 @@ +--- +title: Ionic PageのLife Cycle +sidebar_label: ライフサイクル +--- + + + AngularのページコンポーネントのLife Cycle - すべてのイベントのドキュメンテーション + + + +このガイドでは、Ionic と Angular を使用して構築されたアプリでの Page Life Cycle のしくみについて説明します。(追記:Life Cycle とは、表示をはじめてから破棄するまでを指します。この間の特定のタイミングに設定されているイベントを Life Cycle Events といいます) + +![Ionic life cycle events demo](/img/guides/lifecycle/ioniclifecycle.png) + +## Angular の Life Cycle Events + +Ionic は Angular が提供する Life Cycle Events を取り入れています。最もよく使う 2 つの Angular イベントは次のとおりです。 + +| Event Name | Description | +| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `ngOnInit` | コンポーネントの初期化中に発生します。このイベントを使用して、ローカルメンバーを初期化し、一度だけ実行する必要がある Service を呼び出すことができます。 | +| `ngOnDestroy` | Angular がビューを破棄する直前に発生します。 observables の unsubscribe などのクリーンアップに役立ちます。 | + +Angular の Component Life Cycle イベントの詳細については、それらの [component lifecycle docs](https://angular.jp/guide/lifecycle-hooks) をご覧ください。 + +:::note +`ion-nav` または `ion-router-outlet` を使用するコンポーネントは、 `OnPush` 変更検出方式を使用しないでください。そうすることで、 `ngOnInit` などのライフサイクル・フックが起動するのを防ぐことができます。また、非同期状態の変更は正しくレンダリングされない場合があります。 +::: + +## Ionic の Page Events + +Angular の Life Cycle Events に加えて、Ionic Angular には、使用可能ないくつかの追加イベントがあります: + +| Event Name | Description | +| ------------------ | ------------------------------------------------------------------------ | +| `ionViewWillEnter` | コンポーネントが表示されるアニメーションがはじまる時に発火します。 | +| `ionViewDidEnter` | コンポーネントが表示されるアニメーションが **終了した時に** 発火します。 | +| `ionViewWillLeave` | コンポーネントを離脱するアニメーションが **はじまる時に** 発火します。 | +| `ionViewDidLeave` | コンポーネントを離脱するアニメーションが **終了した時に** 発火します。 | + +これらのライフサイクルは、ルーターによって直接マッピングされたコンポーネントに対してのみ呼び出されます。つまり、`/pageOne`が`PageOneComponent`にマッピングされた場合、Ionic ライフサイクルは`PageOneComponent`で呼び出されますが、`PageOneComponent`がレンダリングする子コンポーネントでは呼び出されません。 + +`ionViewWillEnter`と`ionViewDidEnter`の違いは、いつ発火するかです。前者は `ngOnInit` の直後でページ遷移が始まる前に、後者は遷移が終わった後に直接呼び出されます。 + +`ionViewWillLeave` と `ionViewDidLeave` についてですが、 `ionViewWillLeave` は現在のページから離脱する処理がはじまる前に呼び出されますが、 `ionViewDidLeave` は新しいページに遷移する処理が成功してから呼び出されます (新しいページの `ionViewDidEnter` が発火した後になります)。 + +![Ionic life cycle events demo](/img/guides/lifecycle/ioniclifecycle.gif) + +## Ionic が Page の Life をどのように処理するか + +Ionic は `` という router outlet を持っています。この outlet が Angular の `` を継承し、さらに拡張して、モバイルデバイスのためのより良い体験を可能にしました。 + +`` にアプリがラップされることで、Ionic はナビゲーションの扱いを少し変更します。新しいページに遷移すると、Ionic は古いページを既存の DOM に残しますが、ビューから隠して新しいページに移行します。これを行う理由は 2 つあります: + +1. 古いページの状態を維持することができます(画面上のデータ、スクロール位置など)。 +2. ページがすでに存在しており作成し直す必要がないため、ページへの移行がスムーズになります。 + +たとえば、UI の "戻る" ボタンまたはブラウザの "戻る" ボタンを押すことによってページが「Pop」されると、ページは DOM から削除されるだけとなります。 + +この特別な処理のために、`ngOnInit` と `ngOnDestroy` のメソッドは通常そうあるべきだと思うときには発火しないかもしれません。 + +`ngOnInit` はページが新しく作成されるたびに発火するだけなので、ページに戻ったときには発火されません。たとえば、タブのインタフェースで各ページ間を移動しても、各ページの `ngOnInit` メソッドは最初の 1 回だけ呼び出され、その後の表示では呼び出されません。`ngOnDestroy` はページが 「Pop」したときにのみ発生します。 + +## ルートガード + +Ionic 3 では、いつページにアクセスすることができるか( `ionViewCanEnter` )と離脱できるか(`ionViewCanLeave`)を制御するのに役立つ、いくつかの追加のライフサイクルメソッドがありました。これらは、許可されていないユーザーからページを保護したり、ユーザーがページを離れたくないときにユーザーをページ上に保持したりするために使用できます(フォーム入力中など)。 + +これらの方法は、Angular のルートガードを使用するために Ionic 4 で削除されました。 + +ルートガードは、ルートに対して特定のアクションを実行できるかどうかを判断するのに役立ちます。それらは特定のインターフェースを実装するクラスです。`CanActive` と `CanDeactivate` のインターフェイスは、`ionViewCanEnter` と `ionViewCanLeave` と同様のロジックでイベントを削除することができます。 + +```tsx +@Injectable() +export class AuthGuard implements CanActivate { + constructor(private authService: AuthService) {} + + canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) { + return this.authService.isAuthenticated(); + } +} +``` + +このガードを使用するには、それをルート定義の適切なパラメータに追加します: + +```tsx +{ path: 'settings', canActivate: [AuthGuard], loadChildren: '...', } +``` + +ルートガードの使い方の詳細については、Angular の [router documentation](https://angular.jp/guide/router) を参照してください。 + +## Life Cycle メソッドのガイダンス + +以下は、life cycle events ごとのユースケースに関するヒントです。 + +- `ngOnInit` - コンポーネントを初期化し、Service からアクセスごとに更新する必要がないデータをロードします。 +- `ionViewWillEnter` - `ionViewWillEnter` は View がナビゲートされる度に呼び出されるので(初期化されているかどうかにかかわらず)、Service からデータをロードするのに適したメソッドです。ただし、アニメーション中にデータがを取得すると、大量の DOM 操作が開始される可能性があります。これにより、ぎこちないアニメーションが発生する可能性があります。 +- `ionViewDidEnter` - `ionViewWillEnter` を使ってデータを取得していてパフォーマンスに問題がある時は、`ionViewDidEnter` を代わりに使うことができます。ただし、Page がユーザーに表示されるまではこのイベントは発火しません。そのため、ロードインジケータまたはスケルトン画面を使用することをお勧めします。これにより、遷移が完了した後にコンテンツが不自然に点滅することはありません。 +- `ionViewWillLeave` - observables の unsubscribing のように、クリーンアップで利用します。 `ngOnDestroy` はあなたが現在のページから遷移する時には発火しない可能性がありますので、画面が表示されていない時にアクティブにしたくない場合はここでクリーンアップの処理を行います。 +- `ionViewDidLeave` - このイベントが発生すると、新しいページへと完全に遷移したことがわかります。そのため、ビューが表示されているときに通常は行わない可能性があるロジックはすべてここに移動できます。 +- `ngOnDestroy` - `ionViewWillLeave` でクリーンアップしたくないページのクリーンアップロジックはここにおいてください。 diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/angular/navigation.md b/i18n/ja/docusaurus-plugin-content-docs/current/angular/navigation.md new file mode 100644 index 00000000000..be00e6f566b --- /dev/null +++ b/i18n/ja/docusaurus-plugin-content-docs/current/angular/navigation.md @@ -0,0 +1,497 @@ +--- +title: Angular ナビゲーション +sidebar_label: ナビゲーション/ルーティング +--- + +import useBaseUrl from '@docusaurus/useBaseUrl'; + + + Angular Navigation: How Routing & Redirects Work in Angular Apps + + + +このガイドでは、Ionic と Angular を使用して構築されたアプリでのルーティングのしくみについて説明します。 + +Angular Router は、Angular アプリケーションで最も重要なライブラリの 1 つです。これがなければ、アプリはシングルビュー/シングルコンテキストアプリになるか、ブラウザのリロード時にナビゲーションのステートを維持できなくなります。Angular Router を使用すると、リンク可能でリッチなアニメーションを持つリッチなアプリを作成できます(もちろん、Ionic と組み合わせると!)。Angular Router の基本と、それを Ionic アプリケーション用に設定する方法を見てみましょう。 + +## シンプルな Route + +ほとんどのアプリでは、some sort of route を持つことがしばしば必要になります。最も基本的な設定はこのようになります: + +```tsx + +import { RouterModule } from '@angular/router'; + +@NgModule({ + imports: [ + ... + RouterModule.forRoot([ + { path: '', component: LoginComponent }, + { path: 'detail', component: DetailComponent }, + ]) + ], +}) +``` + +URL path と Component の組み合わせを確認する最も簡単な方法は、ここをみるすることです。アプリがロードされると、ルーターはユーザーがロードしようとしている URL を読むことで動作を開始します。私たちのサンプルでは、Route は `''` を参照します。これは本質的に私たちのインデックスルートとなります。そうすると、一致するエントリを探し出して、 `LoginComponent` がロードされます。かなり簡単です。この処理は `path` が一致するまで、設定されているすべての Route のエントリを参照します。しかし、初期ロードと異なるパスをロードしたい場合はどうなりますか? + +## リダイレクトの処理 + +そういう場合には、ルーターリダイレクトを使用できます。リダイレクトは通常のルートオブジェクトと同じように書くことができますが、いくつかの異なるキーが含まれます。 + +```tsx +[ + { path: '', redirectTo: 'login', pathMatch: 'full' }, + { path: 'login', component: LoginComponent }, + { path: 'detail', component: DetailComponent }, +]; +``` + +このリダイレクトでは、アプリのインデックス(`''`)を探しはじめると、`login` にリダイレクトします。最後の `pathMatch` キーは、ルータにパスの検索方法を指示するために必要です。 + +`full` を使用すると、たとえ最後まで `/route1/route2/route3` と一致する path がなかったとしても、フルパスを比較する必要があることをルータに伝えることができます。つまり、次のようになります。 + +```tsx +{ path: '/route1/route2/route3', redirectTo: 'login', pathMatch: 'full' }, +{ path: 'login', component: LoginComponent }, +``` + +このように書くと `/route1/route2/route3` をロードすると、リダイレクトを行います。けれど仮に `/route1/route2/route4` であれば、すべての path が一致しないのでリダイレクトを行いません。 + +あるいは、こういう書き方もできます: + +```tsx +{ path: '/route1/route2', redirectTo: 'login', pathMatch: 'prefix' }, +{ path: 'login', component: LoginComponent }, +``` + +`/route1/route2/route3` と `/route1/route2/route4` の両方を読み込んだとおき, どちらの場合もリダイレクトします。 `pathMatch: 'prefix'` によって、一部でも一致したら該当するからです。 + +## routes へのナビゲーション + +routes について説明してきましたが、それではどのようにしてそのルートにナビゲーションしたらいいのでしょうか。これには、 `routerLink` directive を利用します。先ほどの簡単な router 設定でこれを確認してみましょう: + +```ts +RouterModule.forRoot([ + { path: '', component: LoginComponent }, + { path: 'detail', component: DetailComponent }, +]); +``` + +わたしたちは、次の HTML を利用することで、`LoginComponent` から `detail` route に遷移することができます。 + +```html + + + Login + + + + + Go to detail + +``` + +ここで重要なのは`ion-button` と `routerLink` directive です。RouterLink は典型的な `href` と同様の考えで動作しますが、URL を文字列として構築する代わりに配列として構築することができ、それによってより複雑なパスを書くこともできます。 + +Router API を使用して、プログラムで遷移することもできます。 + +```tsx +import { Component } from '@angular/core'; +import { Router } from '@angular/router'; + +@Component({ + ... +}) +export class LoginComponent { + + constructor(private router: Router){} + + navigate(){ + this.router.navigate(['/detail']) + } +} +``` + +どちらのオプションも同様のナビゲーションメカニズムを提供し、異なるユースケースで利用することができます。 + +### LocationStrategy.historyGo を使ったナビゲーション + +Angular Router には [LocationStrategy.historyGo](https://angular.io/api/common/LocationStrategy#historyGo) メソッドがあり、アプリケーションの履歴を進んだり戻ったりすることができます。例を見てみましょう。 + +次のようなアプリケーションの履歴があるとします: + +`/ページA` --> `/ページB` --> `/ページC`。 + +もし `/pageC` で `LocationStrategy.historyGo(-2)` を呼び出すと、 `/pageA` に戻る。その後、 `LocationStrategy.historyGo(2)` を呼び出すと、 `/pageC` に戻る。 + +`LocationStrategy.historyGo()` の主な特徴は、アプリケーションの履歴が線形であることを想定していることです。つまり、`LocationStrategy.historyGo()` は非線形のルーティングを使用するアプリケーションでは使用すべきではありません。詳しくは [リニアルーティング対非リニアルーティング](#linear-routing-versus-non-linear-routing) を参照してください。 + +## Lazy loading routes + +現在のルート設定では、すべての Component が、ルートとなる `app.module` と同じ `chunk` に含まれているので理想的ではありません。代わりに、ルータにはコンポーネントを独自の `chunk` に分離できるように設定されています。 + +```tsx + +import { RouterModule } from '@angular/router'; + +@NgModule({ + imports: [ + ... + RouterModule.forRoot([ + { path: '', redirectTo: 'login', pathMatch: 'full' }, + { path: 'login', loadChildren: () => import('./login/login.module').then(m => m.LoginModule) }, + { path: 'detail', loadChildren: () => import('./detail/detail.module').then(m => m.DetailModule) } + ]) + ], +}) +``` + +`loadChildren` プロパティはコンポーネントの代わりにネイティブインポートを直接仕様してモジュールを参照する方法です。ただしこれを行うには、コンポーネントごとにモジュールを作成する必要があります。 + +```tsx +... +import { RouterModule } from '@angular/router'; +import { LoginComponent } from './login.component'; + +@NgModule({ + imports: [ + ... + RouterModule.forChild([ + { path: '', component: LoginComponent }, + ]) + ], +}) +``` + +:::note +一部のコードを省略して紹介しています +::: + +ここでは、`RouterModule` のインポートとともに、典型的な `Angular Module` の設定がありますが、`RouterModule` では `forChild` によってコンポーネントを使用することを宣言しています。この設定では、ビルドを実行するときに、`App Component`(Root)、 `login Component` 、および `detail Component` において別々のチャンクを作成します。 + +## Standalone Components + +:::warning Experimental API + +Standalone components is an experimental API introduced in Angular 14.x and available in Ionic 6.3 and later. This feature may change before it is stable. + +::: + +Standalone components allow developers to lazy load a component on a route without having to declare the component to an Angular module. + +To use standalone components with routing and Ionic Framework, you must first be on Ionic ^6.3.0. The experimental API requires developers to assign the `EnvironmentInjector` instance for each router outlet (`ion-router-outlet` and `ion-tabs`) that uses standalone component routing. + +```ts title="app.component.ts" +import { Component, EnvironmentInjector } from '@angular/core'; + +@Component({ + selector: 'app-root', + template: 'app.component.html', +}) +export class AppComponent { + constructor(public environmentInjector: EnvironmentInjector) {} +} +``` + +```html title="app.component.html" + + + ... +``` + +Developers can use the existing syntax for standalone component routing from Angular: + +```ts +@NgModule({ + imports: [ + RouterModule.forRoot([ + { + path: 'standalone-route', + loadComponent: () => import('./path/to/my-component.component').then((c) => c.MyComponent), + }, + ]), + ], +}) +export class AppRoutingModule {} +``` + +To get started with standalone components [visit Angular's official docs](https://angular.io/guide/standalone-components). + +## Live Example + +If you would prefer to get hands on with the concepts and code described above, please checkout our [live example](https://stackblitz.com/edit/ionic-angular-routing?file=src/app/app-routing.module.ts) of the topics above on StackBlitz. + +## Linear Routing versus Non-Linear Routing + +### Linear Routing + +If you have built a web app that uses routing, you likely have used linear routing before. Linear routing means that you can move forward or backward through the application history by pushing and popping pages. + +The following is an example of linear routing in a mobile app: + + + +The application history in this example has the following path: + +`Accessibility` --> `VoiceOver` --> `Speech` + +When we press the back button, we follow that same routing path except in reverse. Linear routing is helpful in that it allows for simple and predictable routing behaviors. It also means we can use router Angular Router APIs such as [LocationStrategy.historyGo()](#navigating-using-locationstrategy). + +The downside of linear routing is that it does not allow for complex user experiences such as tab views. This is where non-linear routing comes into play. + +### Non-Linear Routing + +Non-linear routing is a concept that may be new to many web developers learning to build mobile apps with Ionic. + +Non-linear routing means that the view that the user should go back to is not necessarily the previous view that was displayed on the screen. + +The following is an example of non-linear routing: + + + +In the example above, we start on the `Originals` tab. Tapping a card brings us to the `Ted Lasso` view within the `Originals` tab. + +From here, we switch to the `Search` tab. Then, we tap the `Originals` tab again and are brought back to the `Ted Lasso` view. At this point, we have started using non-linear routing. + +Why is this non-linear routing? The previous view we were on was the `Search` view. However, pressing the back button on the `Ted Lasso` view should bring us back to the root `Originals` view. This happens because each tab in a mobile app is treated as its own stack. The [Working with Tabs](#working-with-tabs) sections goes over this in more detail. + +If tapping the back button simply called `LocationStrategy.historyGo(-1)` from the `Ted Lasso` view, we would be brought back to the `Search` view which is not correct. + +Non-linear routing allows for sophisticated user flows that linear routing cannot handle. However, certain linear routing APIs such as `LocationStrategy.historyGo()` cannot be used in this non-linear environment. This means that `LocationStrategy.historyGo()` should not be used when using tabs or nested outlets. + +### Which one should I choose? + +We recommend keeping your application as simple as possible until you need to add non-linear routing. Non-linear routing is very powerful, but it also adds a considerable amount of complexity to mobile applications. + +The two most common uses of non-linear routing is with tabs and nested `ion-router-outlet`s. We recommend only using non-linear routing if your application meets the tabs or nested router outlet use cases. + +For more on tabs, please see [Working with Tabs](#working-with-tabs). + +For more on nested router outlets, please see [Nested Routes](#nested-routes). + +## Shared URLs versus Nested Routes + +A common point of confusion when setting up routing is deciding between shared URLs or nested routes. This part of the guide will explain both and help you decide which one to use. + +### Shared URLs + +Shared URLs is a route configuration where routes have pieces of the URL in common. The following is an example of a shared URL configuration: + +```tsx +const routes: Routes = [ + { + path: 'dashboard', + component: DashboardMainPage, + }, + { + path: 'dashboard/stats', + component: DashboardStatsPage, + }, +]; +``` + +The above routes are considered "shared" because they reuse the `dashboard` piece of the URL. + +### Nested Routes + +Nested Routes is a route configuration where routes are listed as children of other routes. The following is an example of a nested route configuration: + +```tsx +const routes: Routes = [ + { + path: 'dashboard', + component: DashboardRouterOutlet, + children: [ + { + path: '', + component: DashboardMainPage, + }, + { + path: 'stats', + component: DashboardStatsPage, + }, + ], + }, +]; +``` + +The above routes are nested because they are in the `children` array of the parent route. Notice that the parent route renders the `DashboardRouterOutlet` component. When you nest routes, you need to render another instance of `ion-router-outlet`. + +### Which one should I choose? + +Shared URLs are great when you want to transition from page A to page B while preserving the relationship between the two pages in the URL. In our previous example, a button on the `/dashboard` page could transition to the `/dashboard/stats` page. The relationship between the two pages is preserved because of a) the page transition and b) the url. + +Nested routes should be used when you want to render content in outlet A while also rendering sub-content inside of a nested outlet B. The most common use case you will run into is tabs. When you load up a tabs Ionic starter application, you will see `ion-tab-bar` and `ion-tabs` components rendered in the first `ion-router-outlet`. The `ion-tabs` component renders another `ion-router-outlet` which is responsible for rendering the contents of each tab. + +There are very few use cases in which nested routes make sense in mobile applications. When in doubt, use the shared URL route configuration. We strongly caution against using nested routing in contexts other than tabs as it can quickly make navigating your app confusing. + +## Working with Tabs + +タブを使用すると、Angular Router にどのコンポーネントをロードする必要があるかを知るためのメカニズムを Ionic が提供しますが、タブコンポーネントでは複雑な作業が行われます。簡単な例を見てみましょう。 + +```ts +const routes: Routes = [ + { + path: 'tabs', + component: TabsPage, + children: [ + { + path: 'tab1', + children: [ + { + path: '', + loadChildren: () => import('../tab1/tab1.module').then((m) => m.Tab1PageModule), + }, + ], + }, + { + path: '', + redirectTo: '/tabs/tab1', + pathMatch: 'full', + }, + ], + }, + { + path: '', + redirectTo: '/tabs/tab1', + pathMatch: 'full', + }, +]; +``` + +ここでは、 `tabs` パスを読み込んでいます。この例では、path を `tabs` としていますが、これは変更可能です。あなたのアプリに合った名前にすることができます。このルートオブジェクトでは、子ルートも定義することができます。この例では、トップレベルの子ルート「tab1」が「outlet」として機能し、さらに子ルートをロードすることができます。この例では、1 つの子ルートがあり、新しいコンポーネントをロードするだけです。Tabs のマークアップは、次のとおりです: + +```html + + + + + Tab One + + + +``` + +Ionic を使ってアプリを作成したことがあれば、このマークアップはおなじみのはずです。`ion-tabs` コンポーネントを作成し、`ion-tab-bar` を提供します。`ion-tab-bar` は、 `tab`と一緒に`ion-tab-button`を提供します。最新の `@ionic/angular` はもはや `` を必要とせず、開発者がタブバーを完全にカスタマイズできるようになり、すべての設定は Router の設定によって行えるようになりました。 + +### How Tabs in Ionic Work + +Each tab in Ionic is treated as an individual navigation stack. This means if you have three tabs in your application, each tab has its own navigation stack. Within each stack you can navigate forwards (push a view) and backwards (pop a view). + +This behavior is important to note as it is different than most tab implementations that are found in other web based UI libraries. Other libraries typically manage tabs as one single history stack. + +Since Ionic is focused on helping developers build mobile apps, the tabs in Ionic are designed to match native mobile tabs as closely as possible. As a result, there may be certain behaviors in Ionic's tabs that differ from tabs implementations you have seen in other UI libraries. Read on to learn more about some of these differences. + +### Child Routes within Tabs + +When adding additional routes to tabs you should write them as sibling routes with the parent tab as the path prefix. The example below defines the `/tabs/tab1/view` route as a sibling of the `/tabs/tab1` route. Since this new route has the `tab1` prefix, it will be rendered inside of the `Tabs` component, and Tab 1 will still be selected in the `ion-tab-bar`. + +```ts +const routes: Routes = [ + { + path: 'tabs', + component: TabsPage, + children: [ + { + path: 'tab1', + children: [ + { + path: '', + loadChildren: () => import('../tab1/tab1.module').then((m) => m.Tab1PageModule), + }, + ], + }, + { + path: 'tab1/view', + children: [ + { + path: '', + loadChildren: () => import('../tab1/tab1view.module').then((m) => m.Tab1ViewPageModule), + }, + ], + }, + { + path: 'tab2', + children: [ + { + path: '', + loadChildren: () => import('../tab2/tab2.module').then((m) => m.Tab2PageModule), + }, + ], + }, + { + path: 'tab3', + children: [ + { + path: '', + loadChildren: () => import('../tab3/tab3.module').then((m) => m.Tab3PageModule), + }, + ], + }, + ], + }, + { + path: '', + redirectTo: '/tabs/tab1', + pathMatch: 'full', + }, +]; +``` + +### Switching Between Tabs + +Since each tab is its own navigation stack, it is important to note that these navigation stacks should never interact. This means that there should never be a button in Tab 1 that routes a user to Tab 2. In other words, tabs should only be changed by the user tapping a tab button in the tab bar. + +A good example of this in practice is the iOS App Store and Google Play Store mobile applications. These apps both provide tabbed interfaces, but neither one ever routes the user across tabs. For example, the "Games" tab in the iOS App Store app never directs users to the "Search" tab and vice versa. + +Let's take a look at a couple common mistakes that are made with tabs. + +**A Settings Tab That Multiple Tabs Reference** + +A common practice is to create a Settings view as its own tab. This is great if developers need to present several nested settings menus. However, other tabs should never try to route to the Settings tab. As we mentioned above, the only way that the Settings tab should be activated is by a user tapping the appropriate tab button. + +If you find that your tabs need to reference the Settings tab, we recommend making the Settings view a modal by using `ion-modal`. This is a practice found in the iOS App Store app. With this approach, any tab can present the modal without breaking the mobile tabs pattern of each tab being its own stack. + +The example below shows how the iOS App Store app handles presenting an "Account" view from multiple tabs. By presenting the "Account" view in a modal, the app can work within the mobile tabs best practices to show the same view across multiple tabs. + + + +**Reusing Views Across Tabs** + +Another common practice is to present the same view in multiple tabs. Developers often try to do this by having the view contained in a single tab, with other tabs routing to that tab. As we mentioned above, this breaks the mobile tabs pattern and should be avoided. + +Instead, we recommend having routes in each tab that reference the same component. This is a practice done in popular apps like Spotify. For example, you can access an album or podcast from the "Home", "Search", and "Your Library" tabs. When accessing the album or podcast, users stay within that tab. The app does this by creating routes per tab and sharing a common component in the codebase. + +The example below shows how the Spotify app reuses the same album component to show content in multiple tabs. Notice that each screenshot shows the same album but from a different tab. + +| Home Tab | Search Tab | +| :-------------------------------------------------: | :---------------------------------------------------: | +| | | diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/angular/overview.md b/i18n/ja/docusaurus-plugin-content-docs/current/angular/overview.md new file mode 100644 index 00000000000..5d29843b7e6 --- /dev/null +++ b/i18n/ja/docusaurus-plugin-content-docs/current/angular/overview.md @@ -0,0 +1,46 @@ +--- +title: Ionic Angular の概要 +sidebar_label: 概要 +--- + + + Ionic Angular Overview | Angular Version Support and Tooling + + + +import DocsCard from '@components/global/DocsCard'; +import DocsCards from '@components/global/DocsCards'; + +`@ionic/angular` は core Ionic experience に、Angular 開発者向けにカスタマイズされたツールと API を組み合わせたものです。 + +## Angular バージョンサポート + +Ionic v7 は Angular v14+をサポートしています。アップグレード戦略の一環として、Angular にはアップグレードを自動化するためのツールが組み込まれており、API に変更があった際には開発者にフィードバックを提供します。これにより、アップデートの手間を減らし、エコシステムを最新の状態に保つことができます。 + +## Angular Tooling + +Ionic4 以降では、アプリケーション構築とルーティングのために公式の Angular スタックが使用されているため、あなたのアプリケーションは Angular エコシステムと同じように利用できます。更に独自の機能が必要な場合には、Ionic は`@ionic/angular-toolkit`を提供します。、これは [official Angular CLI](https://angular.jp/cli) を構築して統合し、`@ionic/angular` アプリ固有の機能を提供します。 + +## Resources + + + +

Learn the fundamentals you need to know to start building amazing apps with Ionic Framework.

+
+ + +

Learn the basics of navigation inside your app with Ionic and Angular Router

+
+ + +

Learn about using Ionic lifecycle events in class components and with hooks

+
+ + +

Learn about using Modules or Standalone Components in Ionic.

+
+ +
diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/angular/performance.md b/i18n/ja/docusaurus-plugin-content-docs/current/angular/performance.md new file mode 100644 index 00000000000..d2c78341765 --- /dev/null +++ b/i18n/ja/docusaurus-plugin-content-docs/current/angular/performance.md @@ -0,0 +1,73 @@ +--- +title: Angularのパフォーマンス +sidebar_label: パフォーマンス +--- + + + Angular Performance: Manage App Component Change with ngFor + + + +## \*ngFor with Ionic Components + +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. + +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`: + +**home.page.html** + +```html + + {{ item.value }} + +``` + +**home.component.ts** + +```tsx + +items = [ + { id: 0, value: 'Item 0' }, + { id: 1, value: 'Item 1' }, + ... +] + +trackItems(index: number, itemObject: any) { + return itemObject.id; +} +``` + +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. + +For more information on how Angular manages change propagation with `ngFor` see https://angular.io/api/common/NgForOf#change-propagation. + +## From the Ionic Team + +[How to Lazy Load in Ionic Angular](https://ionicframework.com/blog/how-to-lazy-load-in-ionic-angular/) + +[Improved Perceived Performance with Skeleton Screens](https://ionicframework.com/blog/improved-perceived-performance-with-skeleton-screens/) + +## From the Angular Team + +[Build performant and progressive Angular apps](https://web.dev/angular) - web.dev + +## From the Community + + + +[High Performance Animations in Ionic](https://www.joshmorony.com/high-performance-animations-in-ionic/) - Josh Morony + +[High Performance List Filtering in Ionic](https://www.joshmorony.com/high-performance-list-filtering-in-ionic-2/) - Josh Morony + +[Increasing Performance with Efficient DOM Writes in Ionic](https://www.joshmorony.com/increasing-performance-with-efficient-dom-writes-in-ionic-2/) - Josh Morony + +[Ionic Framework is Fast (But Your Code Might Not Be)](https://www.joshmorony.com/ionic-framework-is-fast-but-your-code-might-not-be/) - Josh Morony + + + +:::note +Do you have a guide you'd like to share? Click the _Edit this page_ button below. +::: diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/angular/platform.md b/i18n/ja/docusaurus-plugin-content-docs/current/angular/platform.md new file mode 100644 index 00000000000..5cb3546fc72 --- /dev/null +++ b/i18n/ja/docusaurus-plugin-content-docs/current/angular/platform.md @@ -0,0 +1,246 @@ +--- +title: Platform +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + + + Platform | Ionic Platform to Customize Apps to Fit Any Device + + + +プラットフォームサービスは、現在のデバイスに関する情報を取得するために使用できます。`platforms` メソッドを利用することでデバイスに関連付けられているすべてのプラットフォームを取得できます。例えば、アプリがタブレットから表示されているかどうか(モバイルデバイスまたはブラウザ上にある場合)、および正確なプラットフォーム(iOS、Android など)などです。右から左への言語の向きなどを使用すれば、デバイスの向きもわかります。この情報を使用して、あらゆるデバイスに合わせてアプリを完全にカスタマイズできます。 + +## Usage + + + + +```tsx +import { Platform } from '@ionic/angular'; + +@Component({...}) +export class MyPage { + constructor(public platform: Platform) { + + } +} +``` + + + + +```tsx +import { Platform } from '@ionic/angular/standalone'; + +@Component({...}) +export class MyPage { + constructor(public platform: Platform) { + + } +} +``` + + + + +## Methods + +### `is` + +| | | +| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **Description** | Depending on the platform the user is on, `is(platformName)` will return true or false. Note that the same app can return true for more than one platform name. For example, an app running from an iPad would return true for the platform names: `mobile`, `ios`, `ipad`, and `tablet`. Additionally, if the app was running from Cordova then `cordova` would be true. | +| **Signature** | `is(platformName: Platforms) => boolean` | + +#### Parameters + +| Name | Type | Description | +| -------------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | +| `platformName` | `Platforms` | Name of the platform. Available options are android, capacitor, cordova, desktop, electron, hybrid, ios, ipad, iphone, mobile, phablet, pwa, tablet | + +#### Platforms + +以下は、利用可能なすべての platform の値とそれに対応する説明をまとめた表です。 + +| Platform Name | Description | +| ------------- | ---------------------------------------- | +| android | a device running Android | +| capacitor | a device running Capacitor | +| cordova | a device running Cordova | +| desktop | a desktop device | +| electron | a desktop device running Electron | +| hybrid | a device running Capacitor or Cordova | +| ios | a device running iOS | +| ipad | an iPad device | +| iphone | an iPhone device | +| mobile | a mobile device | +| mobileweb | a web browser running in a mobile device | +| phablet | a phablet device | +| pwa | a PWA app | +| tablet | a tablet device | + +#### Customizing Platform Detection Functions + +The function used to detect a specific platform can be overridden by providing an alternative function in the global [Ionic config](../developing/config). Each function takes `window` as a parameter and returns a boolean. + +```tsx +import { IonicModule } from '@ionic/angular'; + +@NgModule({ + ... + imports: [ + BrowserModule, + IonicModule.forRoot({ + platform: { + /** The default `desktop` function returns false for devices with a touchscreen. + * This is not always wanted, so this function tests the User Agent instead. + **/ + 'desktop': (win) => { + const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(win.navigator.userAgent); + return !isMobile; + } + }, + }), + AppRoutingModule + ], + ... +}) +``` + +```ts +type PlatformConfig = { + android?: ((win: Window) => boolean) | undefined; + capacitor?: ((win: Window) => boolean) | undefined; + cordova?: ((win: Window) => boolean) | undefined; + desktop?: ((win: Window) => boolean) | undefined; + electron?: ((win: Window) => boolean) | undefined; + hybrid?: ((win: Window) => boolean) | undefined; + ios?: ((win: Window) => boolean) | undefined; + ipad?: ((win: Window) => boolean) | undefined; + iphone?: ((win: Window) => boolean) | undefined; + mobile?: ((win: Window) => boolean) | undefined; + mobileweb?: ((win: Window) => boolean) | undefined; + phablet?: ((win: Window) => boolean) | undefined; + pwa?: ((win: Window) => boolean) | undefined; + tablet?: ((win: Window) => boolean) | undefined; +}; +``` + +### `platforms` + +| | | +| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **Description** | Depending on what device you are on, `platforms` can return multiple values. Each possible value is a hierarchy of platforms. For example, on an iPhone, it would return `mobile`, `ios`, and `iphone`. | +| **Signature** | `platforms() => string[]` | + +### `ready` + +| | | +| --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **Description** | Returns a promise when the platform is ready and native functionality can be called. If the app is running from within a web browser, then the promise will resolve when the DOM is ready. When the app is running from an application engine such as Cordova, then the promise will resolve when Cordova triggers the `deviceready` event. The resolved value is the `readySource`, which states the platform that was used.

For example, when Cordova is ready, the resolved ready source is `cordova`. The default ready source value will be `dom`. The `readySource` is useful if different logic should run depending on the platform the app is running from. For example, only Capacitor and Cordova can execute the status bar plugin, so the web should not run status bar plugin logic. | +| **Signature** | `ready() => Promise` | + +### `isRTL` + +| | | +| --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **Description** | Returns if this app is using right-to-left language direction or not. We recommend the app's `index.html` file already has the correct `dir` attribute value set, such as `` or ``. [W3C: Structural markup and right-to-left text in HTML](http://www.w3.org/International/questions/qa-html-dir) | +| **Signature** | `isRTL() => boolean` | + +### `isLandscape` + +| | | +| --------------- | ----------------------------------------------- | +| **Description** | Returns `true` if the app is in landscape mode. | +| **Signature** | `isLandscape() => boolean` | + +### `isPortrait` + +| | | +| --------------- | ---------------------------------------------- | +| **Description** | Returns `true` if the app is in portrait mode. | +| **Signature** | `isPortrait() => boolean` | + +### `width` + +| | | +| --------------- | -------------------------------------------------------------------- | +| **Description** | Gets the width of the platform's viewport using `window.innerWidth`. | +| **Signature** | `width() => number` | + +### `height` + +| | | +| --------------- | ---------------------------------------------------------------------- | +| **Description** | Gets the height of the platform's viewport using `window.innerHeight`. | +| **Signature** | `height() => number` | + +### `url` + +| | | +| --------------- | -------------------- | +| **Description** | Get the current url. | +| **Signature** | `url() => string` | + +### `testUserAgent` + +| | | +| --------------- | ---------------------------------------------------------------------- | +| **Description** | Returns `true` if the expression is included in the user agent string. | +| **Signature** | `testUserAgent(expression: string) => boolean` | + +#### Parameters + +| Name | Type | Description | +| ---------- | ------ | ------------------------------------- | +| expression | string | The string to check in the user agent | + +## Events + +### `pause` + +`pause` イベントは、ネイティブ・プラットフォームがアプリケーションをバックグラウンドに置いたとき、通常はユーザーが別のアプリケーションに切り替えたときに発生します。このイベントは、Cordova/Capacitor アプリケーションがバックグラウンドに置かれたときに発生しますが、標準的な Web ブラウザでは発生しません。 + +#### Examples + +```tsx +this.platform.pause.subscribe(async () => { + alert('Pause event detected'); +}); +``` + +### `resize` + +`resize` イベントは、ブラウザウィンドウの寸法が変更されたときに発生します。これは、ブラウザーウィンドウが物理的にサイズ変更されている場合や、デバイスの向きが変わっている場合に発生します。 + +#### Examples + +```tsx +this.platform.resize.subscribe(async () => { + alert('Resize event detected'); +}); +``` + +### `resume` + +`resume` イベントは、ネイティブプラットフォームがバックグラウンドからアプリケーションを引き出したときに発生します。このイベントは、Cordova/Capacitor アプリがバックグラウンドから出てきても、標準的な Web ブラウザで起動しない場合に発生します。 + +#### Examples + +```tsx +this.platform.resume.subscribe(async () => { + alert('Resume event detected'); +}); +``` diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/angular/pwa.md b/i18n/ja/docusaurus-plugin-content-docs/current/angular/pwa.md new file mode 100644 index 00000000000..684c150c457 --- /dev/null +++ b/i18n/ja/docusaurus-plugin-content-docs/current/angular/pwa.md @@ -0,0 +1,166 @@ +--- +title: AngularでのPWA +sidebar_label: Progressive Web Apps +--- + + + Make Progressive Web Apps (PWA) in Angular - Ionic Tutorial + + + +## Making your Angular app a PWA + +The two main requirements of a PWA are a
Service Worker and a Web Manifest. While it's possible to add both of these to an app manually, the Angular team has an `@angular/pwa` package that can be used to automate this. + +The `@angular/pwa` package will automatically add a service worker and an app manifest to the app. +To add this package to the app, run: + +```shell +ng add @angular/pwa +``` + +Once this package has been added run `ionic build --prod` and the `www` directory will be ready to deploy as a PWA. + +:::note +By default, the `@angular/pwa` package comes with the Angular logo for the app icons. Be sure to update the manifest to use the correct app name and also replace the icons. +::: + +:::note +Features like Service Workers and many JavaScript APIs (such as geolocation) require the app be hosted in a secure context. When deploying an app through a hosting service, be aware that HTTPS will be required to take full advantage of Service Workers. +::: + +## Service Worker configuration + +After `@angular/pwa` has been added, a new `ngsw-config.json` file will be created at the root of the project. This file is responsible for configuring how Angular's service worker mechanism will handle caching assets. By default, the following will be provided: + +```json +{ + "$schema": "./node_modules/@angular/service-worker/config/schema.json", + "index": "/index.html", + "assetGroups": [ + { + "name": "app", + "installMode": "prefetch", + "resources": { + "files": ["/favicon.ico", "/index.html", "/*.css", "/*.js"] + } + }, + { + "name": "assets", + "installMode": "lazy", + "updateMode": "prefetch", + "resources": { + "files": ["/assets/**", "/*.(eot|svg|cur|jpg|png|webp|gif|otf|ttf|woff|woff2|ani)"] + } + } + ] +} +``` + +There are two sections in here, one for app specific resources (JS, CSS, HTML) and assets the app will load on demand. Depending on your app, these options can be customized. For a more detailed guide, read [the official guide from the Angular Team.](https://angular.io/guide/service-worker-config) + +## Deploying + +### Firebase + +Firebase hosting provides many benefits for Progressive Web Apps, including fast response times thanks to CDNs, HTTPS enabled by default, and support for [HTTP2 push](https://firebase.googleblog.com/2016/09/http2-comes-to-firebase-hosting.html). + +First, if not already available, [create the project](https://console.firebase.google.com) in Firebase. + +Next, in a Terminal, install the Firebase CLI: + +```shell +npm install -g firebase-tools +``` + +:::note +If it's the first time you use firebase-tools, login to your Google account with `firebase login` command. +::: + +With the Firebase CLI installed, run `firebase init` within your Ionic project. The CLI prompts: + +**"Which Firebase CLI features do you want to set up for this folder?"** Choose "Hosting: Configure files for Firebase Hosting and (optionally) set up GitHub Action deploys". + +Create a new Firebase project or select an existing one. + +**"Select a default Firebase project for this directory:"** Choose the project you created on the Firebase website. + +**"What do you want to use as your public directory?"** Enter "www". + +:::note +Answering this next question will ensure that routing, hard reload, and deep linking work in the app: +::: + +**Configure as a single-page app (rewrite all urls to /index.html)?"** Enter "Yes". + +**"File build/index.html already exists. Overwrite?"** Enter "No". + +**Set up automatic builds and deploys with Github?** Enter "Yes". + +**For which GitHub repository would you like to set up a Github Workflow?** Enter your project name. + +**Set up the workflow to run a build script before every deploy?** Enter "Yes". + +**What script should be run before every deploy?** Enter `npm ci && npm run build`. + +**Set up automatic deployment to your sites live channel when a PR is merged?** Enter "Yes". + +**What is the name of the get hooked branch associated with your sites live channel?** Enter your project's main branch name. + +A `firebase.json` config file is generated, configuring the app for deployment. + +The last thing needed is to make sure caching headers are being set correctly. To do this, add a `headers` snippet to the `firebase.json` file. The complete `firebase.json` looks like: + +```json +{ + "hosting": { + "public": "www", + "ignore": ["firebase.json", "**/.*", "**/node_modules/**"], + "rewrites": [ + { + "source": "**", + "destination": "/index.html" + } + ], + "headers": [ + { + "source": "/build/app/**", + "headers": [ + { + "key": "Cache-Control", + "value": "public, max-age=31536000" + } + ] + }, + { + "source": "ngsw-worker.js", + "headers": [ + { + "key": "Cache-Control", + "value": "no-cache" + } + ] + } + ] + } +} +``` + +For more information about the `firebase.json` properties, see the [Firebase documentation](https://firebase.google.com/docs/hosting/full-config#section-firebase-json). + +Next, build an optimized version of the app by running: + +```shell +ionic build --prod +``` + +Last, deploy the app by running: + +```shell +firebase deploy +``` + +After this completes, the app will be live. diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/angular/slides.md b/i18n/ja/docusaurus-plugin-content-docs/current/angular/slides.md new file mode 100644 index 00000000000..1d9efbc2bcc --- /dev/null +++ b/i18n/ja/docusaurus-plugin-content-docs/current/angular/slides.md @@ -0,0 +1,366 @@ +--- +title: Migrating from ion-slides to Swiper.js +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + + + Set Up Swiper.js for Angular Slides [Example] | Ionic + + + +:::warning Looking for `ion-slides`? +`ion-slides` was deprecated in v6.0.0 and removed in v7.0.0. We recommend using the Swiper.js library directly. The migration process is detailed below. +::: + +We recommend Swiper.js if you need a modern touch slider component. Swiper 9 introduced Swiper Element as a replacement for its Angular component, so this guide will go over how to get Swiper Element set up in your Ionic Framework application. It will also go over any migration information you may need to move from `ion-slides` to Swiper Element. + +## Getting Started + +First, update to the latest version of Ionic: + +```shell +npm install @ionic/angular@latest +``` + +Once that is done, install the Swiper dependency in your project: + +```shell +npm install swiper@latest +``` + +Next, we need to add the `CUSTOM_ELEMENTS_SCHEMA`, which tells Angular that we will be using custom elements. This can be done in either `app.module.ts`, or the module file for the component where you will be using Swiper. + +```typescript +import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; + +@NgModule({ + schemas: [..., CUSTOM_ELEMENTS_SCHEMA] +}); +... +``` + +Finally, we need to call Swiper's `register` function to globally register Swiper's custom elements. This should only be done once, so place it in `app.component.ts`. + +```typescript +import { register } from 'swiper/element/bundle'; + +register(); + +@Component({ + ... +}) +... +``` + +From there, we just have to replace `ion-slides` elements with `swiper-container` and `ion-slide` elements with `swiper-slide`. Note that these custom elements do not need to be imported, as calling `register` tells Angular about them on its own. + +```html + + Slide 1 + Slide 2 + Slide 3 + +``` + +## Bundled vs. Core Versions + +By default, make sure you import the `register` function from `swiper/element/bundle`. This uses the bundled version of Swiper, which automatically includes all modules and stylesheets needed to run Swiper's various features. + +If you would like to use the Core version instead, which does not include additional modules automatically, see https://swiperjs.com/element#core-version-and-modules. The rest of this migration guide will assume you are using the bundled version. + +## Swiping with Style + +To migrate over your CSS, first update your selectors to target the new custom elements instead: + +| ion-slides Selector | Swiper Selector | +| ------------------- | ------------------ | +| `ion-slides` | `swiper-container` | +| `ion-slide` | `swiper-slide` | + +If you were using the CSS custom properties found on `ion-slides`, below is a list of corresponding properties used in Swiper. + +| `ion-slides` CSS property | `swiper-container` CSS property | +| ---------------------------------- | ------------------------------------------- | +| `--bullet-background` | `--swiper-pagination-bullet-inactive-color` | +| `--bullet-background-active` | `--swiper-pagination-color` | +| `--progress-bar-background` | `--swiper-pagination-progressbar-bg-color` | +| `--progress-bar-background-active` | `--swiper-pagination-color` | +| `--scroll-bar-background` | `--swiper-scrollbar-bg-color` | +| `--scroll-bar-background-active` | `--swiper-scrollbar-drag-bg-color` | + +For additional custom CSS, because Swiper Element uses Shadow DOM encapsulation, styles will need to be injected into the Shadow DOM scope. See https://swiperjs.com/element#injecting-styles for instructions. + +### Additional `ion-slides` Styles + +The `ion-slides` component had additional styling that helped create a native look and feel. These styles are **not** required to use Swiper.js with Ionic, but if you would like to maintain the look of `ion-slides` as closely as possible, add the following CSS to your `global.scss`: + +```css +swiper-container { + --swiper-pagination-bullet-inactive-color: var(--ion-color-step-200, #cccccc); + --swiper-pagination-color: var(--ion-color-primary, #3880ff); + --swiper-pagination-progressbar-bg-color: rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.25); + --swiper-scrollbar-bg-color: rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.1); + --swiper-scrollbar-drag-bg-color: rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.5); +} + +swiper-slide { + display: flex; + position: relative; + + flex-direction: column; + flex-shrink: 0; + align-items: center; + justify-content: center; + + width: 100%; + height: 100%; + + font-size: 18px; + + text-align: center; + box-sizing: border-box; +} + +swiper-slide img { + width: auto; + max-width: 100%; + height: auto; + max-height: 100%; +} +``` + +## The IonicSlides Module + +With `ion-slides`, Ionic automatically customized dozens of Swiper properties. This resulted in an experience that felt smooth when swiping on mobile devices. We recommend using the `IonicSlides` module to ensure that these properties are also set when using Swiper directly. However, using this module is **not** required to use Swiper.js in Ionic. + +It is recommended to review the [properties](https://github.com/ionic-team/ionic-framework/blob/main/core/src/components/slides/IonicSlides.ts) set by `IonicSlides` and determine which ones you would like to customize. + +We can install the `IonicSlides` module by importing and passing it to the `modules` property of `swiper-container` as an array: + + + + +```typescript +// home.page.ts + +import { IonicSlides } from '@ionic/angular'; + +@Component({ + ... +}) +export class HomePage { + swiperModules = [IonicSlides]; +} +``` + + + + +```typescript +// home.page.ts + +import { IonicSlides } from '@ionic/angular/standalone'; + +@Component({ + ... +}) +export class HomePage { + swiperModules = [IonicSlides]; +} +``` + + + + +```html + + + ... +``` + +:::note +If you are using the Core version of Swiper and have installed additional modules, ensure that `IonicSlides` is the last module in the array. This will let it automatically customize the settings of modules such as Pagination, Scrollbar, Zoom, and more. +::: + +## Properties + +Swiper options should be provided as individual properties directly on the `` component. + +Let's say in an app with `ion-slides` we had the `slidesPerView` and `loop` options set: + +```html + + Slide 1 + Slide 3 + Slide 3 + +``` + +To set these options as properties directly on `` we would do the following: + +```html + + Slide 1 + Slide 2 + Slide 3 + +``` + +Below is a full list of property changes when going from `ion-slides` to Swiper Element: + +| Name | Notes | +| ------- | --------------------------------------------------------------------------------------------------------------------------------------- | +| options | Set each option as a property directly on the `` component. | +| mode | For different styles based upon the mode, you can target the slides with `.ios swiper-container` or `.md swiper-container` in your CSS. | +| pager | Use the `pagination` property instead. | + +:::note +All properties available in Swiper Element can be found at https://swiperjs.com/swiper-api#parameters. +::: + +## Events + +Since the `swiper-container` component is not provided by Ionic Framework, event names will not have an `ionSlide` prefix to them. Additionally, all event names should be lowercase instead of camelCase. + +Let's say in an app with `ion-slides` we used the `ionSlideDidChange` event: + +```html + + Slide 1 + Slide 3 + Slide 3 + +``` + +To migrate, we would change the name of the event to `slidechange`: + +```html + + Slide 1 + Slide 2 + Slide 3 + +``` + +Below is a full list of event name changes when going from `ion-slides` to Swiper Angular: + +| ion-slides Event | Swiper Event | +| ------------------------- | ---------------------------- | +| `ionSlideWillChange` | `slidechangetransitionstart` | +| `ionSlideDidChange` | `slidechangetransitionend` | +| `ionSlideDoubleTap` | `doubletap` | +| `ionSlideDrag` | `slidermove` | +| `ionSlideNextStart` | `slidenexttransitionstart` | +| `ionSlideNextEnd` | `slidenexttransitionend` | +| `ionSlidePrevStart` | `slideprevtransitionstart` | +| `ionSlidePrevEnd` | `slideprevtransitionend` | +| `ionSlideReachStart` | `reachbeginning` | +| `ionSlideReachEnd` | `reachend` | +| `ionSlideTap` | `tap` | +| `ionSlideTouchStart` | `touchstart` | +| `ionSlideTouchEnd` | `touchend` | +| `ionSlideTransitionStart` | `transitionstart` | +| `ionSlideTransitionEnd` | `transitionend` | +| `ionSlidesDidLoad` | `init` | + +:::note +All events available in Swiper Element can be found at https://swiperjs.com/swiper-api#events. +::: + +## Methods + +Most methods have been removed in favor of directly accessing the properties of the Swiper instance. To access the Swiper instance, first get a reference to the `` element (such as through `ViewChild`), then access its `swiper` prop: + +```html + + + + Slide 1 + Slide 2 + Slide 3 + +``` + +```typescript +// slides.component.ts + +import { ..., ElementRef, ViewChild } from '@angular/core'; + +@Component({ + ... +}) +export class SlidesExample { + @ViewChild('swiper') + swiperRef: ElementRef | undefined; + + logActiveIndex() { + console.log(this.swiperRef?.nativeElement.swiper.activeIndex); + } +} +``` + +Below is a full list of method changes when going from `ion-slides` to Swiper Element: + +| ion-slides Method | Notes | +| -------------------- | ------------------------------------------------------------------------------------ | +| `getActiveIndex()` | Use the `activeIndex` property instead. | +| `getPreviousIndex()` | Use the `previousIndex` property instead. | +| `getSwiper()` | Get a reference to the Swiper instance using the `swiper` prop. See example above. | +| `isBeginning()` | Use the `isBeginning` property instead. | +| `isEnd()` | Use the `isEnd` property instead. | +| `length()` | Use the `slides` property instead. (i.e swiper.slides.length) | +| `lockSwipeToNext()` | Use the `allowSlidesNext` property instead. | +| `lockSwipeToPrev()` | Use the `allowSlidePrev` property instead. | +| `lockSwipes()` | Use the `allowSlideNext`, `allowSlidePrev`, and `allowTouchMove` properties instead. | +| `startAutoplay()` | Use the `autoplay` property instead. | +| `stopAutoplay()` | Use the `autoplay` property instead. | + +:::note +All methods and properties available on the Swiper instance can be found at https://swiperjs.com/swiper-api#methods-and-properties. +::: + +## Effects + +Effects such as Cube or Fade can be used in Swiper Element with no additional imports, as long as you are using the bundled version of Swiper. For example, the below code will cause the slides to have a flip transition effect: + +```html + ... +``` + +:::note +For more information on effects in Swiper, please see https://swiperjs.com/swiper-api#fade-effect. +::: + +## Wrap Up + +Now that you have Swiper installed, there is a whole set of new Swiper features for you to enjoy. We recommend starting with the Swiper Element documentation and then referencing the Swiper API docs. + +## FAQ + +### Where can I find an example of this migration? + +You can find a sample app with `ion-slides` and the equivalent Swiper usage at https://github.com/ionic-team/slides-migration-samples. + +### Where can I get help with this migration? + +If you are running into issues with the migration, please create a post on the [Ionic Forum](https://forum.ionicframework.com/). + +### Where do I file bug reports? + +Before opening an issue, please consider creating a post on the Swiper Discussion Board or the Ionic Forum to see if your issue can be resolved by the community. + +If you are running into problems with the Swiper library, new bugs should be filed on the Swiper repo: https://github.com/nolimits4web/swiper/issues + +If you are running into problems with the `IonicSlides` module, new bugs should be filed on the Ionic Framework repo: https://github.com/ionic-team/ionic-framework/issues diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/angular/storage.md b/i18n/ja/docusaurus-plugin-content-docs/current/angular/storage.md new file mode 100644 index 00000000000..23c365eb7d4 --- /dev/null +++ b/i18n/ja/docusaurus-plugin-content-docs/current/angular/storage.md @@ -0,0 +1,32 @@ +--- +title: データストレージ +sidebar_label: ストレージ +--- + + + Angular App Data Storage Options - Ionic Documentation + + + +Ionic アプリ内にデータを保存するためのさまざまなオプションを用意しています。 + +Here are two official Ionic options: + +## Ionic Secure Storage + +For teams building mission-critical apps or requiring encryption support, [Ionic Secure Storage](https://ionic.io/docs/secure-storage) is an official premium solution from the Ionic team that provides a cross-platform data storage system that works on iOS and Android. + +It makes it easy to build high performance, offline-ready Ionic apps across iOS, Android, and the web. + +[Learn more](https://ionic.io/products/secure-storage) + +## @ionic/storage + +For developers not requiring encryption nor relational data support, [@ionic/storage](https://github.com/ionic-team/ionic-storage) is an open source key/value API for building apps that work across storage engines on multiple platforms. + +Additionally, Ionic Secure Storage has a driver that works with the key/value API in `@ionic/storage` while providing encryption and SQLite support. + +Learn more about [@ionic/storage](https://github.com/ionic-team/ionic-storage) diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/angular/testing.md b/i18n/ja/docusaurus-plugin-content-docs/current/angular/testing.md new file mode 100644 index 00000000000..095c38c8061 --- /dev/null +++ b/i18n/ja/docusaurus-plugin-content-docs/current/angular/testing.md @@ -0,0 +1,593 @@ +--- +title: テスト +--- + + + Angular Unit and End-to-End Testing for Ionic App Components + + + +Ionic CLI を使用して `@ionic/angular` アプリケーションを生成すると、アプリケーションのユニットテストとエンドツーエンドのテスト用に自動的に準備されます。これは Angular CLI で使われる設定と同じものです。Angular で作られたアプリケーションのテストについての詳細は Angular Testing Guide をご参照ください。 + +## テストの原則 + +アプリケーションをテストするときは、テストによってシステムに欠陥があるかどうかを確認できる、ということを覚えておくことが一番です。しかし、どんなささいなシステムも完全に欠陥のないことを証明することは不可能です。このため、テストの目的はコードが正しいことを確認することではなく、コードの中の問題を見つけることです。これは微妙ですが、重要な違いです。 + +もし私たちがコードが正しいことを証明しようとするのであれば、私たちはコードを通じて幸せな道を歩み続けようとするでしょう。もし私が問題の発見しようとするのであれば、コードをより完全に実行し、そこに潜むバグを発見する可能性が高くなります。 + +最初からアプリケーションのテストを開始することも最良です。これにより、修正が容易な段階で早期に欠陥を発見できます。またこれにより、システムに新しい機能が追加されたときに、コードを確実にリファクタリングすることもできます。 + +## ユニットテスト + +ユニットテストでは、システムの他の部分から分離して、単一のコードユニット(Component、Page、Service、Pipe など)を実行します。分離は、コードの依存関係の代わりにモックオブジェクトを注入することによって実現されます。モックオブジェクトによって、テストは依存関係の切り出しをきめ細かく制御することができます。モックによって、どの依存関係が呼び出され、何が渡されたかをテストで判断することもできます。 + +適切に記述されたユニットテストは、コードの単位とそれに含まれる機能が `describe()` コールバックによって記述されるように構成されています。コード単位とその機能の要件は、`it()` コールバックによってテストされます。`describe()` コールバックと `it()` コールバックの説明を読むと、フレーズとして意味がわかります。ネストされた `describe()` と最後の `it()` の記述をつなげると、テストケースを完全に記述する文が形成されます。 + +ユニットテストはコードを分離して実行するため、高速で堅牢であり、高度なコードカバレッジが可能です。 + +### モックの利用 + +ユニットテストでは、コードをコードをモジュールで分離して実行します。これを簡単にするには、Jasmine(https://jasmine.github.io/) を使用することをお勧めします。Jasmine は、テスト実行中に依存関係の代わりにモックオブジェクト(Jasmine は 「スパイ」 と呼んでいます)を作成します。モックオブジェクトを使用すると、テストはその依存関係への呼び出しによって返される値を制御できるため、依存関係に加えられた変更から現在のテストを独立させることができます。これにより、テストのセットアップも簡単になり、テスト対象のモジュール内のコードだけをテストすることができます。 + +モックを使用すると、モックが呼び出されたかどうか、および `toHaveBeenCalled*` セットの関数を介してどのように呼び出されたかを判断するために、テストでモックを確認することもできます。これらの関数では、メソッドが呼び出されたことをテストするときに、`toHaveBeenCalled` メソッドの呼び出しよりも `toHaveBeenCalledTimes` の呼び出しを優先して、テストをできるだけ具体的に行う必要があります。つまり、`expect(mock.foo).toHaveBeenCalledTimes(1)` は `expect(mock.foo).toHaveBeenCalled()` よりも優れています。何かが呼ばれていないこと(`expect(mock.foo).not.toHaveBeenCalled()`)をテストする際は、逆のアドバイスに従うべきです。 + +Jasmine でモックオブジェクトを作成する一般的な方法は 2 つあります。モックオブジェクトは、`jasmine.createSpy` と`jasmine.createSpyObj` を使ってスクラッチで作成することも、`spyOn()` と `spyOnProperty()` を使って既存のオブジェクトにスパイをインストールすることもできます。 + +### `jasmine.createSpy` と `jasmine.createSpyObj` の利用 + +`jasmine.createSpyObj` は、作成時に定義された一連のモックメソッドを使用して、完全なモックオブジェクトをスクラッチで作成します。これはとてもシンプルで便利です。テストのために何かを組み立てたり注入したりする必要はありません。この関数の使用する欠点は、実際のオブジェクトと一致しないオブジェクトを生成できることです。 + +`jasmine.createSpy` も似ていますが、スタンドアロンのモック関数を作成します。 + +#### `spyOn()` と `spyOnProperty()` の利用 + +`spyOn()` は、既存のオブジェクトにスパイをインストールします。この手法を使用する利点は、オブジェクト上に存在しないメソッドをスパイしようとすると、例外が発生することです。これにより、テストが存在しないメソッドをモックすることを防ぎます。欠点は、テストが最初から完全に整形されたオブジェクトを必要とすることであり、これはテストに必要なセットアップの量を増加させるかと思います。 + +`spyOnProperty()` は似ていますが、メソッドではなくプロパティに対してスパイするという点で異なります。 + +### 一般的なテストの構成 + +ユニットテストは、エンティティ(Component、Page、Service、Pipe など)ごとに 1 つの `spec` ファイルを持つ `spec` ファイルに含まれています。`spec` ファイルは、テスト中のソースと一緒に存在し、かつその名前が付けられます。たとえば、プロジェクトに WeatherService という Service がある場合、そのコードは`weather.service.ts` という名前のファイルにあり、テストは `weather.service.spec.ts` という名前のファイルにあります。これらのファイルは両方とも同じフォルダにあります。 + +`spec` ファイル自体には、そのテスト全体を定義するただ一つの `describe` コールが含まれています。その中には、主要な機能領域を定義する他の `describe` コールがネストされています。各 `describe` コールには、setup コードと teardown コード(一般的に `beforeEach` と `afterEach` コールによって処理される)、機能を階層的に分解した `describe` コール、また個々のテストケースを定義する `it` コールが含まれます。 + +`describe` と `it` コールには、説明のテキストラベルも含まれます。適切な形式のテストでは、`describe` と `it` をコールすると、ラベルと組み合わせた適切なフレーズが実行され、各テストケースのすべてのラベルが `describe` と `it` ラベルを組み合わせて構成され、完全な文が作成されます。 + +例: + +```tsx +describe('Calculation', () => { + describe('divide', () => { + it('calculates 4 / 2 properly' () => {}); + it('cowardly refuses to divide by zero' () => {}); + ... + }); + + describe('multiply', () => { + ... + }); +}); +``` + +外側の `describe` コールは `Calculation` Service がテストされていることを示し、内側の `describe` コールはテストされている機能を正確に示し、そして `it` コールはテストケースが何であるかを示しています。各テストケースの完全なラベルを実行すると、意味のある文になります(卑劣な 0 での除算という計算を拒否しました)。 + +### ページとコンポーネント + +Pages は単なる Angular コンポーネントです。そのため、ページとコンポーネントは両方とも Angular のコンポーネントテストガイドライン を使ってテストされます。 + +ページとコンポーネントには TypeScript コードと HTML テンプレートマークアップの両方が含まれているため、コンポーネントクラスのテストとコンポーネント DOM のテストの両方を実行できます。ページが作成されると、生成されるテンプレートテストは次のようになります: + +```tsx +import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TabsPage } from './tabs.page'; + +describe('TabsPage', () => { + let component: TabsPage; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [TabsPage], + schemas: [CUSTOM_ELEMENTS_SCHEMA], + }).compileComponents(); + + fixture = TestBed.createComponent(TabsPage); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); +``` + +コンポーネントクラスのテストを行う場合、コンポーネントオブジェクトは `component=fixture.componentInstance;` によって定義されたコンポーネントオブジェクトを使用してアクセスされます。これはコンポーネントクラスのインスタンスです。DOM テストを行う際には、`fixture.nativeElement` プロパティが使用されます。これはコンポーネントの実際の `HTMLElement`であり、テストで DOM を調べるために `HTMLElement.querySelector` などの標準の HTML API メソッドを使うことを可能にします。 + +## Service + +Service は、多くの場合、計算やその他の操作を実行するユーティリティの service と、主に HTTP 操作やデータ操作を実行するデータの service の 2 つの大まかなカテゴリーのいずれかに分類されます。 + +### 基本的な Service のテスト + +ほとんどの service をテストするために推奨する方法は、service をインスタンス化し、service が持つ依存関係のモックを手動で注入することです。こうすることで、コードを分離してテストすることができます。 + +たとえば、タイムカードの配列を取得して差引支給額を計算するメソッドを持つ service があるとします。また税金計算は、現在の service が依存しているもう一つの service を介して処理されるとします。この給与計算の service は、このようにテストすることができます: + +```tsx +import { PayrollService } from './payroll.service'; + +describe('PayrollService', () => { + let service: PayrollService; + let taxServiceSpy; + + beforeEach(() => { + taxServiceSpy = jasmine.createSpyObj('TaxService', { + federalIncomeTax: 0, + stateIncomeTax: 0, + socialSecurity: 0, + medicare: 0 + }); + service = new PayrollService(taxServiceSpy); + }); + + describe('net pay calculations', () => { + ... + }); +}); +``` + +これにより、テストでは `taxServiceSpy.federalIncomeTax.and.returnValue(73.24)` などのモックの設定を介して様々な税金計算から戻される値を制御できます。これにより、「差引支給額」のテストを税金計算ロジックから独立させることができます。税金のコードが変更された場合、修正する必要があるのは税金 service 関連のコードとテストのみです。差引支給額のテストは、税金がどのように計算されるかを考慮せず、値が適切に適用されるのみであるため、そのまま機能し続けることができます。 + +`ionic g service name` で service を生成するときに使われる scaffold は Angular のテストユーティリティを使ってテストモジュールをセットアップします。必ずしもそうする必要はありません。ただし、このコードを残しておくことで、手動でサービスを構築したり、次のように注入したりすることができます: + +```tsx +import { TestBed, inject } from '@angular/core/testing'; + +import { PayrollService } from './payroll.service'; +import { TaxService } from './tax.service'; + +describe('PayrolService', () => { + let taxServiceSpy; + + beforeEach(() => { + taxServiceSpy = jasmine.createSpyObj('TaxService', { + federalIncomeTax: 0, + stateIncomeTax: 0, + socialSecurity: 0, + medicare: 0, + }); + TestBed.configureTestingModule({ + providers: [PayrollService, { provide: TaxService, useValue: taxServiceSpy }], + }); + }); + + it('does some test where it is injected', inject([PayrollService], (service: PayrollService) => { + expect(service).toBeTruthy(); + })); + + it('does some test where it is manually built', () => { + const service = new PayrollService(taxServiceSpy); + expect(service).toBeTruthy(); + }); +}); +``` + +#### HTTP データ Service のテスト + +HTTP 操作を実行するほとんどの service は、それらの操作を実行するために Angular の HttpClient service を使用します。そのようなテストには、Angular の `HttpClientTestingModule` を使うことが推奨されています。このモジュールの詳細なドキュメントは Angular の HTTP リクエストをテストする のガイドを参照してください。 + +このようなテストの基本的な設定は次のようになります: + +```tsx +import { HttpBackend, HttpClient } from '@angular/common/http'; +import { HttpTestingController, HttpClientTestingModule } from '@angular/common/http/testing'; +import { TestBed, inject } from '@angular/core/testing'; + +import { IssTrackingDataService } from './iss-tracking-data.service'; + +describe('IssTrackingDataService', () => { + let httpClient: HttpClient; + let httpTestingController: HttpTestingController; + let issTrackingDataService: IssTrackingDataService; + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [HttpClientTestingModule], + providers: [IssTrackingDataService], + }); + + httpClient = TestBed.get(HttpClient); + httpTestingController = TestBed.get(HttpTestingController); + issTrackingDataService = new IssTrackingDataService(httpClient); + }); + + it('exists', inject([IssTrackingDataService], (service: IssTrackingDataService) => { + expect(service).toBeTruthy(); + })); + + describe('location', () => { + it('gets the location of the ISS now', () => { + issTrackingDataService.location().subscribe((x) => { + expect(x).toEqual({ longitude: -138.1719, latitude: 44.4423 }); + }); + const req = httpTestingController.expectOne('http://api.open-notify.org/iss-now.json'); + expect(req.request.method).toEqual('GET'); + req.flush({ + iss_position: { longitude: '-138.1719', latitude: '44.4423' }, + timestamp: 1525950644, + message: 'success', + }); + httpTestingController.verify(); + }); + }); +}); +``` + +### Pipe + +pipe は、特別に定義されたインタフェースを持つ service のようなものです。このクラスには、入力値(およびその他のオプションの引数)を操作してページにレンダリングされる出力を作成するための public メソッド `transform` が含まれています。パイプをテストするには、パイプをインスタンス化し、transform メソッドを呼び出して結果を検証します。 + +簡単な例として、`Person` オブジェクトを受け取り、名前をフォーマットする pipe を見てみましょう。簡単にするために、`Person` は `id`、`firstName`、`lastName`、`middleInitial` で構成されるとします。パイプの要件は、名・姓・ミドルネームのいずれかが存在しない場合に、名前を「性、名 M(ミドルネーム)。」として出力することです。このようなテストは次のようになります: + +```tsx +import { NamePipe } from './name.pipe'; + +import { Person } from '../../models/person'; + +describe('NamePipe', () => { + let pipe: NamePipe; + let testPerson: Person; + + beforeEach(() => { + pipe = new NamePipe(); + testPerson = { + id: 42, + firstName: 'Douglas', + lastName: 'Adams', + middleInitial: 'N', + }; + }); + + it('exists', () => { + expect(pipe).toBeTruthy(); + }); + + it('formats a full name properly', () => { + expect(pipe.transform(testPerson)).toBeEqual('Adams, Douglas N.'); + }); + + it('handles having no middle initial', () => { + delete testPerson.middleInitial; + expect(pipe.transform(testPerson)).toBeEqual('Adams, Douglas'); + }); + + it('handles having no first name', () => { + delete testPerson.firstName; + expect(pipe.transform(testPerson)).toBeEqual('Adams N.'); + }); + + it('handles having no last name', () => { + delete testPerson.lastName; + expect(pipe.transform(testPerson)).toBeEqual('Douglas N.'); + }); +}); +``` + +また、pipe を利用するコンポーネントおよびページでの DOM テストを介して pipe を実行することも有益です。 + +## エンドツーエンドテスト + +エンドツーエンドのテストは、アプリケーションが全体として機能し、多くの場合、ライブデータへの接続を含むことを検証するために使用されます。一方で、ユニットテストは分離されたコードユニットに重点を置いているため、アプリケーションロジックの低レベルのテストが可能ですが、エンドツーエンドテストはさまざまなユーザーストーリーや使用・シナリオに重点を置いており、アプリケーション全体を通したデータフローの総合的な高レベルのテストを提供します。また一方で、ユニットテストではアプリケーションのロジックの問題を明らかにしようとしますが、エンドツーエンドテストでは、個々のユニットが一緒に使用される場合に発生する問題を明らかにしようとします。エンドツーエンドのテストにより、アプリケーションの全体的なアーキテクチャに関する問題が明らかになります。 + +エンドツーエンドテストはユーザーストーリーを実行し、個々のコードモジュールではなくアプリケーション全体を対象とするため、エンドツーエンドテストは、メインアプリケーション自体のコードとは別に、プロジェクト内の独自のアプリケーションとして存在します。ほとんどのエンドツーエンドテストは、アプリケーションとの共通のユーザー対話を自動化し、それらの対話の結果を判別するために DOM を調査します。 + +### テストの構成 + +`@ionic/angular` アプリケーションが作成されると、 デフォルトのエンドツーエンドのテストアプリケーションが `e2e` フォルダに生成されます。このアプリケーションは Protractor を使用してブラウザを制御し、Jasmine を使用してテストを構築し、実行します。アプリケーションは、初期時は次の 4 つのファイルで構成されています: + +- `protractor.conf.js` - Protractor の設定ファイル +- `tsconfig.e2e.json` - テストアプリケーション用の特定の TypeScript の設定 +- `src/app.po.ts` - アプリケーションをナビゲートするメソッド、DOM 内の要素を照会するメソッド、ページ上の要素を操作するメソッドを含むページオブジェクト +- `src/app.e2e-spec.ts` - テスト用のスクリプト + +#### ページオブジェクト + +エンドツーエンドのテストは、アプリケーションとの共通のユーザー対話を自動化し、アプリケーションが応答するのを待ち、対話の結果を判別するために DOM を検査します。これには、多くの DOM 操作と試験が必要です。これらをすべて手作業で行うと、テストは非常に脆くなり、見て理解することや保守が困難になります。 + +ページオブジェクトは、TypeScript クラスの単一ページの HTML をカプセル化し、テスト用のスクリプトがアプリケーションと対話するために使用する API を提供します。DOM 操作ロジックをページオブジェクト内にカプセル化することで、テストが読みやすくなり、かつ判断することがはるかに簡単になり、テストの保守コストが大幅に削減されます。洗練されたページオブジェクトを作成することは、高品質で保守しやすいエンドツーエンドのテストを作成するための鍵です。 + +##### ベースページオブジェクト + +多くのテストは、ページが表示されるのを待ったり、input にテキストを入力したり、ボタンをクリックするなどのアクションに依存しています。これを行うために使用されるメソッドは、適切な DOM 要素の変更を取得するために使用される CSS セレクターのみと一貫性があります。したがって、このロジックを、他のページオブジェクトが使用できるベースクラスに抽象化することは理にかなっています。 + +すべてのページオブジェクトがサポートを必要とするいくつかのベースメソッドを実装する例を次に示します: + +```tsx +import { browser, by, element, ExpectedConditions } from 'protractor'; + +export class PageObjectBase { + private path: string; + protected tag: string; + + constructor(tag: string, path: string) { + this.tag = tag; + this.path = path; + } + + load() { + return browser.get(this.path); + } + + rootElement() { + return element(by.css(this.tag)); + } + + waitUntilInvisible() { + browser.wait(ExpectedConditions.invisibilityOf(this.rootElement()), 3000); + } + + waitUntilPresent() { + browser.wait(ExpectedConditions.presenceOf(this.rootElement()), 3000); + } + + waitUntilNotPresent() { + browser.wait(ExpectedConditions.not(ExpectedConditions.presenceOf(this.rootElement())), 3000); + } + + waitUntilVisible() { + browser.wait(ExpectedConditions.visibilityOf(this.rootElement()), 3000); + } + + getTitle() { + return element(by.css(`${this.tag} ion-title`)).getText(); + } + + protected enterInputText(sel: string, text: string) { + const el = element(by.css(`${this.tag} ${sel}`)); + const inp = el.element(by.css('input')); + inp.sendKeys(text); + } + + protected enterTextareaText(sel: string, text: string) { + const el = element(by.css(`${this.tag} ${sel}`)); + const inp = el.element(by.css('textarea')); + inp.sendKeys(text); + } + + protected clickButton(sel: string) { + const el = element(by.css(`${this.tag} ${sel}`)); + browser.wait(ExpectedConditions.elementToBeClickable(el)); + el.click(); + } +} +``` + +##### ページ毎の要約 + +アプリケーションの各ページには、そのページの要素を抽象化する独自のページオブジェクトクラスがあります。ベースとなるページオブジェクトクラスを使用する場合、ページオブジェクトを作成するには、ほとんどの場合そのページに固有の要素のカスタムメソッドを作成する必要があります。多くの場合、これらのカスタム要素は、必要な作業を実行するためにベースクラスのメソッドの恩恵を受けます。 + +次に、単純ですが典型的なログインページのページオブジェクトの例を示します。`enterEMail()` のような多くのメソッドは、作業の大部分を行うベースクラスのメソッドを呼び出すことに注意してください。 + +```tsx +import { browser, by, element, ExpectedConditions } from 'protractor'; +import { PageObjectBase } from './base.po'; + +export class LoginPage extends PageObjectBase { + constructor() { + super('app-login', '/login'); + } + + waitForError() { + browser.wait(ExpectedConditions.presenceOf(element(by.css('.error'))), 3000); + } + + getErrorMessage() { + return element(by.css('.error')).getText(); + } + + enterEMail(email: string) { + this.enterInputText('#email-input', email); + } + + enterPassword(password: string) { + this.enterInputText('#password-input', password); + } + + clickSignIn() { + this.clickButton('#signin-button'); + } +} +``` + +#### テストスクリプト + +ユニットテストと同様に、エンドツーエンドのテストスクリプトはネストされた `describe()` と `it()` 関数で構成されています。エンドツーエンドのテストの場合、`describe()` 関数は一般に、特定のシナリオを、そのシナリオ内でアクションが実行されるときにアプリケーションによって表されるべき特定の振る舞いを示す `it()` 関数とともに示します。 + +また、ユニットテストと同様に、`describe()` および `it()` 関数で使用されるラベルは、"describe" または "it"と、完全なテストケースを形成するためにともに連結されるとき、両方とも意味をなします。 + +典型的なログインシナリオを実行するエンドツーエンドのテストスクリプトの簡単な例を次に示します。 + +```tsx +import { AppPage } from '../page-objects/pages/app.po'; +import { AboutPage } from '../page-objects/pages/about.po'; +import { CustomersPage } from '../page-objects/pages/customers.po'; +import { LoginPage } from '../page-objects/pages/login.po'; +import { MenuPage } from '../page-objects/pages/menu.po'; +import { TasksPage } from '../page-objects/pages/tasks.po'; + +describe('Login', () => { + const about = new AboutPage(); + const app = new AppPage(); + const customers = new CustomersPage(); + const login = new LoginPage(); + const menu = new MenuPage(); + const tasks = new TasksPage(); + + beforeEach(() => { + app.load(); + }); + + describe('before logged in', () => { + it('displays the login screen', () => { + expect(login.rootElement().isDisplayed()).toEqual(true); + }); + + it('allows in-app navigation to about', () => { + menu.clickAbout(); + about.waitUntilVisible(); + login.waitUntilInvisible(); + }); + + it('does not allow in-app navigation to tasks', () => { + menu.clickTasks(); + app.waitForPageNavigation(); + expect(login.rootElement().isDisplayed()).toEqual(true); + }); + + it('does not allow in-app navigation to customers', () => { + menu.clickCustomers(); + app.waitForPageNavigation(); + expect(login.rootElement().isDisplayed()).toEqual(true); + }); + + it('displays an error message if the login fails', () => { + login.enterEMail('test@test.com'); + login.enterPassword('bogus'); + login.clickSignIn(); + login.waitForError(); + expect(login.getErrorMessage()).toEqual('The password is invalid or the user does not have a password.'); + }); + + it('navigates to the tasks page if the login succeeds', () => { + login.enterEMail('test@test.com'); + login.enterPassword('testtest'); + login.clickSignIn(); + tasks.waitUntilVisible(); + }); + }); + + describe('once logged in', () => { + beforeEach(() => { + tasks.waitUntilVisible(); + }); + + it('allows navigation to the customers page', () => { + menu.clickCustomers(); + customers.waitUntilVisible(); + tasks.waitUntilInvisible(); + }); + + it('allows navigation to the about page', () => { + menu.clickAbout(); + about.waitUntilVisible(); + tasks.waitUntilInvisible(); + }); + + it('allows navigation back to the tasks page', () => { + menu.clickAbout(); + tasks.waitUntilInvisible(); + menu.clickTasks(); + tasks.waitUntilVisible(); + }); + }); +}); +``` + +### 設定 + +デフォルトの設定では、開発に使用される同じ `environment.ts` ファイルを使います。エンドツーエンドのテストで使用するデータをより適切に制御するには、テスト用の特定の環境を用意し、テストにその環境を使用すると便利なことが多いです。このセクションでは、この設定を作成する 1 つの方法を示します。 + +#### テスト環境 + +テスト環境を設定するには、テスト専用のバックエンドを使用する新しい環境ファイルを作成し、その環境を使うために `angular.json` ファイルを更新し、`package.json` 中の `e2e` スクリプトを `test` 環境を指定するように修正します。 + +##### `environment.e2e.ts` ファイルを生成 + +Angular の `environment.ts` と `environment.prod.ts` ファイルは、アプリケーションのバックエンドのデータサービスのベース URL などの情報を格納するために度々使用されます。また、同じ情報を提供する `environment.e2e.ts` を作成してください。これは、開発または本番のバックエンドサービスではなく、テスト専用のバックエンドサービスにのみ接続します。以下に例を示します: + +```tsx +export const environment = { + production: false, + databaseURL: 'https://e2e-test-api.my-great-app.com', + projectId: 'my-great-app-e2e', +}; +``` + +##### `angular.json` ファイルを修正 + +`angular.json` ファイルを使用するには、このファイルを修正する必要があります。これは階層化プロセスです。以下の XPath リストに従って、必要な設定を追加しましょう。 + +`/projects/app/architect/build/configurations` にファイルの置換を行う `test` という名前の設定を追加します: + +```json +"test": { + "fileReplacements": [ + { + "replace": "src/environments/environment.ts", + "with": "src/environments/environment.e2e.ts" + } + ] +} +``` + +`/projects/app/architect/serve/configurations` に、上記で定義した `test` というビルドの設定をブラウザターゲットに指定する `test` という名前の設定を追加します。 + +```json +"test": { + "browserTarget": "app:build:test" +} +``` + +`/projects/app-e2e/architect/e2e/configurations` に、上記で定義した `test` という起動設定で開発サーバーターゲットを指定する `test` という名前の設定を追加します。 + +```json +"test": { + "devServerTarget": "app:serve:test" +} +``` + +##### `package.json` ファイルを修正 + +`npm run e2e` が `test` の設定を使うように `package.json` ファイルを修正します。 + +```json +"scripts": { + "e2e": "ng e2e --configuration=test", + "lint": "ng lint", + "ng": "ng", + "start": "ng serve", + "test": "ng test", + "test:dev": "ng test --browsers=ChromeHeadlessCI", + "test:ci": "ng test --no-watch --browsers=ChromeHeadlessCI" +}, +``` + +#### テストクリーンアップ + +エンドツーエンドテストが何らかの方法でデータを変更する場合は、テストが完了したらデータを既知の状態に一度リセットすると便利です。そのための 1 つの方法は: + +1. クリーンアップを実行するエンドポイントを生成する。 +1. `protractor.conf.js` ファイルによってエクスポートされる `config` オブジェクトに `onCleanUp()` 関数を追加する + +次に例を示します: + +```javascript +onCleanUp() { + const axios = require('axios'); + return axios + .post( + 'https://e2e-test-api.my-great-app.com/purgeDatabase', + {} + ) + .then(res => { + console.log(res.data); + }) + .catch(err => console.log(err)); +} +``` diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/angular/virtual-scroll.md b/i18n/ja/docusaurus-plugin-content-docs/current/angular/virtual-scroll.md new file mode 100644 index 00000000000..3e239956e27 --- /dev/null +++ b/i18n/ja/docusaurus-plugin-content-docs/current/angular/virtual-scroll.md @@ -0,0 +1,133 @@ +# 仮想スクロール + +:::warning Looking for `ion-virtual-scroll`? + +`ion-virtual-scroll` was deprecated in v6.0.0 and removed in v7.0.0. We recommend using the `@angular/cdk` package detailed below. + +::: + +## Installation + +To setup the CDK Scroller, first install `@angular/cdk`: + +```shell +npm add @angular/cdk +``` + +This provides a collection of different utilities, but we'll focus on `ScrollingModule` for now. + +When we want to use the CDK Scroller, we'll need to import the module in our component. For example, in a tabs starter project, we can add our import to the `tabs1.module.ts` file. + +```diff + import { IonicModule } from '@ionic/angular'; + import { NgModule } from '@angular/core'; + import { CommonModule } from '@angular/common'; + import { FormsModule } from '@angular/forms'; + import { Tab1Page } from './tab1.page'; + import { ExploreContainerComponentModule } from '../explore-container/explore-container.module'; ++ import { ScrollingModule } from '@angular/cdk/scrolling'; + import { Tab1PageRoutingModule } from './tab1-routing.module'; + @NgModule({ + imports: [ + IonicModule, + CommonModule, + FormsModule, + ExploreContainerComponentModule, + Tab1PageRoutingModule, ++ ScrollingModule + ], + declarations: [Tab1Page] + }) + export class Tab1PageModule {} +``` + +With this added, we have access to the Virtual Scroller in the Tab1Page component. + +## Usage + +The CDK Virtual Scroller can be added to a component by adding the `cdk-virtual-scroll-viewport` to a component's template. + +```html + + + +``` + +`cdk-virtual-scroll-viewport` becomes the root of our scrollable content and is responsible for recycling DOM nodes as they scroll out of view. + +The DOM nodes at this point can be any content needed for an app. The difference is that when we want to iterate over a collection, `*cdkVirtualFor` is used instead of `*ngFor`. + +```html + + + + + + + + {{item }} + + + + +``` + +Here, `items` is an array, but it can be an array, `Observable`, or `DataSource`. `DataSource` is an abstract class that can provide the data needed as well as utility methods. For more details, check out the [CDK Virtual Scrolling docs](https://material.angular.io/cdk/scrolling/overview). + +The component is not complete yet as the `cdk-virtual-scroll-viewport` needs to know how big each node will be as well as the min/max buffer sizes. + +At the moment, CDK Virtual Scroller only supports fixed sized elements, but dynamic sized elements are planned for the future. For the `Tab1Page` component, since it is only rendering an item, it can be hard-coded to a fixed size. + +The min/max buffer size tells the scroller "render as many nodes as it takes to meet this minimum height, but not over this". + +```html + +``` + +For this case, the `cdk-virtual-scroll-viewport` will render cells at a height 56px until it reaches a height of 900px, but no more at 1350px. These numbers are arbitrary, so be sure to test out what values will work in a real use case. + +Putting everything together, the final HTML should look like: + +```html + + + + + + + + {{item }} + + + + +``` + +The last piece needed is a some CSS to size the viewport correctly. In the `tab1.page.scss` file, add the following + +```scss +cdk-virtual-scroll-viewport { + height: 100%; + width: 100%; +} +``` + +Since the viewport is built to fit various use cases, the default sizing is not set and is up to developers to set. + +## Usage with Ionic Components + +Ionic Framework requires that features such as collapsible large titles, `ion-infinite-scroll`, `ion-refresher`, and `ion-reorder-group` be used within an `ion-content`. To use these experiences with virtual scrolling, you must add the `.ion-content-scroll-host` class to the virtual scroll viewport. + +For example: + +```html + + + + + +``` + +## Further Reading + +This only covers a small portion of what the CDK Virtual Scroller is capable of. For more details, please see the [Angular CDK Virtual Scrolling docs](https://material.angular.io/cdk/scrolling/overview). diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/angular/your-first-app.md b/i18n/ja/docusaurus-plugin-content-docs/current/angular/your-first-app.md new file mode 100644 index 00000000000..ae976bdaaaf --- /dev/null +++ b/i18n/ja/docusaurus-plugin-content-docs/current/angular/your-first-app.md @@ -0,0 +1,182 @@ +--- +title: 'はじめてのIonicアプリ: Angular' +sidebar_label: はじめてのアプリ +--- + + + Build Your First Ionic Mobile App: Angular Development Tutorial + + + +Ionic の素晴らしいところは、1 つのコードベースで、使い慣れた Web ツールと言語を使用して任意のプラットフォーム用にビルドできることです。 Follow along as we learn the fundamentals of Ionic app development by creating a realistic app step by step. + +Here’s the finished app running on all 3 platforms: + + + +:::note +Looking for the previous version of this guide that covered Ionic 4 and Cordova? [See here.](../developer-resources/guides/first-app-v4/intro.md) +::: + +## What We'll Build + +We'll create a Photo Gallery app that offers the ability to take photos with your device's camera, display them in a grid, and store them permanently on the device. + +Highlights include: + +- One Angular-based codebase that runs on the web, iOS, and Android using Ionic Framework [UI components](https://ionicframework.com/docs/components). +- Deployed as a native iOS and Android mobile app using [Capacitor](https://capacitorjs.com), Ionic's official native app runtime. +- Photo Gallery functionality powered by the Capacitor [Camera](https://capacitorjs.com/docs/apis/camera), [Filesystem](https://capacitorjs.com/docs/apis/filesystem), and [Preferences](https://capacitorjs.com/docs/apis/preferences) APIs. + +Find the complete app code referenced in this guide [on GitHub](https://github.com/ionic-team/photo-gallery-capacitor-ng). + +## Download Required Tools + +Download and install these right away to ensure an optimal Ionic development experience: + +- **Node.js** for interacting with the Ionic ecosystem. [Download the LTS version here](https://nodejs.org/en/). +- **A code editor** for... writing code! We are fans of [Visual Studio Code](https://code.visualstudio.com/). +- **Command-line interface/terminal (CLI)**: + - **Windows** users: for the best Ionic experience, we recommend the built-in command line (cmd) or the Powershell + CLI, running in Administrator mode. + - **Mac/Linux** users, virtually any terminal will work. + +## Install Ionic Tooling + +Run the following in the command line terminal to install the Ionic CLI (`ionic`), `native-run`, used to run native binaries on devices and simulators/emulators, and `cordova-res`, used to generate native app icons and splash screens: + +:::note +To open a terminal in Visual Studio Code, go to Terminal -> New Terminal. +::: + +```shell +npm install -g @ionic/cli native-run cordova-res +``` + +:::note +The `-g` option means _install globally_. When packages are installed globally, `EACCES` permission errors can occur. + +Consider setting up npm to operate globally without elevated permissions. See [Resolving Permission Errors](../developing/tips.md#resolving-permission-errors) for more information. +::: + +## アプリの作成 + +次に、"Tabs" というアプリテンプレートを使用して Ionic Angular アプリを生成し、Native 機能を使うために Capacitor を追加します。 + +```shell +ionic start photo-gallery tabs --type=angular --capacitor +``` + +:::note + +`NgModules` と `Standalone` のどちらかを選択するプロンプトが表示されたら、このチュートリアルは `NgModules` のアプローチに従っているので、`NgModules` を選択する。 + +::: + +このスタータープロジェクトには、Ionic 開発のために事前に構成された 3 つのページとベストプラクティスが用意されています。共通の構成要素がすでに配置されているため、機能を簡単に追加できます! + +次に、アプリのフォルダに移動します: + +```shell +cd photo-gallery +``` + +Next we'll need to install the necessary Capacitor plugins to make the app's native functionality work: + +```shell +npm install @capacitor/camera @capacitor/preferences @capacitor/filesystem +``` + +### PWA Elements + +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). + +It's a separate dependency, so install it next: + +```shell +npm install @ionic/pwa-elements +``` + +Next, import `@ionic/pwa-elements` by editing `src/main.ts`. + +```tsx +import { defineCustomElements } from '@ionic/pwa-elements/loader'; + +// Call the element loader before the bootstrapModule/bootstrapApplication call +defineCustomElements(window); +``` + +That’s it! Now for the fun part - let’s see the app in action. + +## アプリを起動 + +次のコマンドを実行してください: + +```shell +ionic serve +``` + +And voilà! Your Ionic app is now running in a web browser. Most of your app can be built and tested right in the browser, greatly increasing development and testing speed. + +## Photo Gallery!!! + +There are three tabs. Click on the Tab2 tab. It’s a blank canvas, aka the perfect spot to transform into a Photo Gallery. The Ionic CLI features Live Reload, so when you make changes and save them, the app is updated immediately! + +![Before and after going through this tutorial](/img/guides/first-app-cap-ng/email-photogallery.gif) + +Open the photo-gallery app folder in your code editor of choice, then navigate to `/src/app/tab2/tab2.page.html`. We see: + +```html + + + Tab 2 + + + + + + + Tab 2 + + + +``` + +`ion-header` represents the top navigation and toolbar, with "Tab 2" as the title (there are two of them due to iOS [Collapsible Large Title](https://ionicframework.com/docs/api/title#collapsible-large-titles) support). Rename both `ion-title` elements to: + +```html +Photo Gallery +``` + +We put the visual aspects of our app into ``. In this case, it’s where we’ll add a button that opens the device’s camera as well as displays the image captured by the camera. Start by adding a [floating action button](https://ionicframework.com/docs/api/fab) (FAB) to the bottom of the page and set the camera image as the icon. + +```html + + + + + + + +``` + +Next, open `src/app/tabs/tabs.page.html`. Change the label to “Photos” and the icon name to “images”: + +```html + + + Photos + +``` + +Save all changes to see them automatically applied in the browser. That’s just the start of all the cool things we can do with Ionic. Up next, implement camera taking functionality on the web, then build it for iOS and Android. diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/angular/your-first-app/2-taking-photos.md b/i18n/ja/docusaurus-plugin-content-docs/current/angular/your-first-app/2-taking-photos.md new file mode 100644 index 00000000000..0d839b8e2f5 --- /dev/null +++ b/i18n/ja/docusaurus-plugin-content-docs/current/angular/your-first-app/2-taking-photos.md @@ -0,0 +1,134 @@ +--- +title: Taking Photos with the Camera +sidebar_label: カメラ撮影 +--- + + + Build Camera API for iOS, Android & Web | Ionic Capacitor Camera + + + +Now for the fun part - adding the ability to take photos with the device’s camera using the Capacitor [Camera API](https://capacitorjs.com/docs/apis/camera). We’ll begin with building it for the web, then make some small tweaks to make it work on mobile (iOS and Android). + +## Photo Service + +All Capacitor logic (Camera usage and other native features) will be encapsulated in a service class. Create `PhotoService` using the `ionic generate` command: + +```shell +ionic g service services/photo +``` + +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: + +```tsx +import { Camera, CameraResultType, CameraSource, Photo } from '@capacitor/camera'; +import { Filesystem, Directory } from '@capacitor/filesystem'; +import { Preferences } from '@capacitor/preferences'; +``` + +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: + +```tsx +public async addNewToGallery() { + // Take a photo + const capturedPhoto = await Camera.getPhoto({ + resultType: CameraResultType.Uri, + source: CameraSource.Camera, + quality: 100 + }); +} +``` + +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. + +Next, open up `tab2.page.ts` and import the PhotoService class and add a method that calls the `addNewToGallery` method on the imported service: + +```tsx +import { PhotoService } from '../services/photo.service'; + +constructor(public photoService: PhotoService) { } + +addPhotoToGallery() { + this.photoService.addNewToGallery(); +} +``` + +Then, open `tab2.page.html` and call the `addPhotoToGallery()` function when the FAB is tapped/clicked: + +```html + + + + + + + +``` + +Save the file, and if it's not running already, restart the development server in your browser by running `ionic serve`. On the Photo Gallery tab, click the Camera button. If your computer has a webcam of any sort, a modal window appears. Take a selfie! + +![Camera API on the web](/img/guides/first-app-cap-ng/camera-web.png) + +_(Your selfie is probably much better than mine)_ + +After taking a photo, it disappears right away. We need to display it within our app and save it for future access. + +## Displaying Photos + +Outside of the `PhotoService` class definition (the very bottom of the file), create a new interface, `UserPhoto`, to hold our photo metadata: + +```tsx +export interface UserPhoto { + filepath: string; + webviewPath?: string; +} +``` + +Back at the top of the file, define an array of Photos, which will contain a reference to each photo captured with the Camera. + +```tsx +export class PhotoService { + public photos: UserPhoto[] = []; + + // other code +} +``` + +Over in the `addNewToGallery` function, add the newly captured photo to the beginning of the Photos array. + +```tsx + const capturedPhoto = await Camera.getPhoto({ + resultType: CameraResultType.Uri, + source: CameraSource.Camera, + quality: 100 + }); + + this.photos.unshift({ + filepath: "soon...", + webviewPath: capturedPhoto.webPath! + }); +} +``` + +Next, move over to `tab2.page.html` so we can display the image on the screen. Add a [Grid component](https://ionicframework.com/docs/api/grid) so that each photo will display nicely as photos are added to the gallery, and loop through each photo in the `PhotoServices`'s Photos array, adding an Image component (``) for each. Point the `src` (source) at the photo’s path: + +```html + + + + + + + + + + + +``` + +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! + +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. diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/angular/your-first-app/3-saving-photos.md b/i18n/ja/docusaurus-plugin-content-docs/current/angular/your-first-app/3-saving-photos.md new file mode 100644 index 00000000000..cf9b948c221 --- /dev/null +++ b/i18n/ja/docusaurus-plugin-content-docs/current/angular/your-first-app/3-saving-photos.md @@ -0,0 +1,81 @@ +--- +sidebar_label: 写真の保存 +--- + +# Saving Photos to the Filesystem + +We’re now able to take multiple photos and display them in a photo gallery on the second tab of our app. These photos, however, are not currently being stored permanently, so when the app is closed, they will be deleted. + +## Filesystem API + +Fortunately, saving them to the filesystem only takes a few steps. Begin by creating a new class method, `savePicture()`, in the `PhotoService` class (`src/app/services/photo.service.ts`). We pass in the `photo` object, which represents the newly captured device photo: + +```tsx +private async savePicture(photo: Photo) { } +``` + +We can use this new method immediately in `addNewToGallery()`: + +```tsx +public async addNewToGallery() { + // Take a photo + const capturedPhoto = await Camera.getPhoto({ + resultType: CameraResultType.Uri, // file-based data; provides best performance + source: CameraSource.Camera, // automatically take a new photo with the camera + quality: 100 // highest quality (0 to 100) + }); + + // Save the picture and add it to photo collection + const savedImageFile = await this.savePicture(capturedPhoto); + this.photos.unshift(savedImageFile); +} +``` + +We’ll use the Capacitor [Filesystem API](https://capacitorjs.com/docs/apis/filesystem) to save the photo to the filesystem. To start, convert the photo to base64 format, then feed the data to the Filesystem’s `writeFile` function. As you’ll recall, we display each photo on the screen by setting each image’s source path (`src` attribute) in `tab2.page.html` to the webviewPath property. So, set it then return the new Photo object. + +```tsx +private async savePicture(photo: Photo) { + // Convert photo to base64 format, required by Filesystem API to save + const base64Data = await this.readAsBase64(photo); + + // Write the file to the data directory + const fileName = Date.now() + '.jpeg'; + const savedFile = await Filesystem.writeFile({ + path: fileName, + data: base64Data, + directory: Directory.Data + }); + + // Use webPath to display the new image instead of base64 since it's + // already loaded into memory + return { + filepath: fileName, + webviewPath: photo.webPath + }; +} +``` + +`readAsBase64()` is a helper function we’ll define next. It's useful to organize via a separate method since it requires a small amount of platform-specific (web vs. mobile) logic - more on that in a bit. For now, implement the logic for running on the web: + +```tsx +private async readAsBase64(photo: Photo) { + // Fetch the photo, read as a blob, then convert to base64 format + const response = await fetch(photo.webPath!); + const blob = await response.blob(); + + return await this.convertBlobToBase64(blob) as string; +} + +private convertBlobToBase64 = (blob: Blob) => new Promise((resolve, reject) => { + const reader = new FileReader(); + reader.onerror = reject; + reader.onload = () => { + resolve(reader.result); + }; + reader.readAsDataURL(blob); +}); +``` + +Obtaining the camera photo as base64 format on the web appears to be a bit trickier than on mobile. In reality, we’re just using built-in web APIs: [fetch()](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) as a neat way to read the file into blob format, then FileReader’s [readAsDataURL()](https://developer.mozilla.org/en-US/docs/Web/API/FileReader/readAsDataURL) to convert the photo blob to base64. + +There we go! Each time a new photo is taken, it’s now automatically saved to the filesystem. diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/angular/your-first-app/4-loading-photos.md b/i18n/ja/docusaurus-plugin-content-docs/current/angular/your-first-app/4-loading-photos.md new file mode 100644 index 00000000000..f2fc61b1fd1 --- /dev/null +++ b/i18n/ja/docusaurus-plugin-content-docs/current/angular/your-first-app/4-loading-photos.md @@ -0,0 +1,69 @@ +--- +sidebar_label: 写真の読み込み +--- + +# Loading Photos from the Filesystem + +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. + +Fortunately, this is easy: we’ll leverage the Capacitor [Preferences API](https://capacitorjs.com/docs/apis/preferences) to store our array of Photos in a key-value store. + +## Preferences API + +Begin by defining a constant variable that will act as the key for the store: + +```tsx +export class PhotoService { + public photos: UserPhoto[] = []; + private PHOTO_STORAGE: string = 'photos'; + + // other code +} +``` + +Next, at the end of the `addNewToGallery` function, add a call to `Preferences.set()` to save the Photos array. By adding it here, the Photos array is stored each time a new photo is taken. This way, it doesn’t matter when the app user closes or switches to a different app - all photo data is saved. + +```tsx +Preferences.set({ + key: this.PHOTO_STORAGE, + value: JSON.stringify(this.photos), +}); +``` + +With the photo array data saved, create a function called `loadSaved()` that can retrieve that data. We use the same key to retrieve the photos array in JSON format, then parse it into an array: + +```tsx +public async loadSaved() { + // Retrieve cached photo array data + const { value } = await Preferences.get({ key: this.PHOTO_STORAGE }); + this.photos = (value ? JSON.parse(value) : []) as UserPhoto[]; + + // more to come... +} +``` + +On mobile (coming up next!), we can directly set the source of an image tag - `` - to each photo file on the Filesystem, displaying them automatically. On the web, however, we must read each image from the Filesystem into base64 format, using a new `base64` property on the `Photo` object. This is because the Filesystem API uses [IndexedDB](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API) under the hood. Below is the code you need to add in the `loadSaved()` function you just added: + +```tsx +// Display the photo by reading into base64 format +for (let photo of this.photos) { + // Read each saved photo's data from the Filesystem + const readFile = await Filesystem.readFile({ + path: photo.filepath, + directory: Directory.Data, + }); + + // Web platform only: Load the photo as base64 data + photo.webviewPath = `data:image/jpeg;base64,${readFile.data}`; +} +``` + +After, call this new method in `tab2.page.ts` so that when the user first navigates to Tab 2 (the Photo Gallery), all photos are loaded and displayed on the screen. + +```tsx +async ngOnInit() { + await this.photoService.loadSaved(); +} +``` + +That’s it! We’ve built a complete Photo Gallery feature in our Ionic app that works on the web. Next up, we’ll transform it into a mobile app for iOS and Android! diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/angular/your-first-app/5-adding-mobile.md b/i18n/ja/docusaurus-plugin-content-docs/current/angular/your-first-app/5-adding-mobile.md new file mode 100644 index 00000000000..16235a008a4 --- /dev/null +++ b/i18n/ja/docusaurus-plugin-content-docs/current/angular/your-first-app/5-adding-mobile.md @@ -0,0 +1,117 @@ +--- +strip_number_prefixes: false +--- + +# モバイルデバイス機能の追加 + +Our photo gallery app won’t be complete until it runs on iOS, Android, and the web - all using one codebase. All it takes is some small logic changes to support mobile platforms, installing some native tooling, then running the app on a device. Let’s go! + +## Import Platform API + +Let’s start with making some small code changes - then our app will “just work” when we deploy it to a device. + +Import the Ionic [Platform API](https://ionicframework.com/docs/angular/platform) into `photo.service.ts`, which is used to retrieve information about the current device. In this case, it’s useful for selecting which code to execute based on the platform the app is running on (web or mobile): + +```tsx +import { Platform } from '@ionic/angular'; + +export class PhotoService { + public photos: UserPhoto[] = []; + private PHOTO_STORAGE: string = 'photos'; + private platform: Platform; + + constructor(platform: Platform) { + this.platform = platform; + } + + // other code +} +``` + +## Platform-specific Logic + +First, we’ll update the photo saving functionality to support mobile. In the `readAsBase64()` function, check which platform the app is running on. If it’s “hybrid” (Capacitor or Cordova, two native runtimes), then read the photo file into base64 format using the Filesystem `readFile()` method. Otherwise, use the same logic as before when running the app on the web: + +```tsx +private async readAsBase64(photo: Photo) { + // "hybrid" will detect Cordova or Capacitor + if (this.platform.is('hybrid')) { + // Read the file into base64 format + const file = await Filesystem.readFile({ + path: photo.path! + }); + + return file.data; + } + else { + // Fetch the photo, read as a blob, then convert to base64 format + const response = await fetch(photo.webPath!); + const blob = await response.blob(); + + return await this.convertBlobToBase64(blob) as string; + } +} +``` + +Next, update the `savePicture()` method. When running on mobile, set `filepath` to the result of the `writeFile()` operation - `savedFile.uri`. When setting the `webviewPath`, use the special `Capacitor.convertFileSrc()` method ([details here](https://ionicframework.com/docs/core-concepts/webview#file-protocol)). + +```tsx +// Save picture to file on device +private async savePicture(photo: Photo) { + // Convert photo to base64 format, required by Filesystem API to save + const base64Data = await this.readAsBase64(photo); + + // Write the file to the data directory + const fileName = Date.now() + '.jpeg'; + const savedFile = await Filesystem.writeFile({ + path: fileName, + data: base64Data, + directory: Directory.Data + }); + + if (this.platform.is('hybrid')) { + // Display the new image by rewriting the 'file://' path to HTTP + // Details: https://ionicframework.com/docs/building/webview#file-protocol + return { + filepath: savedFile.uri, + webviewPath: Capacitor.convertFileSrc(savedFile.uri), + }; + } + else { + // Use webPath to display the new image instead of base64 since it's + // already loaded into memory + return { + filepath: fileName, + webviewPath: photo.webPath + }; + } +} +``` + +Next, head back over to the `loadSaved()` function we implemented for the web earlier. On mobile, we can directly set the source of an image tag - `` - to each photo file on the Filesystem, displaying them automatically. Thus, only the web requires reading each image from the Filesystem into base64 format. Update this function to add an _if statement_ around the Filesystem code: + +```tsx +public async loadSaved() { + // Retrieve cached photo array data + const { value } = await Preferences.get({ key: this.PHOTO_STORAGE }); + this.photos = (value ? JSON.parse(value) : []) as UserPhoto[]; + + // Easiest way to detect when running on the web: + // “when the platform is NOT hybrid, do this” + if (!this.platform.is('hybrid')) { + // Display the photo by reading into base64 format + for (let photo of this.photos) { + // Read each saved photo's data from the Filesystem + const readFile = await Filesystem.readFile({ + path: photo.filepath, + directory: Directory.Data + }); + + // Web platform only: Load the photo as base64 data + photo.webviewPath = `data:image/jpeg;base64,${readFile.data}`; + } + } +} +``` + +Our Photo Gallery now consists of one codebase that runs on the web, Android, and iOS. Next up, the part you’ve been waiting for - deploying the app to a device. diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/angular/your-first-app/6-deploying-mobile.md b/i18n/ja/docusaurus-plugin-content-docs/current/angular/your-first-app/6-deploying-mobile.md new file mode 100644 index 00000000000..82e392c2e64 --- /dev/null +++ b/i18n/ja/docusaurus-plugin-content-docs/current/angular/your-first-app/6-deploying-mobile.md @@ -0,0 +1,114 @@ +--- +title: Deploying to iOS and Android +sidebar_label: モバイルへのデプロイ +--- + + + Deploying to iOS and Android Apps - Capacitor Setup on Ionic + + + +Since we added Capacitor to our project when it was first created, there’s only a handful of steps remaining until the Photo Gallery app is on our device! Remember, you can find the complete source code for this app [here](https://github.com/ionic-team/photo-gallery-capacitor-ng). + +## Capacitor Setup + +Capacitor is Ionic’s official app runtime that makes it easy to deploy web apps to native platforms like iOS, Android, and more. If you’ve used Cordova in the past, consider reading more about the differences [here](https://capacitorjs.com/docs/cordova#differences-between-capacitor-and-cordova). + +If you’re still running `ionic serve` in the terminal, cancel it. Complete a fresh build of your Ionic project, fixing any errors that it reports: + +```shell +ionic build +``` + +Next, create both the iOS and Android projects: + +```shell +$ ionic cap add ios +$ ionic cap add android +``` + +Both android and ios folders at the root of the project are created. These are entirely standalone native projects that should be considered part of your Ionic app (i.e., check them into source control, edit them using their native tooling, etc.). + +Every time you perform a build (e.g. `ionic build`) that updates your web directory (default: `www`), you'll need to copy those changes into your native projects: + +```shell +ionic cap copy +``` + +Note: After making updates to the native portion of the code (such as adding a new plugin), use the `sync` command: + +```shell +ionic cap sync +``` + +## iOS Deployment + +:::note +To build an iOS app, you’ll need a Mac computer. +::: + +Capacitor iOS apps are configured and managed through Xcode (Apple’s iOS/Mac IDE), with dependencies managed by [CocoaPods](https://cocoapods.org/). Before running this app on an iOS device, there's a couple of steps to complete. + +First, run the Capacitor `open` command, which opens the native iOS project in Xcode: + +```shell +ionic cap open ios +``` + +In order for some native plugins to work, user permissions must be configured. In our photo gallery app, this includes the Camera plugin: iOS displays a modal dialog automatically after the first time that `Camera.getPhoto()` is called, prompting the user to allow the app to use the Camera. The permission that drives this is labeled “Privacy - Camera Usage.” To set it, the `Info.plist` file must be modified ([more details here](https://capacitorjs.com/docs/ios/configuration)). To access it, click "Info," then expand "Custom iOS Target Properties." + +![Xcode Custom iOS Target Properties](/img/guides/first-app-cap-ng/xcode-info-plist.png) + +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." + +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. + +Follow the same process to add the other two Keys required of the Camera plugin: `NSPhotoLibraryAddUsageDescription` and `NSPhotoLibraryUsageDescription`. + +Next, click on `App` in the Project Navigator on the left-hand side, then within the `Signing & Capabilities` section, select your Development Team. + +![Xcode - Selecting Development Team](/img/guides/first-app-cap-ng/xcode-signing.png) + +With permissions in place and Development Team selected, we are ready to try out the app on a real device! Connect an iOS device to your Mac computer, select it (`App -> Matthew’s iPhone` for me) then click the "Build" button to build, install, and launch the app on your device: + +![Xcode build button](/img/guides/first-app-cap-ng/xcode-build-button.png) + +Upon tapping the Camera button on the Photo Gallery tab, the permission prompt will display. Tap OK, then take a picture with the Camera. Afterward, the photo shows in the app! + +![iOS Camera permissions](/img/guides/first-app-cap-ng/ios-permissions-photo.png) + +## Android Deployment + +Capacitor Android apps are configured and managed through Android Studio. Before running this app on an Android device, there's a couple of steps to complete. + +First, run the Capacitor `open` command, which opens the native Android project in Android Studio: + +```shell +ionic cap open android +``` + +Similar to iOS, we must enable the correct permissions to use the Camera. Configure these in the `AndroidManifest.xml` file. Android Studio will likely open this file automatically, but in case it doesn't, locate it under `android/app/src/main/`. + +![Android Manifest location](/img/guides/first-app-cap-ng/android-manifest.png) + +Scroll to the `Permissions` section and ensure these entries are included: + +```xml + + +``` + +Save the file. With permissions in place, we are ready to try out the app on a real device! Connect an Android device to your computer. Within Android Studio, click the "Run" button, select the attached Android device, then click OK to build, install, and launch the app on your device. + +![Launching app on Android](/img/guides/first-app-cap-ng/android-device.png) + +Once again, upon tapping the Camera button on the Photo Gallery tab, the permission prompt should be displayed. Tap OK, then take a picture with the Camera. Afterward, the photo should appear in the app. + +![Android Camera permissions](/img/guides/first-app-cap-ng/android-permissions-photo.png) + +Our Photo Gallery app has just been deployed to Android and iOS devices. 🎉 + +In the next portion of this tutorial, we’ll use the Ionic CLI’s Live Reload functionality to quickly implement photo deletion - thus completing our Photo Gallery feature. diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/angular/your-first-app/7-live-reload.md b/i18n/ja/docusaurus-plugin-content-docs/current/angular/your-first-app/7-live-reload.md new file mode 100644 index 00000000000..484feddcc0f --- /dev/null +++ b/i18n/ja/docusaurus-plugin-content-docs/current/angular/your-first-app/7-live-reload.md @@ -0,0 +1,114 @@ +--- +title: アプリ開発を高速化するためのライブリロード +sidebar_label: ライブリロード +--- + + + + + +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? + +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. + +## Live Reload + +Remember `ionic serve`? That was Live Reload working in the browser, allowing us to iterate quickly. + +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. + +Let’s use Live Reload to implement photo deletion, the missing piece of our Photo Gallery feature. Select your platform of choice (iOS or Android) and connect a device to your computer. Next, run either command in a terminal, based on your chosen platform: + +```shell +$ ionic cap run ios -l --external + +$ ionic cap run android -l --external +``` + +The Live Reload server will start up, and the native IDE of choice will open if not opened already. Within the IDE, click the Play button to launch the app onto your device. + +## Deleting Photos + +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 `` 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. + +```html + + + +``` + +Over in `tab2.page.ts`, import Action Sheet and add it to the constructor: + +```tsx +import { ActionSheetController } from '@ionic/angular'; + +constructor(public photoService: PhotoService, + public actionSheetController: ActionSheetController) {} +``` + +Add `UserPhoto` to the import statement. + +```tsx +import { PhotoService, UserPhoto } from '../services/photo.service'; +``` + +Next, implement the `showActionSheet()` function. We add two options: `Delete` that calls PhotoService’s `deletePicture()` function (to be added next) and `Cancel`, which when given the role of “cancel” will automatically close the action sheet: + +```tsx +public async showActionSheet(photo: UserPhoto, position: number) { + const actionSheet = await this.actionSheetController.create({ + header: 'Photos', + buttons: [{ + text: 'Delete', + role: 'destructive', + icon: 'trash', + handler: () => { + this.photoService.deletePicture(photo, position); + } + }, { + text: 'Cancel', + icon: 'close', + role: 'cancel', + handler: () => { + // Nothing to do, action sheet is automatically closed + } + }] + }); + await actionSheet.present(); +} +``` + +Save both of the files we just edited. The Photo Gallery app will reload automatically, and now when we tap on one of the photos in the gallery, the action sheet displays. Tapping “Delete” doesn’t do anything yet, so head back into your code editor. + +In `src/app/services/photo.service.ts`, add the `deletePicture()` function: + +```tsx +public async deletePicture(photo: UserPhoto, position: number) { + // Remove this photo from the Photos reference data array + this.photos.splice(position, 1); + + // Update photos array cache by overwriting the existing photo array + Preferences.set({ + key: this.PHOTO_STORAGE, + value: JSON.stringify(this.photos) + }); + + // delete photo file from filesystem + const filename = photo.filepath + .substr(photo.filepath.lastIndexOf('/') + 1); + + await Filesystem.deleteFile({ + path: filename, + directory: Directory.Data + }); +} +``` + +The selected photo is removed from the Photos array first. Then, we use the Capacitor Preferences API to update the cached version of the Photos array. Finally, we delete the actual photo file itself using the Filesystem API. + +Save this file, then tap on a photo again and choose the “Delete” option. This time, the photo is deleted! Implemented much faster using Live Reload. 💪 + +In the final portion of this tutorial, we’ll walk you through the basics of the Appflow product used to build and deploy your application to users' devices. diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/angular/your-first-app/8-distribute.md b/i18n/ja/docusaurus-plugin-content-docs/current/angular/your-first-app/8-distribute.md new file mode 100644 index 00000000000..545e57c1945 --- /dev/null +++ b/i18n/ja/docusaurus-plugin-content-docs/current/angular/your-first-app/8-distribute.md @@ -0,0 +1,100 @@ +--- +sidebar_label: Distribute +--- + +# Build and Deploy your App + +Now that you have built your first app, you are going to want to get it distributed so everyone can start using it. The mechanics of building and deploying your application can be quite cumbersome. That is where [Appflow](https://ionic.io/docs/appflow/) comes into play. Appflow allows you to effectively generate web and native builds, push out live app updates, publish your app to the app stores, and automate the whole process. The entire Quickstart guide can be found [here](https://ionic.io/docs/appflow/quickstart). + +Below we will run through an overview of the steps. + +## Connect Your Repo + +Appflow works directly with Git version control and uses your existing code base as the source of truth for Deploy and Package builds. You will first need to integrate with your hosting service, such as GitHub or Bitbucket, or you can push your code directly to Appflow. Once this is completed, Appflow will have access to your code. + +For more on connecting your code repository to Appflow, checkout the [Connect your Repo](https://ionic.io/docs/appflow/quickstart/connect) section inside the Appflow docs. + +## Install the Appflow SDK + +The Appflow SDK (also known as Ionic Deploy plugin) will allow you to take advantage of arguably two of the best Appflow features: deploying live updates to your app and bypassing the app stores. Ionic Appflow's Live Update feature is shipped with Appflow SDK and features the capabilities of detecting and syncing the updates for your app that you have pushed to your identified channels within the dashboard. + +To get the Appflow SDK plugin added to your project, you can follow the install instructions within the Appflow Dashboard by clicking on "Install Instructions" inside of the `Deploy > Destinations` section. Alternatively, you can install the plugin manually by executing the following command in your app's root directory: + +```shell +ionic deploy add \ + --app-id="YOUR_APP_ID" \ + --channel-name="YOUR_CHANNEL_NAME" \ + --update-method="background|auto|none" \ +``` + +For prerequisite and additional instructions on installing the Appflow SDK, visit the [Install the Appflow SDK](https://ionic.io/docs/appflow/quickstart/installation) section inside the Appflow docs. + +## Push a Commit + +In order for Appflow to access the latest and greatest changes to your code, you will need to push a commit via the version control integration of your choosing. For those that use GitHub or Bitbucket, this would look as follows: + +```shell +git add . # stage any changes +git commit -m "added appflow sdk" # commit staged changes +git push origin main # push the changes from the main branch to your git host +``` + +After the push is made, you will then see your commit under the `Commits` tab of the Appflow Dashboard. For more on this, take a look at the [Push a Commit](https://ionic.io/docs/appflow/quickstart/push) section inside the Appflow docs. + +## Deploy a Live Update + +With the Appflow SDK installed and your commit pushed up to the Dashboard, you are ready to deploy a live update to a device. The Live Update feature uses the installed Appflow SDK with your native application to listen to a particular Deploy Channel Destination. When a live update is assigned to a Channel Destination, that update will be deployed to user devices running binaries that are configured to listen to that specific Channel Destination. + +To get the live update deployed, a Web build will need to be created. This can be done through the `Start build` icon from the `Commits` tab or by clicking the `New build` button in the top right corner of the `Build > Builds` tab. After selecting the correct commit to deploy, select the `Web` target platform and the `Latest` build stack. Depending on your Appflow plan, you will then be able to include custom environments, if any are configured. Finally, you can enable `Live Update` and pick the Channel to automatically assign the build to once it successfully completes. + +Upon completion of the Web Build, additional versioning options are available to you. After completing this section and you have a successful Deploy build, you can then assign it to the same Channel you configured the Appflow SDK to listen to when you installed it by clicking the `Deploy live updates` button in the build detail page. The same can be done by clicking the `Deploy live updates` icon on the build in the `Build > Builds` tab and select the Channel from the dropdown. + +To receive this live update, you will need to run the app on a device or an emulator. The quickest and easiest way to do this is through the following command: + +```shell +ionic [cordova | cap] run [ios | android] [options] +``` + +Assuming the app is configured correctly to listen to the channel you deployed too, the app should immediately update on startup if you have chosen the auto update method during setup. If the background update method was chosen, be sure to stay in the app for about 30 seconds to ensure the update was downloaded. Then, close the application, reopen it, and you will see the updates applied! + +To dive into more details on the steps to deploy a live update, as well as additional information such as disabling deploy for development, check out the [Deploy a Live Update](https://ionic.io/docs/appflow/quickstart/deploy) section inside the Appflow docs. + +## Build a Native Binary + +Next up is a native binary for your app build and deploy process. This is done via the [Ionic Package](https://ionic.io/docs/appflow/package/intro) service. First things first, you will need to create a [Package build](https://ionic.io/docs/appflow/package/builds). This can be done by clicking the `Start build` icon from the `Commits` tab or by clicking the `New build` button in the top right from the `Build > Builds` tab. Then you will select the proper commit for your build and fill in all of the several required fields and any optional fields that you want to specify. After filling in all of the information and the build begins, you can check out it's progress and review the logs if you encounter any errors. + +Given a successful Package build, an iOS binary (`.ipa` or IPA) or/and an Android binary (`.apk` or APK) file becomes available to you. The file can subsequently be downloaded so you can install it on a device by clicking the file name in the `Artifacts` section in the right of the build detail page or clicking the `Download IPA/APK` icon on the build in the `Build > Builds` tab. + +Further information regarding building native binaries can be found inside of the [Build a Native Binary](https://ionic.io/docs/appflow/quickstart/package) section inside the Appflow docs. + +## Create an Automation + +[Automations](https://ionic.io/docs/appflow/automation/intro) enable you and your team to utilize the full CI/CD powers of Appflow. You can create automations that trigger [Package builds](https://ionic.io/docs/appflow/package/builds) and [Deploy builds](https://ionic.io/docs/appflow/deploy/builds) every time your team commits new code to a given branch. The automations can also be configured to use different environments and native configurations for building different versions of your app for development, staging, QA and production. + +For more information, visit the [Create an Automation](https://ionic.io/docs/appflow/quickstart/automation) section within the Appflow docs. There you will see details on creating a single automation. However, you can create multiple automations for different branches or workflows and customize them to fit your needs. An important note is that the ability to create an automation is available for those on our [Basic plans](https://ionic.io/pricing) and above. + +## Create an Environment + +[Package builds](https://ionic.io/docs/appflow/package/builds) and [Deploy builds](https://ionic.io/docs/appflow/deploy/builds) can be further customized via [Environments](https://ionic.io/docs/appflow/automation/environments). This powerful feature allows you to create different configurations based on the environment variables passed in at build time. When combined with the [Automation](https://ionic.io/docs/appflow/automation/intro) feature, development teams can easily configure development, staging, and production build configurations, allowing them to embrace DevOps best practices and ship better quality updates faster than ever. + +Creating an Environment is available for those on our [Basic plans](https://ionic.io/pricing) and above. More information on this can be found in the [Create an Environment](https://ionic.io/docs/appflow/quickstart/environment) section within the Appflow docs. + +## Create a Native Configuration + +[Native Configurations](https://ionic.io/docs/appflow/package/native-configs) allow you to easily modify common configuration values that can change between different environments (development, production, staging, etc.) so you do not need to use extra logic or manually commit them to version control. Native configurations can be attached to any [Package build](https://ionic.io/docs/appflow/package/intro) or [Automation](https://ionic.io/docs/appflow/automation/intro). + +Native configs can be used to: + +- Overwrite the unique bundle identifier or [id attribute](https://cordova.apache.org/docs/en/latest/config_ref/#widget) in `config.xml` +- Overwrite the App Name as it will appear on the home screen of a device +- Overwrite the [Appflow SDK (Deploy Plugin) variables and preferences](https://ionic.io/docs/appflow/deploy/api#plugin-variables) + +For access to the ability to create a Native Configuration, you will need to be on our [Basic plans](https://ionic.io/pricing) and above. Additional details of this feature can be found in the [Create a Native Configuration](https://ionic.io/docs/appflow/quickstart/native-config) section within the Appflow docs. + +## What’s Next? + +Congratulations! You developed a complete cross-platform Photo Gallery app that runs on the web, iOS, and Android. Not only that, you have also then built the app and deployed it to your users devices! + +There are many paths to follow from here. Try adding another [Ionic UI component](https://ionicframework.com/docs/components) to the app, or more [native functionality](https://capacitorjs.com/docs/apis). The sky’s the limit. Once you have added another feature, run the the build and deploy process again through Appflow to get it out to your users. + +Happy app building! 💙 diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/api.md b/i18n/ja/docusaurus-plugin-content-docs/current/api.md new file mode 100644 index 00000000000..01b482ea210 --- /dev/null +++ b/i18n/ja/docusaurus-plugin-content-docs/current/api.md @@ -0,0 +1,17 @@ +--- +title: APIインデックス +--- + +import APIList from '@components/page/api/APIList'; + + + API Index | API カスタム要素の Ionic Docs API Index + + + +各 Ionic の [コンポーネント](/docs/components) は、1 つ以上の [カスタム要素](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements) から構成されます。各カスタム要素は順番に、プロパティ、メソッド、イベント、および CSS カスタムプロパティを公開できます。 + + diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/api/accordion-group.md b/i18n/ja/docusaurus-plugin-content-docs/current/api/accordion-group.md new file mode 100644 index 00000000000..65c2348de79 --- /dev/null +++ b/i18n/ja/docusaurus-plugin-content-docs/current/api/accordion-group.md @@ -0,0 +1,59 @@ +--- +title: "ion-accordion-group" +--- +import Props from '@ionic-internal/component-api/v7/accordion-group/props.md'; +import Events from '@ionic-internal/component-api/v7/accordion-group/events.md'; +import Methods from '@ionic-internal/component-api/v7/accordion-group/methods.md'; +import Parts from '@ionic-internal/component-api/v7/accordion-group/parts.md'; +import CustomProps from '@ionic-internal/component-api/v7/accordion-group/custom-props.md'; +import Slots from '@ionic-internal/component-api/v7/accordion-group/slots.md'; + +import EncapsulationPill from '@components/page/api/EncapsulationPill'; + + + +アコーディオン・グループは、アコーディオンインスタンスのためのコンテナです。これは、アコーディオンの状態を管理し、キーボードナビゲーションを提供します。 + +より詳細な情報や使用方法については、 [Accordion](./accordion) を参照ください。 + + +## Interfaces + +### AccordionGroupChangeEventDetail + +```typescript +interface AccordionGroupChangeEventDetail { + value: T; +} +``` + +### AccordionGroupCustomEvent + +必須ではありませんが、このコンポーネントから発行される Ionic イベントでより強く型付けを行うために、`CustomEvent` インターフェースの代わりにこのインターフェースを使用することが可能です。 + +```typescript +interface AccordionGroupCustomEvent extends CustomEvent { + detail: AccordionGroupChangeEventDetail; + target: HTMLIonAccordionGroupElement; +} +``` + + + +## プロパティ + + +## イベント + + +## メソッド + + +## CSS Shadow Parts + + +## CSSカスタムプロパティ + + +## Slots + diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/api/accordion.md b/i18n/ja/docusaurus-plugin-content-docs/current/api/accordion.md new file mode 100644 index 00000000000..09c7d993972 --- /dev/null +++ b/i18n/ja/docusaurus-plugin-content-docs/current/api/accordion.md @@ -0,0 +1,211 @@ +--- +title: "ion-accordion" +--- +import Props from '@ionic-internal/component-api/v7/accordion/props.md'; +import Events from '@ionic-internal/component-api/v7/accordion/events.md'; +import Methods from '@ionic-internal/component-api/v7/accordion/methods.md'; +import Parts from '@ionic-internal/component-api/v7/accordion/parts.md'; +import CustomProps from '@ionic-internal/component-api/v7/accordion/custom-props.md'; +import Slots from '@ionic-internal/component-api/v7/accordion/slots.md'; + + + ion-accordion: Accordion Components: How to Build & Examples + + + +import EncapsulationPill from '@components/page/api/EncapsulationPill'; + + + + +アコーディオンは、情報を整理してグループ化する方法を提供しながら、垂直方向のスペースを減らすために、コンテンツに折り畳み可能なセクションを提供します。すべての `ion-accordion` コンポーネントは `ion-accordion-group` コンポーネントの中にグループ化されている必要があります。 + +## 基本的な使い方 + +import Basic from '@site/static/usage/v7/accordion/basic/index.md'; + + + +## アコーディオンをトグルする方法 + +どのアコーディオンを開くかは、`ion-accordion-group` の `value` プロパティを設定することで制御できます。このプロパティを設定することで、開発者はプログラムによって特定のアコーディオンを展開したり折りたたんだりすることができます。 + +import Toggle from '@site/static/usage/v7/accordion/toggle/index.md'; + + + +## アコーディオンの状態変化を監視 + +開発者は `ionChange` イベントを監視することで、アコーディオンが展開または折りたたまれたときに通知されるようにすることができます。 + +import ListenChanges from '@site/static/usage/v7/accordion/listen-changes/index.md'; + + + +## 複数のアコーディオン + +開発者は `multiple` プロパティを使用して、複数のアコーディオンを一度に開くことができるようにすることができます。 + +import Multiple from '@site/static/usage/v7/accordion/multiple/index.md'; + + + +## アコーディオンの無効化 + +### アコーディオンを無効にする + +個々のアコーディオンは、`ion-accordion` の `disabled` プロパティで無効にできます。 + +import DisableIndividual from '@site/static/usage/v7/accordion/disable/individual/index.md'; + + + +### アコーディオングループ + +アコーディオングループは、`ion-accordion-group` の `disabled` プロパティで無効にすることができます。 + +import DisableGroup from '@site/static/usage/v7/accordion/disable/group/index.md'; + + + +## 読み込み可能なアコーディオン + +### 個別アコーディオン + +個々のアコーディオンは、`ion-accordion` の `readonly` プロパティで無効にできます。 + +import ReadonlyIndividual from '@site/static/usage/v7/accordion/readonly/individual/index.md'; + + + +### アコーディオングループ + +アコーディオングループは、`ion-accordion-group` の `readonly` プロパティで無効にできます。 + +import ReadonlyGroup from '@site/static/usage/v7/accordion/readonly/group/index.md'; + + + +## 構造 + +## ヘッダー + +`header` slotは、アコーディオンを展開または折りたたむためのトグルとして使用されます。アクセシビリティとテーマ機能を利用するために、ここでは `ion-item` を使用することをお勧めします。 + +`header` slotに `ion-item` を使用する場合、 `ion-item` の `button` プロパティは `true` に、 `detail` プロパティは `false` に設定されます。さらに、`ion-item` にはトグルアイコンも自動的に追加されます。このアイコンは、アコーディオンを展開したり折りたたんだりすると、自動的に回転するようになります。詳しくは、 [アイコンのカスタマイズ](#icons) を参照してください。 + +### コンテンツ + +`content` slotは、アコーディオンの状態に応じて表示/非表示される部分として使用されます。1ページに1つだけ `ion-content` インスタンスを追加する必要があるため、ここには他の `ion-content` インスタンスを除いて何でも置くことができます。 + +## カスタマイズ + +### 拡張スタイル + +組み込みの拡張スタイルには、`compact` と `inset` の 2 種類があります。この拡張スタイルは `ion-accordion-group` の `expand` プロパティによって設定されます。 + +`expand="inset"` の場合、アコーディオングループにはborder radiusが与えられます。 `md` モードでは、アコーディオン全体を開くと下に移動します。 + +import ExpansionStyles from '@site/static/usage/v7/accordion/customization/expansion-styles/index.md'; + + + +### 高度な拡張スタイル + +アコーディオンの状態に応じてスタイルを設定することで、展開の動作をカスタマイズすることができます。 `ion-accordion` には4つのステートクラスが適用されています。これらのクラスを使ってスタイリングすることで、高度な状態遷移を作成することができます。 + +| Class Name | Description | +| ---------- |-----------------------------------| +| `.accordion-expanding` | アコーディオンがアクティブに展開しているときに適用されます。 | +| `.accordion-expanded` | アコーディオンが完全に展開されたときに適用されます。 | +| `.accordion-collapsing` | アコーディオンがアクティブに折りたたまれているときに適用されます。 | +| `.accordion-collapsed` | アコーディオンが完全に折りたたまれているときに適用されます。 | + +アコーディオンの特定の部分をターゲットにする必要がある場合、要素を直接ターゲットにすることをお勧めします。例えば、アコーディオンが展開されたときに `header` slot の ion-item をカスタマイズしたい場合、以下のセレクタを使用することができます。 + +```css +ion-accordion.accordion-expanding ion-item[slot="header"], +ion-accordion.accordion-expanded ion-item[slot="header"] { + --color: red; +} +``` + +import AdvancedExpansionStyles from '@site/static/usage/v7/accordion/customization/advanced-expansion-styles/index.md'; + + + +### アイコン + +`header` slot に `ion-item` を使用する場合、自動的に `ion-icon` が追加されます。使用するアイコンの種類は `toggleIcon` プロパティで制御でき、追加するスロットも `toggleIconSlot` プロパティで制御することができます。 + +アイコンを自分で管理したい場合や、`ion-icon` 以外のアイコンを使用したい場合は、icon 要素に `ion-accordion-toggle-icon` クラスを追加することができます。 + +どのオプションを選択しても、アコーディオンを展開または折りたたむと、アイコンは自動的に回転します。 + +import Icons from '@site/static/usage/v7/accordion/customization/icons/index.md'; + + + +### テーマ + +`ion-accordion` はヘッダーとコンテンツ要素を囲むシェルとして機能するので、アコーディオンを簡単に好きなようにテーマ化することができます。ヘッダーのテーマは、スロットの `ion-item` をターゲットにすることで行うことができます。 `ion-item` を使用しているので、 [ion-item CSS Variables](./item#css-custom-properties) と [ion-item Shadow Parts](./item#css-shadow-parts) にもすべてアクセスすることができます。コンテンツのテイムも、`content` slotにある要素をターゲットにすることで簡単に実現できます。 + +import Theming from '@site/static/usage/v7/accordion/customization/theming/index.md'; + + + +## アクセシビリティ + +### アニメーション + +デフォルトでは、アコーディオン・アイテムを展開したり折りたたんだりする際にアニメーションが有効になります。アニメーションは `prefers-reduced-motion` メディアクエリがサポートされ、`reduce` に設定されると自動的に無効化されます。対応していないブラウザでは、Ionic Frameworkアプリで `animated` を設定することで、アニメーションを無効にすることができます。 + +import AccessibilityAnimations from '@site/static/usage/v7/accordion/accessibility/animations/index.md'; + + + +### キーボードナビゲーション + +`ion-accordion-group` の中で使用する場合、`ion-accordion` はキーボードによる操作を完全にサポートしています。次の表は、それぞれのキーが何をするのかの詳細です。 + +| Key | Function | +| ------------------ | ------------------------------------------------------------ | +| `Space` or `Enter` | When focus is on the accordion header, the accordion will collapse or expand depending on the state of the component. | +| `Tab` | Moves focus to the next focusable element. | +| `Shift` + `Tab` | Moves focus to the previous focusable element. | +| `Down Arrow` | - When focus is on an accordion header, moves focus to the next accordion header.
- When focus is on the last accordion header, moves focus to the first accordion header. | +| `Up Arrow` | - When focus is on an accordion header, moves focus to the previous accordion header.
- When focus is on the first accordion header, moves focus to the last accordion header. | +| `Home` | When focus is on an accordion header, moves focus to the first accordion header. | +| `End` | When focus is on an accordion header, moves focus to the last accordion header. | + +## パフォーマンス + +### アニメーション + +アコーディオンアニメーションは、アニメーションを開始するときに `content` slotの高さを知ることによって動作します。アコーディオンは、この高さがアニメーションの間、一貫して保たれることを期待します。そのため、開発者はアニメーション中にコンテンツの高さを変更するような操作を行わないようにしなければなりません。 + +例えば、[ion-img](./img) を使用すると、画像を遅延ロードするため、レイアウトのずれが生じることがあります。つまり、アニメーションを再生すると、 `ion-img` が画像データをロードし、ロードされた画像データを考慮して `ion-img` の寸法が変更されることになります。その結果、 `content` slotの高さが変化してしまうことがあります。これを避けるために、開発者にはいくつかのオプションがあります。 + +1. 遅延読み込みを行わない `img` 要素を使用します。`ion-img` は常に遅延読み込みを使用しますが、`img` はデフォルトでは遅延読み込みを使用しません。これは最も単純なオプションで、遅延読み込みの恩恵をあまり受けない小さな画像を使用する場合に有効です。 + +2. `ion-img` に最小の幅と高さを設定します。遅延読み込みを使用する必要があり、前もって画像の寸法がわかっている場合(同じサイズのアイコンを読み込む場合など)、CSS を使用して `ion-img` に最小限の幅または高さを設定することができます。これにより、開発者はレイアウトの崩れを防ぎつつ、遅延ロードの恩恵を受けることができます。これは、 `img` 要素を `loading="lazy"` と共に使用する場合にも有効です! + +3. これらの解決方法を選択できない場合、開発者は [ion-accordion-group](./accordion-group) の `animated` プロパティを使用してアニメーションを完全に無効にすることを検討することができます。 + +## プロパティ + + +## イベント + + +## メソッド + + +## CSS Shadow Parts + + +## CSSカスタムプロパティ + + +## Slots + diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/api/action-sheet.md b/i18n/ja/docusaurus-plugin-content-docs/current/api/action-sheet.md new file mode 100644 index 00000000000..d2870b292d0 --- /dev/null +++ b/i18n/ja/docusaurus-plugin-content-docs/current/api/action-sheet.md @@ -0,0 +1,298 @@ +--- +title: "ion-action-sheet" +--- +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +import Props from '@ionic-internal/component-api/v7/action-sheet/props.md'; +import Events from '@ionic-internal/component-api/v7/action-sheet/events.md'; +import Methods from '@ionic-internal/component-api/v7/action-sheet/methods.md'; +import Parts from '@ionic-internal/component-api/v7/action-sheet/parts.md'; +import CustomProps from '@ionic-internal/component-api/v7/action-sheet/custom-props.md'; +import Slots from '@ionic-internal/component-api/v7/action-sheet/slots.md'; + + + ion-action-sheet: Action Sheet Dialog for iOS and Android + + + +import EncapsulationPill from '@components/page/api/EncapsulationPill'; + + + + +Action Sheetは複数の選択肢を表示するダイアログです。アプリのコンテンツ上に表示され、ユーザが手動で破棄しないとアプリの利用を再開することはできません。`ios` modeでは、破壊的な選択肢は明示されます(コンテンツの削除などは赤字などでわかりやすく表示されます)。Action Sheetを破棄するには、背景をタップする、デスクトップのパソコンの場合はエスケープキーを押すなど、複数の選択肢があります。 + +## インラインアクションシート (推奨) + +`ion-action-sheet` は、テンプレートに直接コンポーネントを記述することで使用することができます。これにより、アクションシートを表示するために配線する必要があるハンドラの数を減らすことができます。 + +import Trigger from '@site/static/usage/v7/action-sheet/inline/trigger/index.md'; + + + +### `isOpen` を使う + +`ion-action-sheet` の `isOpen` プロパティは、開発者がアプリケーションの状態からアクションシートの表示状態を制御することを可能にします。つまり、`isOpen`が`true`に設定されるとアクションシートが表示され、`isOpen`が`false`に設定されるとアクションシートは解除されます。 + +`isOpen` は一方通行のデータバインディングを使用しているため、アクションシートが終了したときに自動的に `false` に設定されることはありません。開発者は `ionActionSheetDidDismiss` または `didDismiss` イベントをリッスンして `isOpen` を `false` に設定する必要があります。この理由は、`ion-action-sheet` の内部がアプリケーションの状態と密接に結合するのを防ぐためです。一方通行のデータバインディングでは、アクションシートはリアクティブ変数が提供するブーリアン値だけを気にすればよい。一方通行のデータバインディングでは、アクションシートは、ブーリアン値とリアクティブ変数の存在の両方に関心を持つ必要があります。これは、非決定的な動作につながり、アプリケーションのデバッグを困難にします。 + +import IsOpen from '@site/static/usage/v7/action-sheet/inline/isOpen/index.md'; + + + +## Controller アクションシート + +アクションシートの表示・非表示をより細かく制御したい場合は、`actionSheetController`を使用することができます。 + +import Controller from '@site/static/usage/v7/action-sheet/controller/index.md'; + + + +## Buttons + +Buttonの `role` プロパティは、 `destructive` か `cancel` のどちらかを利用できます。 roleプロパティがない場合は、プラットフォームに応じたデフォルトの外観となります。`cancel` role を持つButtonは、配列 `buttons` のどこに配置してもアクションシートの最下部に表示されます。 Note: `destructive` roleをつけるButtonは、一番上のButtonとして配置することをおすすめします。また、背景をタップしてアクションシートを破棄した場合、cancel role に設定されているhandlerが実行されます。 + +Buttonは `ActionSheetButton` の `data` プロパティを介してデータを渡すこともできます。これは `onDidDismiss` メソッドの戻り値にある `data` フィールドにデータを入力します。 + +## Collecting Role Information on Dismiss + +`didDismiss` イベントが発生すると、イベント詳細の `data` と `role` フィールドを使用して、アクションシートがどのように却下されたかについての情報を収集することができます。 + +import RoleInfo from '@site/static/usage/v7/action-sheet/role-info-on-dismiss/index.md'; + + + +## テーマ + +アクションシートはscopedによるカプセル化を採用しており、実行時に各スタイルにクラスを追加することで、自動的にCSSをスコープ化します。CSSでscopedセレクタをオーバーライドするには、[higher specificity](https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity) セレクタが必要です。 + +### スタイリング + +私たちは、 `create` メソッドで `cssClass` にカスタムクラスを渡し、それを使ってホストと内部要素にカスタムスタイルを追加することをお勧めします。このプロパティは、スペースで区切られた複数のクラスを受け付けることもできます。 + +```css +/* DOES NOT WORK - not specific enough */ +.action-sheet-group { + background: #e5e5e5; +} + +/* Works - pass "my-custom-class" in cssClass to increase specificity */ +.my-custom-class .action-sheet-group { + background: #e5e5e5; +} +``` + +import Styling from '@site/static/usage/v7/action-sheet/theming/styling/index.md'; + + + +## CSSカスタムプロパティ + +[CSSカスタムプロパティ](#css-custom-properties-1) は、個々の要素を対象とすることなく、アクションシートのスタイルに使用することができます。 + +import CssCustomProperties from '@site/static/usage/v7/action-sheet/theming/css-properties/index.md'; + + + +## アクセシビリティ + +### Screen Readers + +アクションシートは、スクリーンリーダーにとって [アクセシブル](../reference/glossary#a11y) であるためにariaプロパティを設定しますが、これらのプロパティは、十分な説明になっていなかったり、アクションシートがアプリでどのように使用されているかに合っていなかったりする場合、オーバーライドすることができます。 + +#### Role + +アクションシートには `role` として [`dialog`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/dialog_role) が設定されます。ARIA仕様に合わせるためには、`aria-label`属性か`aria-labelledby`属性のどちらかを設定しなければなりません。 + +#### Action Sheet の概要 + +Ionicは自動的にヘッダー要素を指すように `aria-labelledby` を設定するので、すべてのアクションシートには `header` プロパティを定義することを強く推奨します。しかし、`header`を含めない場合は、`htmlAttributes`プロパティを使って、説明的な`aria-label`を指定するか、カスタムの`aria-labelledby`値を設定することもできます。 + + + + + +```javascript +const actionSheet = await this.actionSheetController.create({ + htmlAttributes: { + 'aria-label': 'action sheet dialog', + }, +}); +``` + + + + + +```javascript +const actionSheet = await this.actionSheetController.create({ + htmlAttributes: { + 'aria-label': 'action sheet dialog', + }, +}); +``` + + + + + +```javascript +useIonActionSheet({ + htmlAttributes: { + 'aria-label': 'action sheet dialog', + }, +}); +``` + + + + + +```javascript +const actionSheet = await actionSheetController.create({ + htmlAttributes: { + 'aria-label': 'action sheet dialog', + }, +}); +``` + + + + + +#### Action Sheet Buttons の概要 + +テキストを含むボタンはスクリーンリーダーによって読み取られる。ボタンがアイコンのみを含んでいる場合や、既存のテキスト以外の説明が必要な場合は、ボタンの `htmlAttributes` プロパティに `aria-label` を渡して、ラベルをボタンに割り当てる必要があります。 + + + + + +```javascript +const actionSheet = await this.actionSheetController.create({ + header: 'Header', + buttons: [ + { + icon: 'close', + htmlAttributes: { + 'aria-label': 'close', + }, + }, + ], +}); +``` + + + + + +```javascript +const actionSheet = await this.actionSheetController.create({ + header: 'Header', + buttons: [ + { + icon: 'close', + htmlAttributes: { + 'aria-label': 'close', + }, + }, + ], +}); +``` + + + + + +```javascript +useIonActionSheet({ + header: 'Header', + buttons: [ + { + icon: 'close', + htmlAttributes: { + 'aria-label': 'close', + }, + }, + ], +}); +``` + + + + + +```javascript +const actionSheet = await actionSheetController.create({ + header: 'Header', + buttons: [ + { + icon: 'close', + htmlAttributes: { + 'aria-label': 'close', + }, + }, + ], +}); +``` + + + + + +## Interfaces + +### ActionSheetButton + +```typescript +interface ActionSheetButton { + text?: string; + role?: 'cancel' | 'destructive' | 'selected' | string; + icon?: string; + cssClass?: string | string[]; + id?: string; + htmlAttributes?: { [key: string]: any }; + handler?: () => boolean | void | Promise; + data?: T; +} +``` + +### ActionSheetOptions + +```typescript +interface ActionSheetOptions { + header?: string; + subHeader?: string; + cssClass?: string | string[]; + buttons: (ActionSheetButton | string)[]; + backdropDismiss?: boolean; + translucent?: boolean; + animated?: boolean; + mode?: Mode; + keyboardClose?: boolean; + id?: string; + htmlAttributes?: { [key: string]: any }; + + enterAnimation?: AnimationBuilder; + leaveAnimation?: AnimationBuilder; +} +``` + +## プロパティ + + +## イベント + + +## メソッド + + +## CSS Shadow Parts + + +## CSSカスタムプロパティ + + +## Slots + diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/api/alert.md b/i18n/ja/docusaurus-plugin-content-docs/current/api/alert.md new file mode 100644 index 00000000000..db06af13123 --- /dev/null +++ b/i18n/ja/docusaurus-plugin-content-docs/current/api/alert.md @@ -0,0 +1,350 @@ +--- +title: "ion-alert" +--- +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +import Props from '@ionic-internal/component-api/v7/alert/props.md'; +import Events from '@ionic-internal/component-api/v7/alert/events.md'; +import Methods from '@ionic-internal/component-api/v7/alert/methods.md'; +import Parts from '@ionic-internal/component-api/v7/alert/parts.md'; +import CustomProps from '@ionic-internal/component-api/v7/alert/custom-props.md'; +import Slots from '@ionic-internal/component-api/v7/alert/slots.md'; + + + ion-alert: Ionic Alert Buttons with Custom Message Prompts + + + +import EncapsulationPill from '@components/page/api/EncapsulationPill'; + + + +アラートは、ユーザーに情報を提示したり、Inputを使ってユーザーから情報を収集したりするダイアログである。アラートはアプリのコンテンツの上に表示され、アプリとの対話を再開する前に、ユーザーが手動で解除する必要があります。また、オプションで `header`、`subHeader`、`message` を持つことができます。 + +## インラインアラート(推奨) + +`ion-alert` は、テンプレートに直接コンポーネントを記述して使用することができます。これにより、アラートを表示するために必要なハンドラの数を減らすことができます。 + +import Trigger from '@site/static/usage/v7/alert/presenting/trigger/index.md'; + + + +### `isOpen` を使う + +`ion-alert` の `isOpen` プロパティは、開発者がアプリケーションの状態からアラートの表示状態を制御することを可能にします。つまり、`isOpen` を `true` に設定するとアラートが表示され、`isOpen` を `false` に設定するとアラートは解除されます。 + +`isOpen` は一方通行のデータバインディングを使用しているため、アラートが解除されたときに自動的に `false` に設定されることはありません。開発者は `ionAlertDidDismiss` または `didDismiss` イベントを待ち、`isOpen` を `false` に設定する必要があります。この理由は、`ion-alert` の内部がアプリケーションの状態と密接に結合するのを防ぐためである。一方通行のデータバインディングでは、アラートはリアクティブ変数が提供するブーリアン値だけを気にすればよい。双方向のデータバインディングでは、アラートはブーリアン値とリアクティブ変数の存在の両方に関心を持つ必要があります。これは、非決定的な動作につながり、アプリケーションのデバッグを困難にする可能性があります。 + +import IsOpen from '@site/static/usage/v7/alert/presenting/isOpen/index.md'; + + + +## Controller Alerts + +`alertController`は、アラートを表示するタイミングや解除するタイミングをより細かく制御する必要がある場合に使用することができる。 + +import Controller from '@site/static/usage/v7/alert/presenting/controller/index.md'; + + + +## Buttons + +`buttons` の配列には、各buttonの `text` のプロパティと、オプションで `handler` を利用することができます。 `handler` が `false` を返した場合、buttonがクリックされてもAlertは自動的に解除されません。すべての `buttons` は、左から右にボタン配列に追加された順序で表示されます。 Note: 一番右のボタン(配列の最後の1つ)がメインボタンです。 + +オプションで、`cancel`のような `role` プロパティをボタンに追加することができます。もし `cancel` ロールがボタンのいずれかに設定されている場合、バックドロップをタップしてアラートが解除されると、キャンセルロールを持つボタンから handler が起動されます。 + +import Buttons from '@site/static/usage/v7/alert/buttons/index.md'; + + + + +## Inputs + +Alertには、複数の異なるInputを含めることもでき、そのデータをアプリで受け取ることができます。 Inputはユーザーに情報の入力を促す簡単な方法として使用できます。Radios, checkboxes と text inputs textarea はすべて利用できますが、これらを混ぜて利用することはできません。例えば、Alertはすべてbutton Inputであったり、すべてcheckboxでのInputを持つことはできますが、同一のAlertにradioとcheckbox Inputを混ぜることはできません。ただし、"text" Inputでは、 `url`, `email`, `text` などの複数のtypeを混ぜて利用することはできます。アラートのガイドラインに収まらない複雑なForm UIが必要な場合は、代わりにModal内でFormを構築することをお勧めします。 + +### Text Inputs Example + +import TextInputs from '@site/static/usage/v7/alert/inputs/text-inputs/index.md'; + + + +### Radio Example + +import Radios from '@site/static/usage/v7/alert/inputs/radios/index.md'; + + + +## カスタマイズ + +Alertはscopedによるカプセル化を使用しており、実行時に各スタイルにクラスを追加することで自動的にCSSをスコープします。CSSでscopedセレクタをオーバーライドするには、[higher specificity](https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity) セレクタが必要です。 + +`create` メソッドで `cssClass` にカスタムクラスを渡し、それを使ってホストと内部要素にカスタムスタイルを追加することをお勧めします。このプロパティは、スペースで区切られた複数のクラスを受け付けることもできます。 + +```css +/* DOES NOT WORK - not specific enough */ +.alert-wrapper { + background: #e5e5e5; +} + +/* Works - pass "my-custom-class" in cssClass to increase specificity */ +.my-custom-class .alert-wrapper { + background: #e5e5e5; +} +``` + +[CSSカスタムプロパティ](#css-custom-properties) は、個々の要素をターゲットにすることなく、アラートのスタイルに使用することができます。 + +```css +.my-custom-class { + --background: #e5e5e5; +} +``` + +import Customization from '@site/static/usage/v7/alert/customization/index.md'; + + + +:::note +IonicのAngularアプリを構築する場合、スタイルはグローバルなスタイルシートファイルに追加する必要があります。 +::: + +## アクセシビリティ + +### Screen Readers + +アラートは、スクリーンリーダーにとって[アクセシブル](../reference/glossary#a11y)であるために、ariaプロパティを設定しますが、これらのプロパティは、十分な説明がない場合、またはアラートがアプリでどのように使用されているかと一致しない場合は、オーバーライドすることができます。 + +#### Role + +Ionicは自動的にアラートの`role`を、入力やボタンがある場合は[`alertdialog`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/alertdialog_role)に、何もない場合は[`alert`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/alert_role)に設定します。 + +#### Alert の概要 + +アラートに `header` プロパティが定義されている場合、`aria-labelledby` 属性は自動的にヘッダの ID に設定されます。 `header` が定義されていない場合、`subHeader` 要素がフォールバックとして使用されます。同様に、 `aria-describedby` 属性が定義されている場合は、自動的に `message` 要素の ID が設定されます。 + +ARIAの仕様に合わせるために、アラートには `message` と `header` または `subHeader` を含めることを強くお勧めします。もし `header` や `subHeader` を含めない場合は、`htmlAttributes` プロパティを使用して、説明的な `aria-label` を指定することができます。 + + + + + +```javascript +const alert = await this.alertController.create({ + message: 'This is an alert with custom aria attributes.', + htmlAttributes: { + 'aria-label': 'alert dialog', + }, +}); +``` + + + + + +```javascript +const alert = await this.alertController.create({ + message: 'This is an alert with custom aria attributes.', + htmlAttributes: { + 'aria-label': 'alert dialog', + }, +}); +``` + + + + + +```javascript +useIonAlert({ + message: 'This is an alert with custom aria attributes.', + htmlAttributes: { + 'aria-label': 'alert dialog', + }, +}); +``` + + + + + +```javascript +const alert = await alertController.create({ + message: 'This is an alert with custom aria attributes.', + htmlAttributes: { + 'aria-label': 'alert dialog', + }, +}); +``` + + + + + + +すべてのARIA属性は、アラートの`htmlAttributes`プロパティにカスタム値を定義することで、手動で上書きすることができます。 + +#### Alert Buttons の概要 + +Buttons containing text will be read by a screen reader. If a description other than the existing text is desired, a label can be set on the button by passing `aria-label` to the `htmlAttributes` property on the button. + + + + + +```javascript +const alert = await this.alertController.create({ + header: 'Header', + buttons: [ + { + text: 'Exit', + htmlAttributes: { + 'aria-label': 'close', + }, + }, + ], +}); +``` + + + + + +```javascript +const alert = await this.alertController.create({ + header: 'Header', + buttons: [ + { + text: 'Exit', + htmlAttributes: { + 'aria-label': 'close', + }, + }, + ], +}); +``` + + + + + +```javascript +useIonAlert({ + header: 'Header', + buttons: [ + { + text: 'Exit', + htmlAttributes: { + 'aria-label': 'close', + }, + }, + ], +}); +``` + + + + + +```javascript +const alert = await alertController.create({ + header: 'Header', + buttons: [ + { + text: 'Exit', + htmlAttributes: { + 'aria-label': 'close', + }, + }, + ], +}); +``` + + + + + +## Interfaces + +### AlertButton + +```typescript +type AlertButtonOverlayHandler = boolean | void | { [key: string]: any }; + +interface AlertButton { + text: string; + role?: 'cancel' | 'destructive' | string; + cssClass?: string | string[]; + id?: string; + htmlAttributes?: { [key: string]: any }; + handler?: (value: any) => AlertButtonOverlayHandler | Promise; +} +``` + + +### AlertInput + +```typescript +interface AlertInput { + type?: TextFieldTypes | 'checkbox' | 'radio' | 'textarea'; + name?: string; + placeholder?: string; + value?: any; + /** + * The label text to display next to the input, if the input type is `radio` or `checkbox`. + */ + label?: string; + checked?: boolean; + disabled?: boolean; + id?: string; + handler?: (input: AlertInput) => void; + min?: string | number; + max?: string | number; + cssClass?: string | string[]; + attributes?: { [key: string]: any }; + tabindex?: number; +} +``` + + +### AlertOptions + +```typescript +interface AlertOptions { + header?: string; + subHeader?: string; + message?: string | IonicSafeString; + cssClass?: string | string[]; + inputs?: AlertInput[]; + buttons?: (AlertButton | string)[]; + backdropDismiss?: boolean; + translucent?: boolean; + animated?: boolean; + htmlAttributes?: { [key: string]: any }; + + mode?: Mode; + keyboardClose?: boolean; + id?: string; + + enterAnimation?: AnimationBuilder; + leaveAnimation?: AnimationBuilder; +} +``` + +## プロパティ + + +## イベント + + +## メソッド + + +## CSS Shadow Parts + + +## CSSカスタムプロパティ + + +## Slots + diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/api/app.md b/i18n/ja/docusaurus-plugin-content-docs/current/api/app.md new file mode 100644 index 00000000000..c92f455e3b6 --- /dev/null +++ b/i18n/ja/docusaurus-plugin-content-docs/current/api/app.md @@ -0,0 +1,47 @@ +--- +title: "ion-app" +--- +import Props from '@ionic-internal/component-api/v7/app/props.md'; +import Events from '@ionic-internal/component-api/v7/app/events.md'; +import Methods from '@ionic-internal/component-api/v7/app/methods.md'; +import Parts from '@ionic-internal/component-api/v7/app/parts.md'; +import CustomProps from '@ionic-internal/component-api/v7/app/custom-props.md'; +import Slots from '@ionic-internal/component-api/v7/app/slots.md'; + + + ion-app: Container Element for an Ionic Application + + + +import EncapsulationPill from '@components/page/api/EncapsulationPill'; + + +AppはIonicアプリケーションのコンテナ要素です。プロジェクトごとに `` 要素は1つだけにしてください。アプリケーションには、menus, headers, content, footersなど、多くのIonicコンポーネントを含めることができます。オーバーレイコンポーネントは、表示されるときに `` に追加されます。 + +`ion-app`を使用すると、以下の動作が可能になります。 + +* [キーボードライフサイクルイベント](../developing/keyboard#keyboard-lifecycle-events) は、ネイティブプラグインを必要なくなります。 +* Android 端末のハードウェアバックボタンの動作をカスタマイズするための [Hardware Back Button Listeners](../developing/hardware-back-button) を使えます +* Capacitor や Cordova でステータスバーをサポートし、ステータスバーをタップすることでビューの最上部にスクロールできるようになります。 +* テキスト入力が画面上のキーボードにかからないように、コンテンツをスクロールさせるスクロールアシストユーティリティが使えます。 +* Material Design モードでのボタン操作時の[Ripple effect](./リップルエフェクト) が使えます。 +* Ionicアプリの使用感をよりネイティブなものにする、その他のタップやフォーカスのユーティリティが使えます。 + + +## プロパティ + + +## イベント + + +## メソッド + + +## CSS Shadow Parts + + +## CSSカスタムプロパティ + + +## Slots + diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/api/avatar.md b/i18n/ja/docusaurus-plugin-content-docs/current/api/avatar.md new file mode 100644 index 00000000000..782ea64a91f --- /dev/null +++ b/i18n/ja/docusaurus-plugin-content-docs/current/api/avatar.md @@ -0,0 +1,67 @@ +--- +title: "ion-avatar" +--- + +import Props from '@ionic-internal/component-api/v7/avatar/props.md'; +import Events from '@ionic-internal/component-api/v7/avatar/events.md'; +import Methods from '@ionic-internal/component-api/v7/avatar/methods.md'; +import Parts from '@ionic-internal/component-api/v7/avatar/parts.md'; +import CustomProps from '@ionic-internal/component-api/v7/avatar/custom-props.md'; +import Slots from '@ionic-internal/component-api/v7/avatar/slots.md'; + + + ion-avatar: Circular Application Avatar Icon Component + + + +import EncapsulationPill from '@components/page/api/EncapsulationPill'; + + + +Avatarは通常、写真やアイコンをラップする円形のコンポーネントです。これらは、人またはオブジェクトを表示するために使用できます。 + +Avatarは、単独で使用することも、任意の要素の内部で使用することもできます。`ion-chip` または `ion-item` の内部に配置すると、Avatarは親コンポーネントに合わせてサイズ変更します。Avatarをitemの左側または右側に配置するには、`slot` を `start` か `end` に設定します。 + +## 基本的な使い方 + +import Basic from '@site/static/usage/v7/avatar/basic/index.md'; + + + +## Chip Avatar + +import Chip from '@site/static/usage/v7/avatar/chip/index.md'; + + + +## Item Avatar + +import Item from '@site/static/usage/v7/avatar/item/index.md'; + + + +## テーマ + +## CSSカスタムプロパティ + +import CSSProps from '@site/static/usage/v7/avatar/theming/css-properties/index.md'; + + + +## プロパティ + + +## イベント + + +## メソッド + + +## CSS Shadow Parts + + +## CSSカスタムプロパティ + + +## Slots + diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/api/back-button.md b/i18n/ja/docusaurus-plugin-content-docs/current/api/back-button.md new file mode 100644 index 00000000000..909e8217746 --- /dev/null +++ b/i18n/ja/docusaurus-plugin-content-docs/current/api/back-button.md @@ -0,0 +1,57 @@ +--- +title: "ion-back-button" +--- +import Props from '@ionic-internal/component-api/v7/back-button/props.md'; +import Events from '@ionic-internal/component-api/v7/back-button/events.md'; +import Methods from '@ionic-internal/component-api/v7/back-button/methods.md'; +import Parts from '@ionic-internal/component-api/v7/back-button/parts.md'; +import CustomProps from '@ionic-internal/component-api/v7/back-button/custom-props.md'; +import Slots from '@ionic-internal/component-api/v7/back-button/slots.md'; + + + ion-back-button: Custom Menu Back Button for Applications + + + +import EncapsulationPill from '@components/page/api/EncapsulationPill'; + + + + +Back Buttonは、クリックされるとアプリの履歴に戻るようにナビゲートします。このボタンは、ナビゲーションスタックに履歴があるときのみ表示されます。ただし、 [`defaultHref`](#default-back-history) が設定されている場合は除きます。戻るボタンはモードに応じて異なるテキストとアイコンを表示しますが、これはカスタマイズすることができます。 + +## 基本的な使い方 + +import Basic from '@site/static/usage/v7/back-button/basic/index.md'; + + + +## カスタムのBack Button + +デフォルトでは、Back Buttonはテキスト `"Back"` と共に、`ios` では `"chevron-back"` アイコン、`md` では `"arrow-back-sharp"` アイコンを表示します。これは、`icon`または`text`プロパティを設定することで、戻るボタンコンポーネントごとにカスタマイズすることができます。また、グローバル設定の `backButtonIcon` または `backButtonText` プロパティを使用して、グローバルに設定することもできます。詳しくは、[Config docs](../developing/config) を参照してください。 + +import Custom from '@site/static/usage/v7/back-button/custom/index.md'; + + + +## デフォルトのBack履歴 + +時折、アプリが履歴がないときに戻るボタンを表示し、ナビゲートする必要がある場合があります。この場合、戻るボタンの `defaultHref` をパスに設定することで実現できます。 `defaultHref` を使用するには、アプリにパスが設定されたルーターが含まれている必要があります。 + +## プロパティ + + +## イベント + + +## メソッド + + +## CSS Shadow Parts + + +## CSSカスタムプロパティ + + +## Slots + diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/api/backdrop.md b/i18n/ja/docusaurus-plugin-content-docs/current/api/backdrop.md new file mode 100644 index 00000000000..7a1a48a1662 --- /dev/null +++ b/i18n/ja/docusaurus-plugin-content-docs/current/api/backdrop.md @@ -0,0 +1,51 @@ +--- +title: "ion-backdrop" +--- +import Props from '@ionic-internal/component-api/v7/backdrop/props.md'; +import Events from '@ionic-internal/component-api/v7/backdrop/events.md'; +import Methods from '@ionic-internal/component-api/v7/backdrop/methods.md'; +import Parts from '@ionic-internal/component-api/v7/backdrop/parts.md'; +import CustomProps from '@ionic-internal/component-api/v7/backdrop/custom-props.md'; +import Slots from '@ionic-internal/component-api/v7/backdrop/slots.md'; + +import EncapsulationPill from '@components/page/api/EncapsulationPill'; + + + +Backdropは、他のコンポーネントをオーバーレイするためフルスクリーンのコンポーネントです。これらは、他のコンテンツの上に遷移するコンポーネントのバックグラウンドで役立ち、そのコンポーネントを削除するために使用できます。 + +## 基本的な使い方 + +Backdropは、その後ろのコンテンツをクリックしたりタップしたりするのを防ぎます。デフォルトでは透明なので、下のデモではCSSで見えるようにしています。 + +import Basic from '@site/static/usage/v7/backdrop/basic/index.md'; + + + +## スタイリング + +バックドロップは、CSSプロパティをバックドロップ要素に直接割り当てることで、カスタマイズすることができます。一般的なプロパティには `background-color`, `background`, `opacity` があります。 + +コンテンツに `z-index` を設定し、背景よりも高い位置に表示させることができます(デフォルトは `2` です)。 + +import Styling from '@site/static/usage/v7/backdrop/styling/index.md'; + + + +## プロパティ + + +## イベント + + +## メソッド + + +## CSS Shadow Parts + + +## CSSカスタムプロパティ + + +## Slots + \ No newline at end of file diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/api/badge.md b/i18n/ja/docusaurus-plugin-content-docs/current/api/badge.md new file mode 100644 index 00000000000..b5cc2582245 --- /dev/null +++ b/i18n/ja/docusaurus-plugin-content-docs/current/api/badge.md @@ -0,0 +1,58 @@ +--- +title: "ion-badge" +--- +import Props from '@ionic-internal/component-api/v7/badge/props.md'; +import Events from '@ionic-internal/component-api/v7/badge/events.md'; +import Methods from '@ionic-internal/component-api/v7/badge/methods.md'; +import Parts from '@ionic-internal/component-api/v7/badge/parts.md'; +import CustomProps from '@ionic-internal/component-api/v7/badge/custom-props.md'; +import Slots from '@ionic-internal/component-api/v7/badge/slots.md'; + + + ion-badge: iOS & Android App Notification Badge Icons + + + +import EncapsulationPill from '@components/page/api/EncapsulationPill'; + + + +バッジはインラインブロック要素で、通常は他の要素の近くに表示されます。通常、数字やその他の文字が含まれています。バッジは、ある要素に関連する追加項目があることを知らせたり、その項目の数を示したりするために使用されます。バッジは、コンテンツが渡されないと非表示になります。 + +## 基本的な使い方 + +import Basic from '@site/static/usage/v7/badge/basic/index.md'; + + + +## テーマ + +### Colors + +import Colors from '@site/static/usage/v7/badge/theming/colors/index.md'; + + + +### CSS Properties + +import CSSProps from '@site/static/usage/v7/badge/theming/css-properties/index.md'; + + + +## プロパティ + + +## イベント + + +## メソッド + + +## CSS Shadow Parts + + +## CSSカスタムプロパティ + + +## Slots + diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/api/breadcrumb.md b/i18n/ja/docusaurus-plugin-content-docs/current/api/breadcrumb.md new file mode 100644 index 00000000000..ec0d92798fe --- /dev/null +++ b/i18n/ja/docusaurus-plugin-content-docs/current/api/breadcrumb.md @@ -0,0 +1,60 @@ +--- +title: "ion-breadcrumb" +--- +import Props from '@ionic-internal/component-api/v7/breadcrumb/props.md'; +import Events from '@ionic-internal/component-api/v7/breadcrumb/events.md'; +import Methods from '@ionic-internal/component-api/v7/breadcrumb/methods.md'; +import Parts from '@ionic-internal/component-api/v7/breadcrumb/parts.md'; +import CustomProps from '@ionic-internal/component-api/v7/breadcrumb/custom-props.md'; +import Slots from '@ionic-internal/component-api/v7/breadcrumb/slots.md'; + +import EncapsulationPill from '@components/page/api/EncapsulationPill'; + + + + +Breadcrumbは、Breadcrumbsコンポーネントの子であり、単一のナビゲーションアイテムです。Breadcrumbは、アプリ内の他の場所にリンクすることも、プレーンテキストにすることもできます。Breadcrumbsは、次のBreadcrumbとの間にセパレータを持ち、オプションでアイコンを含むことができます。 + +詳しい説明は [Breadcrumbs](./breadcrumbs) を参照ください。 + +## Interfaces + +### BreadcrumbCollapsedClickEventDetail + +```typescript +interface BreadcrumbCollapsedClickEventDetail { + collapsedBreadcrumbs?: HTMLIonBreadcrumbElement[]; +} +``` + +### BreadcrumbCustomEvent + +必須ではありませんが、より強い型付けのために、このインターフェースを `CustomEvent` インターフェースの代わりに使用することができます。 + +```typescript +interface BreadcrumbCustomEvent extends CustomEvent { + detail: BreadcrumbCollapsedClickEventDetail; + target: HTMLIonBreadcrumbElement; +} +``` + + + + +## プロパティ + + +## イベント + + +## メソッド + + +## CSS Shadow Parts + + +## CSSカスタムプロパティ + + +## Slots + diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/api/breadcrumbs.md b/i18n/ja/docusaurus-plugin-content-docs/current/api/breadcrumbs.md new file mode 100644 index 00000000000..162b5852469 --- /dev/null +++ b/i18n/ja/docusaurus-plugin-content-docs/current/api/breadcrumbs.md @@ -0,0 +1,104 @@ +--- +title: "ion-breadcrumbs" +--- +import Props from '@ionic-internal/component-api/v7/breadcrumbs/props.md'; +import Events from '@ionic-internal/component-api/v7/breadcrumbs/events.md'; +import Methods from '@ionic-internal/component-api/v7/breadcrumbs/methods.md'; +import Parts from '@ionic-internal/component-api/v7/breadcrumbs/parts.md'; +import CustomProps from '@ionic-internal/component-api/v7/breadcrumbs/custom-props.md'; +import Slots from '@ionic-internal/component-api/v7/breadcrumbs/slots.md'; + + + +import EncapsulationPill from '@components/page/api/EncapsulationPill'; + + + +Breadcrumbsは、ユーザーがアプリやサイトのどこにいるのかを示すために使用されるナビゲーションアイテムです。大規模なサイトや、階層的に配置されたページを持つアプリで使用する必要があります。Breadcrumbsは、表示可能な最大数に応じて折りたたむことができ、折りたたんだインジケータをクリックすると、詳細情報を示すポップオーバーが表示され、折りたたんだBreadcrumbを展開することができます。 + +## 基本的な使い方 + +import Basic from '@site/static/usage/v7/breadcrumbs/basic/index.md'; + + + +## Using Icons + +### アイテムでのアイコン + +import IconsOnItems from '@site/static/usage/v7/breadcrumbs/icons/icons-on-items/index.md'; + + + +### Custom Separators + +import CustomSeparators from '@site/static/usage/v7/breadcrumbs/icons/custom-separators/index.md'; + + + +## Collapsing Items + +### Max Items + +`maxItems` の値よりも多くのアイテムがある場合、breadcrumbsは折りたたまれます。デフォルトでは、最初と最後のアイテムのみが表示されます。 + +import MaxItems from '@site/static/usage/v7/breadcrumbs/collapsing-items/max-items/index.md'; + + + +### Items Before or After Collapse + +アイテムが折りたたまれた後、表示するアイテムの数は `itemsBeforeCollapse` と `itemsAfterCollapse` プロパティで制御することができます。 + +import ItemsBeforeAfter from '@site/static/usage/v7/breadcrumbs/collapsing-items/items-before-after/index.md'; + + + +### Collapsed Indicator Click -- Expand Breadcrumbs + +インジケータをクリックすると、`ionCollapsedClick` イベントが発生します。これは、例えば、breadcrumbsを展開するために使うことができます。 + +import ExpandOnClick from '@site/static/usage/v7/breadcrumbs/collapsing-items/expand-on-click/index.md'; + + + +### Collapsed Indicator Click -- Present Popover + +また、`ionCollapsedClick` イベントは、隠されたパンくずを表示するオーバーレイ(この場合は `ion-popover` )を提示するために使用することができます。 + +import PopoverOnClick from '@site/static/usage/v7/breadcrumbs/collapsing-items/popover-on-click/index.md'; + + + +## テーマ + +### Colors + +import Colors from '@site/static/usage/v7/breadcrumbs/theming/colors/index.md'; + + + +## CSSカスタムプロパティ + +import CSSProps from '@site/static/usage/v7/breadcrumbs/theming/css-properties/index.md'; + + + + +## プロパティ + + +## イベント + + +## メソッド + + +## CSS Shadow Parts + + +## CSSカスタムプロパティ + + +## Slots + diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/api/button.md b/i18n/ja/docusaurus-plugin-content-docs/current/api/button.md new file mode 100644 index 00000000000..50f66a388b4 --- /dev/null +++ b/i18n/ja/docusaurus-plugin-content-docs/current/api/button.md @@ -0,0 +1,115 @@ +--- +title: "ion-button" +--- +import Props from '@ionic-internal/component-api/v7/button/props.md'; +import Events from '@ionic-internal/component-api/v7/button/events.md'; +import Methods from '@ionic-internal/component-api/v7/button/methods.md'; +import Parts from '@ionic-internal/component-api/v7/button/parts.md'; +import CustomProps from '@ionic-internal/component-api/v7/button/custom-props.md'; +import Slots from '@ionic-internal/component-api/v7/button/slots.md'; + + + ion-button: Style Buttons with Custom CSS Properties + + + +import EncapsulationPill from '@components/page/api/EncapsulationPill'; + + + +Buttonはクリック可能な要素を提供し、Form内や、標準の単機能なButton機能を必要とする任意の場所で使用できます。text、icon、またはその両方を表示できます。Buttonは、いくつかの属性を利用して特定の外観になるようにスタイル設定できます。 + +## 基本的な使い方 + +import Basic from '@site/static/usage/v7/button/basic/index.md'; + + + +## Expand + +このプロパティでは、ボタンの幅を指定することができます。デフォルトでは、ボタンは `display: inline-block` を持ちますが、このプロパティを設定すると、ボタンは `display: block` を持つ全角要素に変更されます。 + +import Expand from '@site/static/usage/v7/button/expand/index.md'; + + + +## Shape + +このプロパティは、ボタンの形状を指定することができます。デフォルトでは、ボタンは小さなボーダー半径を持つ長方形ですが、これを `"round"` に設定すると、ボタンは丸みを帯びた要素に変更されます。 + +import Shape from '@site/static/usage/v7/button/shape/index.md'; + + + + +## Fill + +この属性は、Buttonのbackgroundとborder-colorを設定します。デフォルトでは、Buttonはtoolbar内にない限り、backgroundは塗りつぶされます。toolbar内にある場合は、backgroundは透明になります。 + +import Fill from '@site/static/usage/v7/button/fill/index.md'; + + + +## Size + +この属性は、Buttonのサイズを指定します。この属性を設定すると、Buttonの高さとpaddingが変更されます + +import Size from '@site/static/usage/v7/button/size/index.md'; + + + +## Icons + +import Icons from '@site/static/usage/v7/button/icons/index.md'; + + + +## テーマ + +### Colors + +import Colors from '@site/static/usage/v7/button/theming/colors/index.md'; + + + +## CSSカスタムプロパティ + +import CSSProps from '@site/static/usage/v7/button/theming/css-properties/index.md'; + + + +## アクセシビリティ + +ボタンはアクセスしやすいように作られていますが、その内容によっては調整が必要な場合があります。ボタンコンポーネントは、ネイティブの[button element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button)をレンダリングし、ネイティブのボタンが提供する機能を利用できるようにします。 + +### Overflowing Text Content + +ボタンのテキスト・コンテンツがコンテナからはみ出す場合が多々あります。このような場合、すべてのテキストがまだ読めるように、ボタンの内側にテキストを折り返すことをお勧めします。ボタンコンポーネントは、テキストの余分な行を収容するために、その高さを自動的に調整します。 + +テキストが長すぎて収まらない場合、ボタンテキストは自動的に次の行に折り返されません。テキストを折り返すには、`ion-text-wrap`クラスを追加して、`white-space`プロパティを`"normal"`に設定します。これは将来のメジャーリリースでデフォルトになる予定である。 + +:::info +max-width`スタイルは、デモのためだけに下のボタンに設定されています。テキストラッピングは動的なボタン幅で動作します。 +::: + +import TextWrapping from '@site/static/usage/v7/button/text-wrapping/index.md'; + + + +## プロパティ + + +## イベント + + +## メソッド + + +## CSS Shadow Parts + + +## CSSカスタムプロパティ + + +## Slots + diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/api/buttons.md b/i18n/ja/docusaurus-plugin-content-docs/current/api/buttons.md new file mode 100644 index 00000000000..2d81136da74 --- /dev/null +++ b/i18n/ja/docusaurus-plugin-content-docs/current/api/buttons.md @@ -0,0 +1,87 @@ +--- +title: "ion-buttons" +--- +import Props from '@ionic-internal/component-api/v7/buttons/props.md'; +import Events from '@ionic-internal/component-api/v7/buttons/events.md'; +import Methods from '@ionic-internal/component-api/v7/buttons/methods.md'; +import Parts from '@ionic-internal/component-api/v7/buttons/parts.md'; +import CustomProps from '@ionic-internal/component-api/v7/buttons/custom-props.md'; +import Slots from '@ionic-internal/component-api/v7/buttons/slots.md'; + + + ion-buttons: Toolbar Element with Named Slots for Buttons + + + +import EncapsulationPill from '@components/page/api/EncapsulationPill'; + + + + +Buttonsコンポーネントは、コンテナ要素です。 [ツールバー](./toolbar) の内部で使用し、標準の[ボタン](./button)、[メニューボタン](./menu-button)、[戻るボタン](./back-button)を含むいくつかのタイプのボタンを含めることができる。 + +## 基本的な使い方 + +import Basic from '@site/static/usage/v7/buttons/basic/index.md'; + + + + +## Buttons Placement + +ツールバー内のボタンは、スロットという名前を使って配置することができます。下図は各スロットの説明です。 + +| Slot | Description | +|--------------|----------------------------------------------------------------------------------------------------------| +| `start` | Positions to the `left` of the content in LTR, and to the `right` in RTL. | +| `end` | Positions to the `right` of the content in LTR, and to the `left` in RTL. | +| `secondary` | Positions element to the `left` of the content in `ios` mode, and directly to the `right` in `md` mode. | +| `primary` | Positions element to the `right` of the content in `ios` mode, and to the far `right` in `md` mode. | + +import Placement from '@site/static/usage/v7/buttons/placement/index.md'; + + + + +## Buttonsのタイプ + +ツールバーのボタンは、デフォルトでは透明ですが、ボタンの [`fill`](./button#fill) プロパティで変更することが可能です。この例で [バックボタン](./back-button) と [メニューボタン](./menu-button) に含まれるプロパティは表示目的であり、正しい使用方法はそれぞれのドキュメントをご覧ください。 + +import Types from '@site/static/usage/v7/buttons/types/index.md'; + + + + +## Collapsible Buttons + +ボタンに `collapse` プロパティを設定すると、ヘッダーが折りたたまれたときにボタンが折りたたまれます。これは通常、[collapsible large titles](./title#collapsible-large-titles) と共に使用します。 + +:::info + +この機能はiOS modeでのみ有効です。 + +::: + + +import CollapsibleLargeTitleButtons from '@site/static/usage/v7/title/collapsible-large-title/buttons/index.md'; + + + + +## プロパティ + + +## イベント + + +## メソッド + + +## CSS Shadow Parts + + +## CSSカスタムプロパティ + + +## Slots + diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/api/card-content.md b/i18n/ja/docusaurus-plugin-content-docs/current/api/card-content.md new file mode 100644 index 00000000000..be18d82c580 --- /dev/null +++ b/i18n/ja/docusaurus-plugin-content-docs/current/api/card-content.md @@ -0,0 +1,35 @@ +--- +title: "ion-card-content" +--- +import Props from '@ionic-internal/component-api/v7/card-content/props.md'; +import Events from '@ionic-internal/component-api/v7/card-content/events.md'; +import Methods from '@ionic-internal/component-api/v7/card-content/methods.md'; +import Parts from '@ionic-internal/component-api/v7/card-content/parts.md'; +import CustomProps from '@ionic-internal/component-api/v7/card-content/custom-props.md'; +import Slots from '@ionic-internal/component-api/v7/card-content/slots.md'; + +import EncapsulationPill from '@components/page/api/EncapsulationPill'; + + +カードコンテンツは、カードの子コンポーネントで、そのコンテンツの周りにパディングを追加します。カードのテキストコンテンツは、カードコンテンツの中に配置することが推奨されます。 + +詳しくは、[Card](./card)のドキュメントを参照してください。 + + +## プロパティ + + +## イベント + + +## メソッド + + +## CSS Shadow Parts + + +## CSSカスタムプロパティ + + +## Slots + diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/api/card-header.md b/i18n/ja/docusaurus-plugin-content-docs/current/api/card-header.md new file mode 100644 index 00000000000..c3ac19f2bba --- /dev/null +++ b/i18n/ja/docusaurus-plugin-content-docs/current/api/card-header.md @@ -0,0 +1,37 @@ +--- +title: "ion-card-header" +--- +import Props from '@ionic-internal/component-api/v7/card-header/props.md'; +import Events from '@ionic-internal/component-api/v7/card-header/events.md'; +import Methods from '@ionic-internal/component-api/v7/card-header/methods.md'; +import Parts from '@ionic-internal/component-api/v7/card-header/parts.md'; +import CustomProps from '@ionic-internal/component-api/v7/card-header/custom-props.md'; +import Slots from '@ionic-internal/component-api/v7/card-header/slots.md'; + +import EncapsulationPill from '@components/page/api/EncapsulationPill'; + + + + +カードヘッダは、カードの子コンポーネントで、カードコンテンツの前に配置する必要があります。カードタイトル](./card-title)と[カードサブタイトル](./card-subtitle)を含むことができます。 + +詳しくは、[Card](./card)のドキュメントを参照してください。 + + +## プロパティ + + +## イベント + + +## メソッド + + +## CSS Shadow Parts + + +## CSSカスタムプロパティ + + +## Slots + diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/api/card-subtitle.md b/i18n/ja/docusaurus-plugin-content-docs/current/api/card-subtitle.md new file mode 100644 index 00000000000..4aab84d40d9 --- /dev/null +++ b/i18n/ja/docusaurus-plugin-content-docs/current/api/card-subtitle.md @@ -0,0 +1,37 @@ +--- +title: "ion-card-subtitle" +--- +import Props from '@ionic-internal/component-api/v7/card-subtitle/props.md'; +import Events from '@ionic-internal/component-api/v7/card-subtitle/events.md'; +import Methods from '@ionic-internal/component-api/v7/card-subtitle/methods.md'; +import Parts from '@ionic-internal/component-api/v7/card-subtitle/parts.md'; +import CustomProps from '@ionic-internal/component-api/v7/card-subtitle/custom-props.md'; +import Slots from '@ionic-internal/component-api/v7/card-subtitle/slots.md'; + +import EncapsulationPill from '@components/page/api/EncapsulationPill'; + + + + +カードサブタイトルは、[カードヘッダ](./card-header)の内側に配置されるべき、cardの子コンポーネントです。 + +詳しくは、[Card](./card)のドキュメントを参照してください。 + + +## プロパティ + + +## イベント + + +## メソッド + + +## CSS Shadow Parts + + +## CSSカスタムプロパティ + + +## Slots + diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/api/card-title.md b/i18n/ja/docusaurus-plugin-content-docs/current/api/card-title.md new file mode 100644 index 00000000000..cab2d59aae8 --- /dev/null +++ b/i18n/ja/docusaurus-plugin-content-docs/current/api/card-title.md @@ -0,0 +1,42 @@ +--- +title: "ion-card-title" +--- +import Props from '@ionic-internal/component-api/v7/card-title/props.md'; +import Events from '@ionic-internal/component-api/v7/card-title/events.md'; +import Methods from '@ionic-internal/component-api/v7/card-title/methods.md'; +import Parts from '@ionic-internal/component-api/v7/card-title/parts.md'; +import CustomProps from '@ionic-internal/component-api/v7/card-title/custom-props.md'; +import Slots from '@ionic-internal/component-api/v7/card-title/slots.md'; + +import EncapsulationPill from '@components/page/api/EncapsulationPill'; + + + ion-card-title: Ionic App Card Title Component + + + + + + +Card titleはcardの子コンポーネントで、[card header](./card-header)の内側に配置する必要があります。 + +詳しくは、[Card](./card)のドキュメントを参照してください。 + + +## プロパティ + + +## イベント + + +## メソッド + + +## CSS Shadow Parts + + +## CSSカスタムプロパティ + + +## Slots + diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/api/card.md b/i18n/ja/docusaurus-plugin-content-docs/current/api/card.md new file mode 100644 index 00000000000..e4f5148d4cd --- /dev/null +++ b/i18n/ja/docusaurus-plugin-content-docs/current/api/card.md @@ -0,0 +1,87 @@ +--- +title: "ion-card" +--- +import Props from '@ionic-internal/component-api/v7/card/props.md'; +import Events from '@ionic-internal/component-api/v7/card/events.md'; +import Methods from '@ionic-internal/component-api/v7/card/methods.md'; +import Parts from '@ionic-internal/component-api/v7/card/parts.md'; +import CustomProps from '@ionic-internal/component-api/v7/card/custom-props.md'; +import Slots from '@ionic-internal/component-api/v7/card/slots.md'; + +import EncapsulationPill from '@components/page/api/EncapsulationPill'; + + + ion-card: Card UI Components for Ionic Framework API + + + + + + +カードは、テキスト、画像、ボタン、リストなどのコンテンツを表示するためのコンテナです。 +カードは1つのコンポーネントで構成することもできますが、 +多くの場合、ヘッダー、タイトル、サブタイトル、コンテンツで構成されます。 +カードはこの構造に対応するため、いくつかのコンポーネントに分割されます。 +[カードヘッダ](./card-header)、[カードタイトル](./card-title)、[カードサブタイトル](./card-subtitle)、[カードコンテンツ](./card-content)。 + + +## 基本的な使い方 + +import Basic from '@site/static/usage/v7/card/basic/index.md'; + + + + +## Media Cards + +import Media from '@site/static/usage/v7/card/media/index.md'; + + + + +## Card Buttons + +import Buttons from '@site/static/usage/v7/card/buttons/index.md'; + + + + +## List Card + +import List from '@site/static/usage/v7/card/list/index.md'; + + + + +## テーマ + +### Colors + +import Colors from '@site/static/usage/v7/card/theming/colors/index.md'; + + + +## CSSカスタムプロパティ + +import CSSProps from '@site/static/usage/v7/card/theming/css-properties/index.md'; + + + + +## プロパティ + + +## イベント + + +## メソッド + + +## CSS Shadow Parts + + +## CSSカスタムプロパティ + + +## Slots + diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/api/checkbox.md b/i18n/ja/docusaurus-plugin-content-docs/current/api/checkbox.md new file mode 100644 index 00000000000..91651affb23 --- /dev/null +++ b/i18n/ja/docusaurus-plugin-content-docs/current/api/checkbox.md @@ -0,0 +1,139 @@ +--- +title: "ion-checkbox" +--- + +import Props from '@ionic-internal/component-api/v7/checkbox/props.md'; +import Events from '@ionic-internal/component-api/v7/checkbox/events.md'; +import Methods from '@ionic-internal/component-api/v7/checkbox/methods.md'; +import Parts from '@ionic-internal/component-api/v7/checkbox/parts.md'; +import CustomProps from '@ionic-internal/component-api/v7/checkbox/custom-props.md'; +import Slots from '@ionic-internal/component-api/v7/checkbox/slots.md'; + + + ion-checkbox: Ionic App Checkbox to Select Multiple Options + + + +import EncapsulationPill from '@components/page/api/EncapsulationPill'; + + + + +Checkboxを使用すると、一連のオプションから複数のオプションを選択できます。選択すると、チェックマークが付いた状態(checked)で表示されます。checkboxをクリックすると、 `checked` プロパティーが切り替わります。`checked` プロパティを設定して、プログラムで `checked` を切り替えることもできます。 + +## 基本的な使い方 + +import Basic from '@site/static/usage/v7/checkbox/basic/index.md'; + + + +## Label Placement + +開発者は `labelPlacement` プロパティを使用して、ラベルをコントロールに対してどのように配置するかを制御できます。このプロパティはフレックスボックスの `flex-direction` プロパティを反映しています。 + +import LabelPlacement from '@site/static/usage/v7/checkbox/label-placement/index.md'; + + + +## Alignment + +Developers can use the `alignment` property to control how the label and control are aligned on the cross axis. This property mirrors the flexbox `align-items` property. + +:::note +Stacked checkboxes can be aligned using the `alignment` property. This can be useful when the label and control need to be centered horizontally. +::: + +import Alignment from '@site/static/usage/v7/checkbox/alignment/index.md'; + + + +## Justification + +開発者は `justify` プロパティを使用して、ラベルとコントロールの行の詰め方を制御することができます。このプロパティはフレックスボックスの `justify-content` プロパティを反映しています。 + +import Justify from '@site/static/usage/v7/checkbox/justify/index.md'; + + + + +:::note +`ion-item`は、 `justify` がどのように機能するかを強調するためにデモで使用されているだけです。 `justify` が正しく機能するために必須ではありません。 +::: + +## Indeterminate Checkboxes + +import Indeterminate from '@site/static/usage/v7/checkbox/indeterminate/index.md'; + + + +## テーマ + +## CSSカスタムプロパティ + +import CSSProps from '@site/static/usage/v7/checkbox/theming/css-properties/index.md'; + + + +## Interfaces + +### CheckboxChangeEventDetail + +```typescript +interface CheckboxChangeEventDetail { + value: T; + checked: boolean; +} +``` + +### CheckboxCustomEvent + +必須ではありませんが、このコンポーネントから発行される Ionic イベントでより強く型付けを行うために、`CustomEvent` インターフェースの代わりにこのインターフェースを使用することが可能です。 + +```typescript +interface CheckboxCustomEvent extends CustomEvent { + detail: CheckboxChangeEventDetail; + target: HTMLIonCheckboxElement; +} +``` + +## レガシーなチェックボックス構文からのマイグレーション + +Ionic 7.0では、よりシンプルなチェックボックス構文が導入されました。この新しい構文は、チェックボックスの設定に必要な定型文を減らし、アクセシビリティの問題を解決し、開発者のエクスペリエンスを向上させます。 + +開発者は、この移行を一度に1つのチェックボックスずつ実行することができます。開発者はレガシー構文を使い続けることができますが、できるだけ早く移行することをお勧めします。 + +### 最新の構文の使い方 + +最新の構文を使用するには、`ion-label` を削除して、 `ion-checkbox` の中に直接ラベルを渡す必要があります。ラベルの配置は `ion-checkbox` の `labelPlacement` プロパティを使用して設定することができる。ラベルとコントロールの行の詰め方は、`ion-checkbox` の `justify` プロパティを使用して制御することができます。 + +import Migration from '@site/static/usage/v7/checkbox/migration/index.md'; + + + + +:::note +Ionic の過去のバージョンでは、`ion-checkbox` が正しく機能するために `ion-item` が必要でした。Ionic 7.0 からは、`ion-checkbox` は `ion-item` の中で、そのアイテムが `ion-list` に配置される場合にのみ使用されます。また、`ion-checkbox`が正しく機能するためには、`ion-item`はもはや必須ではありません。 +::: + +### レガシーな構文の使い方 + +Ionicは、アプリが最新のチェックボックス構文を使用しているかどうかをヒューリスティックに検出します。場合によっては、レガシーな構文を使い続けることが望ましい場合もあります。開発者は `ion-checkbox` の `legacy` プロパティを `true` に設定することで、そのチェックボックスのインスタンスがレガシー構文を使用するように強制できます。 + + +## プロパティ + + +## イベント + + +## メソッド + + +## CSS Shadow Parts + + +## CSSカスタムプロパティ + + +## Slots + diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/api/chip.md b/i18n/ja/docusaurus-plugin-content-docs/current/api/chip.md new file mode 100644 index 00000000000..586f78f2c5a --- /dev/null +++ b/i18n/ja/docusaurus-plugin-content-docs/current/api/chip.md @@ -0,0 +1,64 @@ +--- +title: "ion-chip" +--- +import Props from '@ionic-internal/component-api/v7/chip/props.md'; +import Events from '@ionic-internal/component-api/v7/chip/events.md'; +import Methods from '@ionic-internal/component-api/v7/chip/methods.md'; +import Parts from '@ionic-internal/component-api/v7/chip/parts.md'; +import CustomProps from '@ionic-internal/component-api/v7/chip/custom-props.md'; +import Slots from '@ionic-internal/component-api/v7/chip/slots.md'; + + + ion-chip: Text, Icon and Avatar for Ionic Framework Apps + + + +import EncapsulationPill from '@components/page/api/EncapsulationPill'; + + + +Chipは連絡先などを複数の小さなエンティティで表示します。 Chipにはavatars, text, や iconsなど、いくつかの異なる要素を含めることができます。 + +## 基本的な使い方 + +import Basic from '@site/static/usage/v7/chip/basic/index.md'; + + + +## Slotting Components and Icons + +import SlotExample from '@site/static/usage/v7/chip/slots/index.md'; + + + +## テーマ + +### Colors + +import Colors from '@site/static/usage/v7/chip/theming/colors/index.md'; + + + +## CSSカスタムプロパティ + +import CSSProps from '@site/static/usage/v7/chip/theming/css-properties/index.md'; + + + +## プロパティ + + +## イベント + + +## メソッド + + +## CSS Shadow Parts + + +## CSSカスタムプロパティ + + +## Slots + diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/api/col.md b/i18n/ja/docusaurus-plugin-content-docs/current/api/col.md new file mode 100644 index 00000000000..305c472f8f1 --- /dev/null +++ b/i18n/ja/docusaurus-plugin-content-docs/current/api/col.md @@ -0,0 +1,49 @@ +--- +title: "ion-col" +--- +import Props from '@ionic-internal/component-api/v7/col/props.md'; +import Events from '@ionic-internal/component-api/v7/col/events.md'; +import Methods from '@ionic-internal/component-api/v7/col/methods.md'; +import Parts from '@ionic-internal/component-api/v7/col/parts.md'; +import CustomProps from '@ionic-internal/component-api/v7/col/custom-props.md'; +import Slots from '@ionic-internal/component-api/v7/col/slots.md'; + + + ion-col: Column Component Padding and Other Properties + + + +import EncapsulationPill from '@components/page/api/EncapsulationPill'; + + + + +Columnは、[Grid](./grid) システムのセルラーコンポーネントで、[row](./row)の内部に配置されます。列は行を埋めるように拡張されます。グリッド内のすべてのコンテンツは、カラムの内部に配置する必要があります。 + +詳しくは、[grid](./grid)のドキュメントを参照してください。 + + +## Column Alignment + +デフォルトでは、カラムは行の高さ全体を埋めるように引き伸ばされます。カラムは[フレックスアイテム](https://developer.mozilla.org/en-US/docs/Glossary/Flex_Item)なので、この動作をカスタマイズするために、カラムに適用できるいくつかの[CSSクラス](/docs/layout/css-utilities#flex-item-properties) があります。 + + + + +## プロパティ + + +## イベント + + +## メソッド + + +## CSS Shadow Parts + + +## CSSカスタムプロパティ + + +## Slots + diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/api/content.md b/i18n/ja/docusaurus-plugin-content-docs/current/api/content.md new file mode 100644 index 00000000000..a437a90020f --- /dev/null +++ b/i18n/ja/docusaurus-plugin-content-docs/current/api/content.md @@ -0,0 +1,179 @@ +--- +title: "ion-content" +--- +import Props from '@ionic-internal/component-api/v7/content/props.md'; +import Events from '@ionic-internal/component-api/v7/content/events.md'; +import Methods from '@ionic-internal/component-api/v7/content/methods.md'; +import Parts from '@ionic-internal/component-api/v7/content/parts.md'; +import CustomProps from '@ionic-internal/component-api/v7/content/custom-props.md'; +import Slots from '@ionic-internal/component-api/v7/content/slots.md'; + + + ion-content: Scrollable Component for Ionic App Content + + + +import EncapsulationPill from '@components/page/api/EncapsulationPill'; + + + + +Contentコンポーネントは、スクロール可能領域を制御するいくつかの便利なメソッドを備えた、 +使いやすいコンテンツ領域を提供します。 +1つのビューに表示できるコンテンツは1つだけです。 + +Contentは、他の多くのIonicコンポーネントと同様に、 [CSS Utilities](/docs/layout/css-utilities) で提供されるグローバルスタイルを使用するか、CSSおよび使用可能な [CSS Custom Properties](#css-custom-properties) を使用して個別にスタイル設定することによって、`padding` や `margin` などを変更するようにカスタマイズできます。 + + +## 基本的な使い方 + +import Basic from '@site/static/usage/v7/content/basic/index.md'; + + + + +## Header & Footer + +コンテンツは、ページ内の唯一のトップレベル・コンポーネントとすることも、[ヘッダー](./header)、[フッター](./footer)、またはその両方と一緒に使用することも可能です。ヘッダーやフッターと一緒に使用すると、残りの高さを埋めるようにサイズが調整されます。 + +import HeaderFooter from '@site/static/usage/v7/content/header-footer/index.md'; + + + + +## Fullscreen Content + +デフォルトでは、コンテンツは [ヘッダー](./header)と [フッター](./footer)の間のスペースを埋めますが、それらの背景にまわることはありません。例えば、ヘッダーとフッターのどちらかに `translucent` プロパティを設定した場合や、ツールバーに `opacity` を設定した場合など、特定のケースでは、コンテンツをヘッダーとフッターの後ろにスクロールさせることが望まれるかもしれない。これは、コンテンツの `fullscreen` プロパティを `true` に設定することで実現することができます。 + +import Fullscreen from '@site/static/usage/v7/content/fullscreen/index.md'; + + + + +## コンテンツの固定 + +スクロール可能な領域の外側に要素を配置するには、`fixed`スロットに割り当てます。そうすることで、その要素はコンテンツの左上に[絶対位置](https://developer.mozilla.org/en-US/docs/Web/CSS/position#absolute_positioning)されます。要素の位置を変えるには、CSSの[top, right, bottom, left](https://developer.mozilla.org/en-US/docs/Web/CSS/position)プロパティを使ってスタイルを設定することができます。 + +import Fixed from '@site/static/usage/v7/content/fixed/index.md'; + + + +## スクロールメソッド + +コンテンツには [メソッド](#methods) が用意されており、これを呼び出すことでコンテンツを下、上、または特定のポイントにスクロールさせることができます。これらのメソッドには `duration` を渡すことができ、瞬時に位置を変更するのではなく、スムーズに移行することができます。 + +import ScrollMethods from '@site/static/usage/v7/content/scroll-methods/index.md'; + + + +## Scroll Events + +スクロールイベントは、パフォーマンス上、コンテンツに対してデフォルトで無効化されています。しかし、`scrollEvents` を `true` に設定することで、有効にすることができます。これは、 スクロール [イベント](#events) を聞く前に必要です。 + +import ScrollEvents from '@site/static/usage/v7/content/scroll-events/index.md'; + + + + +## テーマ + +### Colors + +import Colors from '@site/static/usage/v7/content/theming/colors/index.md'; + + + +### CSS Shadow Parts + +import CSSParts from '@site/static/usage/v7/content/theming/css-shadow-parts/index.md'; + + + +## CSSカスタムプロパティ + +import CSSProps from '@site/static/usage/v7/content/theming/css-properties/index.md'; + + + +### Safe Area Padding + +The content component will not automatically apply padding to any of its sides to account for the [safe area](/docs/theming/advanced#safe-area-padding). This is because the content component is often used in conjunction with other components that apply their own padding, such as [headers](./header) and [footers](./footer). However, if the content component is being used on its own, it may be desired to apply padding to the safe area. This can be done through CSS by using the `--ion-safe-area-(dir)` variables described in [Application Variables](../theming/advanced.md#application-variables). + +The most common use case for this is to apply padding to the top of the content to account for the status bar. This can be done by setting the `padding-top` property to the value of the `--ion-safe-area-top` variable. + +```css +ion-content::part(scroll) { + padding-top: var(--ion-safe-area-top, 0); +} +``` + +Another common use case is to apply padding to the left side of the content to account for the notch when the device is in landscape mode and the notch is on the left side. This can be done by setting the `padding-left` property to the value of the `--ion-safe-area-left` variable. + +```css +ion-content::part(scroll) { + padding-left: var(--ion-safe-area-left, 0); +} +``` + +import SafeArea from '@site/static/usage/v7/content/theming/safe-area/index.md'; + + + +## Interfaces + +### ScrollBaseDetail + +```typescript +interface ScrollBaseDetail { + isScrolling: boolean; +} +``` + +### ScrollDetail + +```typescript +interface ScrollDetail extends GestureDetail, ScrollBaseDetail { + scrollTop: number; + scrollLeft: number; +} +``` + +### ScrollBaseCustomEvent + +必須ではありませんが、`ionScrollStart` と `ionScrollEnd` イベントをより強く型付けするために、`CustomEvent` インターフェースの代わりにこのインターフェースを利用することが可能です。 + +```typescript +interface ScrollBaseCustomEvent extends CustomEvent { + detail: ScrollBaseDetail; + target: HTMLIonContentElement; +} +``` + +### ScrollCustomEvent + +必須ではありませんが、`ionScroll` イベントをより強く型付けするために、`CustomEvent` インターフェースの代わりにこのインターフェースを利用することが可能です。 + +```typescript +interface ScrollCustomEvent extends ScrollBaseCustomEvent { + detail: ScrollDetail; +} +``` + + +## プロパティ + + +## イベント + + +## メソッド + + +## CSS Shadow Parts + + +## CSSカスタムプロパティ + + +## Slots + diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/api/datetime-button.md b/i18n/ja/docusaurus-plugin-content-docs/current/api/datetime-button.md new file mode 100644 index 00000000000..ef67033e12c --- /dev/null +++ b/i18n/ja/docusaurus-plugin-content-docs/current/api/datetime-button.md @@ -0,0 +1,72 @@ +--- +title: "ion-datetime-button" +--- +import Props from '@ionic-internal/component-api/v7/datetime-button/props.md'; +import Events from '@ionic-internal/component-api/v7/datetime-button/events.md'; +import Methods from '@ionic-internal/component-api/v7/datetime-button/methods.md'; +import Parts from '@ionic-internal/component-api/v7/datetime-button/parts.md'; +import CustomProps from '@ionic-internal/component-api/v7/datetime-button/custom-props.md'; +import Slots from '@ionic-internal/component-api/v7/datetime-button/slots.md'; + + + ion-datetime-button: Ionic Input for Datetime Picker + + + +import EncapsulationPill from '@components/page/api/EncapsulationPill'; + + + +Datetimeボタンは、[Datetime](./datetime) コンポーネントとリンクし、フォーマットされた日付と時刻を表示します。また、モーダルやポップオーバーなどで日時を表示するためのボタンも用意されています。 + +## 概要 + +Datetimeボタンは、スペースに制約がある場合に使用する必要があります。このコンポーネントは、現在の日付と時刻の値を表示するボタンを表示します。ボタンがタップされると、日付や時刻のピッカーがオーバーレイで表示されます。 + +Angular、React、VueなどのJavaScriptフレームワークでDatetime Buttonを使用する場合は、 [ion-modalのkeepContentsMountedプロパティ](./modal#keepcontentsmounted) または [ion-popover](./popover#keepcontentsmounted) を使用していることを確認してください。これにより、オーバーレイがまだ表示されていない場合でも、リンクされたdatetimeインスタンスがマウントされるようになります。 + +## 基本的な使い方 + +import Basic from '@site/static/usage/v7/datetime-button/basic/index.md'; + + + +## ローカライゼーション + +`ion-datetime-button` のローカライズされたテキストは、関連する `ion-datetime` インスタンスの `locale` プロパティによって決まります。詳しくは、[Datetime Localization](./datetime#localization) を参照してください。 + +## モーダルやポップオーバーと使う + +`ion-datetime-button` は、マウントされた `ion-datetime` インスタンスと関連付ける必要があります。そのため、[Inline Modals](./modal#inline-modals-recommended) と [Inline Popovers](./popover#inline-popovers) は `keepContentsMounted` プロパティを `true` に設定して使用しなければなりません。 + + + +## プロパティ + + +## イベント + + +## メソッド + + +## CSS Shadow Parts + + +## CSS カスタムプロパティ + + +## Slots + diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/api/datetime.md b/i18n/ja/docusaurus-plugin-content-docs/current/api/datetime.md new file mode 100644 index 00000000000..d71d9fc0f78 --- /dev/null +++ b/i18n/ja/docusaurus-plugin-content-docs/current/api/datetime.md @@ -0,0 +1,480 @@ +--- +title: "ion-datetime" +--- +import Props from '@ionic-internal/component-api/v7/datetime/props.md'; +import Events from '@ionic-internal/component-api/v7/datetime/events.md'; +import Methods from '@ionic-internal/component-api/v7/datetime/methods.md'; +import Parts from '@ionic-internal/component-api/v7/datetime/parts.md'; +import CustomProps from '@ionic-internal/component-api/v7/datetime/custom-props.md'; +import Slots from '@ionic-internal/component-api/v7/datetime/slots.md'; + +import Basic from '@site/static/usage/v7/datetime/basic/index.md'; + +import MaxMin from '@site/static/usage/v7/datetime/date-constraints/max-min/index.md'; +import Values from '@site/static/usage/v7/datetime/date-constraints/values/index.md'; +import Advanced from '@site/static/usage/v7/datetime/date-constraints/advanced/index.md'; + +import CustomLocale from '@site/static/usage/v7/datetime/localization/custom-locale/index.md'; +import HourCycle from '@site/static/usage/v7/datetime/localization/hour-cycle/index.md'; +import FirstDayOfWeek from '@site/static/usage/v7/datetime/localization/first-day-of-week/index.md'; +import LocaleExtensionTags from '@site/static/usage/v7/datetime/localization/locale-extension-tags/index.md'; +import TimeLabel from '@site/static/usage/v7/datetime/localization/time-label/index.md'; + +import MonthAndYear from '@site/static/usage/v7/datetime/presentation/month-and-year/index.md'; +import Time from '@site/static/usage/v7/datetime/presentation/time/index.md'; +import Date from '@site/static/usage/v7/datetime/presentation/date/index.md'; + +import ShowingDefaultTitle from '@site/static/usage/v7/datetime/title/showing-default-title/index.md'; +import CustomizingTitle from '@site/static/usage/v7/datetime/title/customizing-title/index.md'; + +import ShowingConfirmationButtons from '@site/static/usage/v7/datetime/buttons/showing-confirmation-buttons/index.md'; +import CustomizingButtons from '@site/static/usage/v7/datetime/buttons/customizing-buttons/index.md'; +import CustomizingButtonTexts from '@site/static/usage/v7/datetime/buttons/customizing-button-texts/index.md'; + +import HighlightedDatesArray from '@site/static/usage/v7/datetime/highlightedDates/array/index.md'; +import HighlightedDatesCallback from '@site/static/usage/v7/datetime/highlightedDates/callback/index.md'; + +import MultipleDateSelection from '@site/static/usage/v7/datetime/multiple/index.md'; + +import GlobalTheming from '@site/static/usage/v7/datetime/styling/global-theming/index.md'; +import CalendarDaysStyling from '@site/static/usage/v7/datetime/styling/calendar-days/index.md'; +import WheelStyling from '@site/static/usage/v7/datetime/styling/wheel-styling/index.md'; + + + ion-datetime: Ionic API Input for Datetime Format Picker + + + +import EncapsulationPill from '@components/page/api/EncapsulationPill'; + + + +Datetimeはカレンダーとタイムホイールのインターフェイスを表示し、ユーザーが簡単に日付と時刻を選択できるようにします。Datetimeはネイティブの `datetime-local` の `input` 要素と似ていますが、Ionic FrameworkのDatetimeコンポーネントを使用すると、好みのフォーマットで日付と時刻を表示したり、datetimeの値を管理することが簡単にできます。 + +## 概要 + +これまで、JavaScriptやHTMLの入力でdatetimeの値を扱うことは、常に困難でした。 +入力でさえも、常に課題でした。 +特に、JavaScriptの `Date` オブジェクトは、datetime文字列を正しく解析したり、datetime値をフォーマットしたりするのが難しいことで有名です。 +さらに悪いことに、ブラウザやJavaScriptのバージョンによって、 +特にロケールごとに様々なdatetime文字列の解析が異なるのです。 + +Ionic Frameworkのdatetimeは、開発者が一般的な落とし穴を回避できるように設計されており、 +開発者は簡単にdatetime値を操作し、ユーザーにシンプルなdatetimeピッカーを提供し、素晴らしいユーザーエクスペリエンスを提供することができます。 + +### ISO 8601 Datetime Format: `YYYY-MM-DDTHH:mmZ` + +Ionic Frameworkでは、[ISO 8601 datetime format](https://www.w3.org/TR/NOTE-datetime) を値として使用します。 +この値は、JavaScriptの `Date` オブジェクトを使用するのではなく、単純に文字列として使用されます。 +ISO datetimeフォーマットを使用することで、 +JSONオブジェクトやデータベース内でのシリアライズやパースが容易になります。 + +以下は、 `ion-datetime` で使用できる ISO 8601 フォーマットの例です: + +| Description | Format | Datetime Value Example | +| -------------------- | ------------------------ | ------------------------------ | +| Year | `YYYY` | `1994` | +| Year and Month | `YYYY-MM` | `1994-12` | +| Complete Date | `YYYY-MM-DD` | `1994-12-15` | +| Date and Time | `YYYY-MM-DDTHH:mm` | `1994-12-15T13:47` | +| UTC Timezone | `YYYY-MM-DDTHH:mm:ssZ` | `1994-12-15T13:47:20Z` | +| Timezone Offset | `YYYY-MM-DDTHH:mm:ssTZD` | `1994-12-15T13:47:20+05:00` | +| Hour and Minute | `HH:mm` | `13:47` | + +年号は常に4桁、ミリ秒は(加算される場合は)常に3桁、その他は常に2桁であることに注意してください。 +ミリ秒は3桁、その他は2桁である。 +ですから、1月を表す数字には 1月を表す数字には常に先頭のゼロ、例えば`01`が付きます。 +また、時刻は常に24時間表示で、 +12時間表示の時計では「00」は「午前12時」、「13」は「午後1時」、「23」は「午後3時」を意味します。 + +:::note +秒、ミリ秒、タイムゾーンは ISO 8601 datetime フォーマットで指定できますが、 `ion-datetime` は秒、ミリ秒、タイムゾーンを選択するためのインターフェイスを提供しません。秒、ミリ秒、タイムゾーンの値を指定しても無視されます。 +::: + +## 基本的な使い方 + + + +## 日付ボタンと使う + +モーダルやポップオーバーなどのオーバーレイで日付時刻を表示する必要がある場合は、 [ion-datetime-button](./datetime-button) を使用することをお勧めします。スペースに制約がある場合は、 `ion-datetime-button` を使用する必要があります。このコンポーネントは、現在の日付と時刻の値を表示するボタンを表示します。ボタンがタップされると、日付と時刻のピッカーがオーバーレイで表示されます。 + +## 非同期に値を設定する + +すでにdatetimeが作成された後にプログラムで`value`が更新されると、datetimeは自動的に新しい日付にジャンプします。しかし、ユーザーがdatetimeを操作しているときに、この方法で`value`を更新することは避けることをお勧めします。例えば、datetimeの`value`が非同期処理で読み込まれる場合、値の更新が終わるまでCSSでdatetimeを非表示にすることをお勧めします。 + +## 日付コンテナ + +### 日付の最小値と最大値 + +日付の最小値と最大値をカスタマイズするには、 `min` と `max` コンポーネントプロパティを使用します。上の表にあるのと同じ IS0 8601 フォーマットに従って、各コンポーネントはユーザーが選択できる日付を制限することができます。 + +以下の例では、日付の選択を2022年3月から2022年5月のみに制限しています。 + + + +### 特定の値を選択する + +`min` と `max` プロパティでは、日付の選択をある範囲に制限することができますが、 `monthValues`, `dayValues`, `yearValues`, `hourValues`, `minuteValues` プロパティでは、ユーザーが選択できる特定の日や時刻を選択することが可能です。 + +次の例では、15分単位で分を選択することができます。また、日付を5刻みで選択することができます。 + + + +### 高度な日付制限 + +`isDateEnabled` プロパティを使用すると、開発者は `ion-datetime` をカスタマイズして、ISO 8601 の日付文字列を使用して、特定の日、日付の範囲、週末、または任意のカスタムルールを無効にすることができる。 +isDateEnabled` プロパティは、日付が有効かどうかを示すブール値を返す関数を受け付ける。この関数は、レンダリングされた各日付、前月、当月、翌月に対して呼び出されます。カスタムの実装では、ジャンクを避けるためにパフォーマンスを最適化する必要があります。 + +次の例では、週末の日付をすべて無効にする方法を示しています。より高度な日付操作を行うには、 `date-fns` のような日付ユーティリティを使用することをお勧めします。 + + + +## ローカライゼーション + +Ionic Frameworkでは、[Intl.DatetimeFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DatetimeFormat) Web APIを利用して、ユーザーの端末に設定されている言語や地域に応じて、月名と曜日名を自動的にローカライズすることが可能です。 + +### カスタムロケール + +特定のロケールが必要な場合、 `locale` プロパティを使用して設定することができます。ロケールは、表示される言語と日付・時刻のフォーマットの両方を制御します。 + +次の例では、ロケールをスペイン語(Spanish)に設定する方法を示しています。 + + + +:::note +時刻の表記は、自動的にローカライズされません。詳しくは [Time Label](#time-label) を参照してください。 +::: + +### 時間サイクル + +`ion-datetime` は、デフォルトで `locale` プロパティで指定された時間サイクルを使用します。例えば、 `locale` が `en-US` に設定されている場合、 `ion-datetime` は12時間のサイクルを使用します。 + +時間サイクルには4つのタイプがあります。 + +| Hour cycle type | Description | +| --------------- | ------------------------------------------------------------ | +| `'h12'` | Hour system using 1–12; corresponds to 'h' in patterns. The 12 hour clock, with midnight starting at 12:00 am. | +| `'h23'` | Hour system using 0–23; corresponds to 'H' in patterns. The 24 hour clock, with midnight starting at 0:00. | +| `'h11'` | Hour system using 0–11; corresponds to 'K' in patterns. The 12 hour clock, with midnight starting at 0:00 am. | +| `'h24'` | Hour system using 1–24; corresponds to 'k' in pattern. The 24 hour clock, with midnight starting at 24:00. | + +:::note + ソース: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Locale/hourCycle +::: + + +どの時間のサイクルを使用するか、もっとコントロールする必要があるシナリオがあるかもしれません。このような場合には、 `hourCycle` プロパティが役に立ちます。 + +次の例では、 `hourCycle` プロパティを使用して、ロケールが `en-GB` であるにもかかわらず、 `ion-datetime` に12時間周期を使用するように強制することができます。 + + + +### 週初めの日 + +`ion-datetime`の場合、週初めの曜日はデフォルトで日曜日です。2022年現在、Ionicがデバイスのロケールに基づいて自動的に週の最初の曜日を決定するためのブラウザAPIはありませんが、これに関する作業は進行中です(参照: [TC39 GitHub](https://github.com/tc39/ecma402/issues/6) ). + + + +### 時刻表記 + +時刻表記は自動的にローカライズされるわけではありません。幸いなことに、Ionicでは `time-label` スロットで簡単にカスタムのローカライズを提供することができます。 + + + +### ロケールエクステンションタグ + +`ion-datetime` は、 `Intl.Locale` API の一部として [locale extension tags](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Locale) もサポートしています。これらのタグを使用すると、ロケールに関する情報をロケール文字列自体にエンコードすることができます。開発者は、アプリの中で [Intl.Locale API](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Locale) を使っている場合、拡張タグのアプローチを使うことを好むかもしれません。 + +たとえば、 `en-GB` ロケールで 12 時間周期を使用したい場合は、 `locale` と `hourCycle` の両方のプロパティを使用するのではなく、拡張タグを使用します。 + + + +:::note +アプリで使用する前に、 `Intl.Locale` の [Browser Compatibility Chart](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Locale#browser_compatibility) を必ず確認してください。 +::: + +## プレゼンテーション + +デフォルトでは、 `ion-datetime` は日付と時刻の両方を選択することができる。さらに、ユーザは特定の月、年、時間、分を選択することができます。 + +ユースケースによっては、日付だけを選択したり、時間だけを選択したりすることもできます。 `presentation` プロパティでは、表示するピッカーとその順番を指定することができます。例えば、 `date-time` を設定すると、カレンダーピッカーがタイムピッカーよりも先に表示されます。 `time-date` を設定すると、カレンダーピッカーはtimeピッカーの後に表示されます。 + +### 月と年の選択 + +月と年の選択は、 `presentation` プロパティに `month-year` , `year-month` , `month` , または `year` を渡すことで行うことができます。 + +この例では、 `month-year` を設定した datetime を示しています。 + + + +### 時刻の選択 + +時刻の選択は、 `presentation` プロパティに `date-time`, `time-date`, `time` を渡すことで行うことができます。 + +この例では、`time`の設定で datetime を表示しています。 + +