mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2026-03-13 10:22:08 +08:00
chore(): sync with main:
This commit is contained in:
@@ -3,6 +3,19 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [6.3.0 Manganese](https://github.com/ionic-team/ionic/compare/v6.2.9...v6.3.0) (2022-10-05)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **angular:** use standalone components with routing ([#25589](https://github.com/ionic-team/ionic/issues/25589)) ([3c84d48](https://github.com/ionic-team/ionic/commit/3c84d48cfa87810896364cb7ca16efcbdd7e8b07)), closes [#25404](https://github.com/ionic-team/ionic/issues/25404)
|
||||
* **button:** submit from outside of form ([#25913](https://github.com/ionic-team/ionic/issues/25913)) ([b139838](https://github.com/ionic-team/ionic/commit/b13983848c9ea7387062953412eaae744c001ec7)), closes [#21194](https://github.com/ionic-team/ionic/issues/21194)
|
||||
* **datetime:** add header text to multiple selection; improve header consistency between modes ([#25817](https://github.com/ionic-team/ionic/issues/25817)) ([8a1b3c5](https://github.com/ionic-team/ionic/commit/8a1b3c5f300a1ec953d406b65601f84fa49aa807))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [6.2.9](https://github.com/ionic-team/ionic/compare/v6.2.8...v6.2.9) (2022-09-28)
|
||||
|
||||
**Note:** Version bump only for package @ionic/angular
|
||||
|
||||
18
angular/package-lock.json
generated
18
angular/package-lock.json
generated
@@ -1,15 +1,15 @@
|
||||
{
|
||||
"name": "@ionic/angular",
|
||||
"version": "6.2.9",
|
||||
"version": "6.3.0",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@ionic/angular",
|
||||
"version": "6.2.9",
|
||||
"version": "6.3.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@ionic/core": "^6.2.9",
|
||||
"@ionic/core": "^6.3.0",
|
||||
"jsonc-parser": "^3.0.0",
|
||||
"tslib": "^2.0.0"
|
||||
},
|
||||
@@ -1023,9 +1023,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@ionic/core": {
|
||||
"version": "6.2.9",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-6.2.9.tgz",
|
||||
"integrity": "sha512-d2KBXYUKBND2AD8aMgash3O/t04IDc/DHHMshcOydfNJ5qqAxwJYzZR7hs96UknCcIlhHk1pb5C29epkv7gOcQ==",
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-6.3.0.tgz",
|
||||
"integrity": "sha512-6MR0hOdIM6sQyZyXez3/jWAnHScrZKaQxzGT2XiXXIpBrKztNdeAhqDLXoxbDU1PLyDnXXPWBzT6xZ698gG67g==",
|
||||
"dependencies": {
|
||||
"@stencil/core": "^2.18.0",
|
||||
"ionicons": "^6.0.3",
|
||||
@@ -7951,9 +7951,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"@ionic/core": {
|
||||
"version": "6.2.9",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-6.2.9.tgz",
|
||||
"integrity": "sha512-d2KBXYUKBND2AD8aMgash3O/t04IDc/DHHMshcOydfNJ5qqAxwJYzZR7hs96UknCcIlhHk1pb5C29epkv7gOcQ==",
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-6.3.0.tgz",
|
||||
"integrity": "sha512-6MR0hOdIM6sQyZyXez3/jWAnHScrZKaQxzGT2XiXXIpBrKztNdeAhqDLXoxbDU1PLyDnXXPWBzT6xZ698gG67g==",
|
||||
"requires": {
|
||||
"@stencil/core": "^2.18.0",
|
||||
"ionicons": "^6.0.3",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ionic/angular",
|
||||
"version": "6.2.9",
|
||||
"version": "6.3.0",
|
||||
"description": "Angular specific wrappers for @ionic/core",
|
||||
"keywords": [
|
||||
"ionic",
|
||||
@@ -46,7 +46,7 @@
|
||||
"validate": "npm i && npm run lint && npm run test && npm run build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ionic/core": "^6.2.9",
|
||||
"@ionic/core": "^6.3.0",
|
||||
"jsonc-parser": "^3.0.0",
|
||||
"tslib": "^2.0.0"
|
||||
},
|
||||
|
||||
@@ -30,5 +30,5 @@ export abstract class EnvironmentInjector implements Injector {
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
abstract onDestroy(callback: () => void): void;
|
||||
abstract onDestroy?(callback: () => void): void;
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
Optional,
|
||||
Output,
|
||||
SkipSelf,
|
||||
Input,
|
||||
} from '@angular/core';
|
||||
import { OutletContext, Router, ActivatedRoute, ChildrenOutletContexts, PRIMARY_OUTLET } from '@angular/router';
|
||||
import { componentOnReady } from '@ionic/core';
|
||||
@@ -55,6 +56,16 @@ export class IonRouterOutlet implements OnDestroy, OnInit {
|
||||
|
||||
tabsPrefix: string | undefined;
|
||||
|
||||
/**
|
||||
* @experimental
|
||||
*
|
||||
* The `EnvironmentInjector` provider instance from the parent component.
|
||||
* Required for using standalone components with `ion-router-outlet`.
|
||||
*
|
||||
* Will be deprecated and removed when Angular 13 support is dropped.
|
||||
*/
|
||||
@Input() environmentInjector: EnvironmentInjector;
|
||||
|
||||
@Output() stackEvents = new EventEmitter<any>();
|
||||
// eslint-disable-next-line @angular-eslint/no-output-rename
|
||||
@Output('activate') activateEvents = new EventEmitter<any>();
|
||||
@@ -88,7 +99,6 @@ export class IonRouterOutlet implements OnDestroy, OnInit {
|
||||
@Optional() @Attribute('tabs') tabs: string,
|
||||
private config: Config,
|
||||
private navCtrl: NavController,
|
||||
@Optional() private environmentInjector: EnvironmentInjector,
|
||||
@Optional() private componentFactoryResolver: ComponentFactoryResolver,
|
||||
commonLocation: Location,
|
||||
elementRef: ElementRef,
|
||||
@@ -234,20 +244,24 @@ export class IonRouterOutlet implements OnDestroy, OnInit {
|
||||
} else {
|
||||
const snapshot = (activatedRoute as any)._futureSnapshot;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
const component = snapshot.routeConfig!.component as any;
|
||||
|
||||
/**
|
||||
* Angular 14 introduces a new `loadComponent` property to the route config,
|
||||
* that assigns the component to load to the `component` property of
|
||||
* the route snapshot. We can check for the presence of this property
|
||||
* to determine if the route is using standalone components.
|
||||
*
|
||||
* TODO: FW-1631: Remove this check when supporting standalone components
|
||||
* Angular 14 introduces a new `loadComponent` property to the route config.
|
||||
* This function will assign a `component` property to the route snapshot.
|
||||
* We check for the presence of this property to determine if the route is
|
||||
* using standalone components.
|
||||
*/
|
||||
if (component == null && snapshot.component) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
if (snapshot.routeConfig!.component == null && this.environmentInjector == null) {
|
||||
console.warn(
|
||||
'[Ionic Warning]: Standalone components are not currently supported with ion-router-outlet. You can track this feature request at https://github.com/ionic-team/ionic-framework/issues/25404'
|
||||
'[Ionic Warning]: You must supply an environmentInjector to use standalone components with routing:\n\n' +
|
||||
'In your component class, add:\n\n' +
|
||||
` import { EnvironmentInjector } from '@angular/core';\n` +
|
||||
' constructor(public environmentInjector: EnvironmentInjector) {}\n' +
|
||||
'\n' +
|
||||
'In your router outlet template, add:\n\n' +
|
||||
' <ion-router-outlet [environmentInjector]="environmentInjector"></ion-router-outlet>\n\n' +
|
||||
'Alternatively, if you are routing within ion-tabs:\n\n' +
|
||||
' <ion-tabs [environmentInjector]="environmentInjector"></ion-tabs>'
|
||||
);
|
||||
return;
|
||||
}
|
||||
@@ -267,6 +281,9 @@ export class IonRouterOutlet implements OnDestroy, OnInit {
|
||||
*/
|
||||
resolverOrInjector = resolverOrInjector || this.componentFactoryResolver;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
const component = snapshot.routeConfig!.component ?? snapshot.component;
|
||||
|
||||
if (resolverOrInjector && isComponentFactoryResolver(resolverOrInjector)) {
|
||||
// Backwards compatibility for Angular 13 and lower
|
||||
const factory = resolverOrInjector.resolveComponentFactory(component);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Component, ContentChild, EventEmitter, HostListener, Output, ViewChild } from '@angular/core';
|
||||
import { Component, ContentChild, EventEmitter, HostListener, Input, Output, ViewChild } from '@angular/core';
|
||||
|
||||
import { EnvironmentInjector } from '../../di/r3_injector';
|
||||
import { NavController } from '../../providers/nav-controller';
|
||||
import { IonTabBar } from '../proxies';
|
||||
|
||||
@@ -10,7 +11,12 @@ import { StackEvent } from './stack-utils';
|
||||
selector: 'ion-tabs',
|
||||
template: ` <ng-content select="[slot=top]"></ng-content>
|
||||
<div class="tabs-inner">
|
||||
<ion-router-outlet #outlet tabs="true" (stackEvents)="onPageSelected($event)"></ion-router-outlet>
|
||||
<ion-router-outlet
|
||||
#outlet
|
||||
tabs="true"
|
||||
[environmentInjector]="environmentInjector"
|
||||
(stackEvents)="onPageSelected($event)"
|
||||
></ion-router-outlet>
|
||||
</div>
|
||||
<ng-content></ng-content>`,
|
||||
styles: [
|
||||
@@ -46,6 +52,16 @@ export class IonTabs {
|
||||
@ViewChild('outlet', { read: IonRouterOutlet, static: false }) outlet: IonRouterOutlet;
|
||||
@ContentChild(IonTabBar, { static: false }) tabBar: IonTabBar | undefined;
|
||||
|
||||
/**
|
||||
* @experimental
|
||||
*
|
||||
* The `EnvironmentInjector` provider instance from the parent component.
|
||||
* Required for using standalone components with `ion-router-outlet`.
|
||||
*
|
||||
* Will be deprecated and removed when Angular 13 support is dropped.
|
||||
*/
|
||||
@Input() environmentInjector: EnvironmentInjector;
|
||||
|
||||
@Output() ionTabsWillChange = new EventEmitter<{ tab: string }>();
|
||||
@Output() ionTabsDidChange = new EventEmitter<{ tab: string }>();
|
||||
|
||||
|
||||
@@ -242,13 +242,13 @@ export declare interface IonButton extends Components.IonButton {
|
||||
|
||||
@ProxyCmp({
|
||||
defineCustomElementFn: undefined,
|
||||
inputs: ['buttonType', 'color', 'disabled', 'download', 'expand', 'fill', 'href', 'mode', 'rel', 'routerAnimation', 'routerDirection', 'shape', 'size', 'strong', 'target', 'type']
|
||||
inputs: ['buttonType', 'color', 'disabled', 'download', 'expand', 'fill', 'form', 'href', 'mode', 'rel', 'routerAnimation', 'routerDirection', 'shape', 'size', 'strong', 'target', 'type']
|
||||
})
|
||||
@Component({
|
||||
selector: 'ion-button',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
template: '<ng-content></ng-content>',
|
||||
inputs: ['buttonType', 'color', 'disabled', 'download', 'expand', 'fill', 'href', 'mode', 'rel', 'routerAnimation', 'routerDirection', 'shape', 'size', 'strong', 'target', 'type']
|
||||
inputs: ['buttonType', 'color', 'disabled', 'download', 'expand', 'fill', 'form', 'href', 'mode', 'rel', 'routerAnimation', 'routerDirection', 'shape', 'size', 'strong', 'target', 'type']
|
||||
})
|
||||
export class IonButton {
|
||||
protected el: HTMLElement;
|
||||
@@ -530,14 +530,14 @@ export declare interface IonDatetime extends Components.IonDatetime {
|
||||
|
||||
@ProxyCmp({
|
||||
defineCustomElementFn: undefined,
|
||||
inputs: ['cancelText', 'clearText', 'color', 'dayValues', 'disabled', 'doneText', 'firstDayOfWeek', 'hourCycle', 'hourValues', 'isDateEnabled', 'locale', 'max', 'min', 'minuteValues', 'mode', 'monthValues', 'multiple', 'name', 'preferWheel', 'presentation', 'readonly', 'showClearButton', 'showDefaultButtons', 'showDefaultTimeLabel', 'showDefaultTitle', 'size', 'value', 'yearValues'],
|
||||
inputs: ['cancelText', 'clearText', 'color', 'dayValues', 'disabled', 'doneText', 'firstDayOfWeek', 'hourCycle', 'hourValues', 'isDateEnabled', 'locale', 'max', 'min', 'minuteValues', 'mode', 'monthValues', 'multiple', 'name', 'preferWheel', 'presentation', 'readonly', 'showClearButton', 'showDefaultButtons', 'showDefaultTimeLabel', 'showDefaultTitle', 'size', 'titleSelectedDatesFormatter', 'value', 'yearValues'],
|
||||
methods: ['confirm', 'reset', 'cancel']
|
||||
})
|
||||
@Component({
|
||||
selector: 'ion-datetime',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
template: '<ng-content></ng-content>',
|
||||
inputs: ['cancelText', 'clearText', 'color', 'dayValues', 'disabled', 'doneText', 'firstDayOfWeek', 'hourCycle', 'hourValues', 'isDateEnabled', 'locale', 'max', 'min', 'minuteValues', 'mode', 'monthValues', 'multiple', 'name', 'preferWheel', 'presentation', 'readonly', 'showClearButton', 'showDefaultButtons', 'showDefaultTimeLabel', 'showDefaultTitle', 'size', 'value', 'yearValues']
|
||||
inputs: ['cancelText', 'clearText', 'color', 'dayValues', 'disabled', 'doneText', 'firstDayOfWeek', 'hourCycle', 'hourValues', 'isDateEnabled', 'locale', 'max', 'min', 'minuteValues', 'mode', 'monthValues', 'multiple', 'name', 'preferWheel', 'presentation', 'readonly', 'showClearButton', 'showDefaultButtons', 'showDefaultTimeLabel', 'showDefaultTitle', 'size', 'titleSelectedDatesFormatter', 'value', 'yearValues']
|
||||
})
|
||||
export class IonDatetime {
|
||||
protected el: HTMLElement;
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
describe('Routing with Standalone Components', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('/version-test/standalone');
|
||||
});
|
||||
|
||||
it('should render the component', () => {
|
||||
cy.get('ion-content').contains('This is a standalone component rendered from a route.');
|
||||
});
|
||||
});
|
||||
3
angular/test/apps/ng14/src/app/app.component.html
Normal file
3
angular/test/apps/ng14/src/app/app.component.html
Normal file
@@ -0,0 +1,3 @@
|
||||
<ion-app>
|
||||
<ion-router-outlet [environmentInjector]="environmentInjector"></ion-router-outlet>
|
||||
</ion-app>
|
||||
11
angular/test/apps/ng14/src/app/app.component.ts
Normal file
11
angular/test/apps/ng14/src/app/app.component.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { Component, EnvironmentInjector } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
templateUrl: './app.component.html',
|
||||
styleUrls: ['./app.component.css']
|
||||
})
|
||||
export class AppComponent {
|
||||
|
||||
constructor(public environmentInjector: EnvironmentInjector) { }
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
<ion-content>
|
||||
<p>This is a standalone component rendered from a route.</p>
|
||||
<ion-button routerLink="/">Return home</ion-button>
|
||||
</ion-content>
|
||||
@@ -0,0 +1,12 @@
|
||||
import { Component } from "@angular/core";
|
||||
import { RouterModule } from "@angular/router";
|
||||
|
||||
import { IonicModule } from '@ionic/angular';
|
||||
|
||||
@Component({
|
||||
selector: 'app-standalone',
|
||||
templateUrl: './standalone.component.html',
|
||||
standalone: true,
|
||||
imports: [IonicModule, RouterModule]
|
||||
})
|
||||
export class StandaloneComponent { }
|
||||
@@ -0,0 +1,15 @@
|
||||
import { NgModule } from "@angular/core";
|
||||
import { RouterModule } from "@angular/router";
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
RouterModule.forChild([
|
||||
{
|
||||
path: 'standalone',
|
||||
loadComponent: () => import('./standalone/standalone.component').then(m => m.StandaloneComponent)
|
||||
}
|
||||
])
|
||||
],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class VersionTestRoutingModule { }
|
||||
@@ -1,7 +0,0 @@
|
||||
# Ionic Angular Test App
|
||||
|
||||
```
|
||||
npm install
|
||||
npm run sync:build
|
||||
npm start
|
||||
```
|
||||
@@ -1,6 +1,6 @@
|
||||
import { NgModule } from "@angular/core";
|
||||
import { RouterModule } from "@angular/router";
|
||||
import { VersionTestComponent } from ".";
|
||||
import { VersionTestComponent } from "./version-test.component";
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
|
||||
21
angular/test/base/tsconfig.json
Normal file
21
angular/test/base/tsconfig.json
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"compileOnSave": false,
|
||||
"compilerOptions": {
|
||||
"importHelpers": true,
|
||||
"outDir": "./dist/out-tsc",
|
||||
"sourceMap": true,
|
||||
"declaration": false,
|
||||
"moduleResolution": "node",
|
||||
"module": "es2020",
|
||||
"target": "es2020",
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"typeRoots": ["node_modules/@types"],
|
||||
"lib": ["es2018", "dom"],
|
||||
"plugins": [
|
||||
{
|
||||
"name": "typescript-eslint-language-service"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -31,3 +31,5 @@ cp -R $FULL_BASE_DIR $BUILD_APP_DIR
|
||||
# Then we can copy the specific app which
|
||||
# will override any files in the base application.
|
||||
cp -R $FULL_APP_DIR $BUILD_APP_DIR
|
||||
|
||||
echo "Copied test app files for ${APP_DIR}"
|
||||
|
||||
35
angular/test/sync-e2e.sh
Executable file
35
angular/test/sync-e2e.sh
Executable file
@@ -0,0 +1,35 @@
|
||||
#!/bin/bash
|
||||
|
||||
# The directory where the source
|
||||
# for each specific application is.
|
||||
APPS_DIR="apps"
|
||||
|
||||
# The directory where the
|
||||
# base application logic is
|
||||
BASE_DIR="base"
|
||||
BUILD_DIR="build"
|
||||
|
||||
# The specific application
|
||||
# we are building
|
||||
APP_DIR="${1}"
|
||||
|
||||
# The full path to the specific application.
|
||||
FULL_APP_DIR="${APPS_DIR}/${APP_DIR}/e2e"
|
||||
|
||||
# The full path to the base application.
|
||||
FULL_BASE_DIR="${BASE_DIR}/e2e"
|
||||
|
||||
# The full path to the built application.
|
||||
BUILD_APP_DIR="${BUILD_DIR}/${APP_DIR}/"
|
||||
|
||||
# Make the build directory if it does not already exist.
|
||||
mkdir -p $BUILD_DIR
|
||||
|
||||
# First we need to copy the base application
|
||||
cp -R $FULL_BASE_DIR $BUILD_APP_DIR
|
||||
|
||||
# Then we can copy the specific app which
|
||||
# will override any files in the base application.
|
||||
cp -R $FULL_APP_DIR $BUILD_APP_DIR
|
||||
|
||||
echo "Synced e2e tests for ${APP_DIR}"
|
||||
Reference in New Issue
Block a user