mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2026-03-13 10:22:08 +08:00
Compare commits
291 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7f4d3a36df | ||
|
|
a633db1688 | ||
|
|
3ec9607281 | ||
|
|
84e306c1a6 | ||
|
|
713ea8adaa | ||
|
|
8f7853c5e9 | ||
|
|
f94300cbb3 | ||
|
|
3a22105375 | ||
|
|
6bbdb80871 | ||
|
|
7cd68b59fc | ||
|
|
d237e808c2 | ||
|
|
e043ea9dae | ||
|
|
f9579bcd1d | ||
|
|
23f327ecb6 | ||
|
|
3e1dfc657b | ||
|
|
32bb1f7230 | ||
|
|
48352533ff | ||
|
|
e3a5d1f93a | ||
|
|
f08ac68e0b | ||
|
|
7951289460 | ||
|
|
9f32d0edd7 | ||
|
|
27a68b3f7f | ||
|
|
962783bfba | ||
|
|
e82648bda2 | ||
|
|
9b85e13493 | ||
|
|
462cee5b2e | ||
|
|
d792560447 | ||
|
|
7272d481bf | ||
|
|
c83edd9329 | ||
|
|
a869ca0bba | ||
|
|
c2348f71a5 | ||
|
|
67ffe2f9cc | ||
|
|
2e02dc7319 | ||
|
|
b7761fe353 | ||
|
|
00891119f7 | ||
|
|
c91819c94f | ||
|
|
3ef6ecf422 | ||
|
|
7ba718c0db | ||
|
|
e8ab0fd317 | ||
|
|
815fa2eb06 | ||
|
|
c52b3b4997 | ||
|
|
23ce6fae9e | ||
|
|
a8455a90ff | ||
|
|
798103bf63 | ||
|
|
bd8ca63451 | ||
|
|
cf27063aae | ||
|
|
fb18f3ba25 | ||
|
|
71137a2ffa | ||
|
|
544e550286 | ||
|
|
854004cf2c | ||
|
|
6b5a59dc43 | ||
|
|
fbfc07688e | ||
|
|
9b075ef529 | ||
|
|
97fec92365 | ||
|
|
26e6d6f115 | ||
|
|
978cc39009 | ||
|
|
53179c475c | ||
|
|
7ae9303a97 | ||
|
|
045bc59b75 | ||
|
|
08af35aad2 | ||
|
|
5b932152f8 | ||
|
|
9993b73355 | ||
|
|
f1eeed1c91 | ||
|
|
ee81907713 | ||
|
|
1f40d8fffd | ||
|
|
723196a157 | ||
|
|
0b0dddf8ec | ||
|
|
e33bfc7f1d | ||
|
|
03c1d19e07 | ||
|
|
8beeff2c52 | ||
|
|
f060db5fe6 | ||
|
|
4a3ff61571 | ||
|
|
908f36f574 | ||
|
|
292cc867a5 | ||
|
|
ab20bf472d | ||
|
|
470615eb05 | ||
|
|
f56fea6a1f | ||
|
|
7fda509333 | ||
|
|
0031ab82b7 | ||
|
|
e059fc8048 | ||
|
|
7953088418 | ||
|
|
1add112be6 | ||
|
|
f16b118794 | ||
|
|
d71c1cd6b0 | ||
|
|
ccd46028f2 | ||
|
|
24840d4d99 | ||
|
|
a656dadf4b | ||
|
|
03c834c647 | ||
|
|
876ab41ba8 | ||
|
|
dfa2b13c3a | ||
|
|
c6bb2730a8 | ||
|
|
08daaeb1a3 | ||
|
|
1f51ab27c4 | ||
|
|
36a58df181 | ||
|
|
4038e0a60c | ||
|
|
6042b39313 | ||
|
|
dc04a4b8a9 | ||
|
|
98499acff9 | ||
|
|
2417d32316 | ||
|
|
735280168f | ||
|
|
ef10f190cd | ||
|
|
b9b60df0a4 | ||
|
|
b69fb69a1a | ||
|
|
92e0f98633 | ||
|
|
0d58101edc | ||
|
|
44c88ad908 | ||
|
|
45b82dc466 | ||
|
|
22ac160021 | ||
|
|
b46a025576 | ||
|
|
7d5477cf22 | ||
|
|
f48dc3dd1a | ||
|
|
301b0fc1d1 | ||
|
|
d4c7b036fc | ||
|
|
8a88dd25b6 | ||
|
|
ad00679da9 | ||
|
|
598a13ecc0 | ||
|
|
34dfc3ce98 | ||
|
|
78e477b2a7 | ||
|
|
832306cf6e | ||
|
|
73599c22aa | ||
|
|
26ecf2b10f | ||
|
|
1e014f0b14 | ||
|
|
b40f7d36d5 | ||
|
|
7f1829eb21 | ||
|
|
eb9bad7a31 | ||
|
|
5bdd16404e | ||
|
|
9e4346bb44 | ||
|
|
eca4121dc6 | ||
|
|
828eaaf3d3 | ||
|
|
335e02aa44 | ||
|
|
0f242fd956 | ||
|
|
8b8bbb8a8d | ||
|
|
36fd78281c | ||
|
|
b85b7c6b9d | ||
|
|
320719b904 | ||
|
|
4ad078a975 | ||
|
|
d075b2c6e2 | ||
|
|
64460b8efc | ||
|
|
a583902f30 | ||
|
|
aac60b1390 | ||
|
|
500edddcb1 | ||
|
|
43ed2b0d1d | ||
|
|
267e733109 | ||
|
|
05a407196f | ||
|
|
bba311653d | ||
|
|
b8b8d697f4 | ||
|
|
577318be15 | ||
|
|
0b78a00afb | ||
|
|
ef29b5fb04 | ||
|
|
b959e0b5ec | ||
|
|
20c146e1e5 | ||
|
|
8d2a47e881 | ||
|
|
055e12570d | ||
|
|
35c143a036 | ||
|
|
a3e23fc9fa | ||
|
|
58672fb221 | ||
|
|
5c5934bc24 | ||
|
|
7610787e09 | ||
|
|
54bdb367c2 | ||
|
|
10de1da948 | ||
|
|
4a0de23cab | ||
|
|
be8dd55c21 | ||
|
|
3a4f475889 | ||
|
|
49eba77c37 | ||
|
|
1899c13385 | ||
|
|
aac7a23fd5 | ||
|
|
5ba0aa9aac | ||
|
|
c8104a29ec | ||
|
|
17ad73ace2 | ||
|
|
b2290a6420 | ||
|
|
fbb76e63ad | ||
|
|
d53e7aa51c | ||
|
|
11cde99e20 | ||
|
|
0fd3e5d4c5 | ||
|
|
f0af70736b | ||
|
|
292b24ad8f | ||
|
|
6ddde3aa98 | ||
|
|
4bba540311 | ||
|
|
454510092e | ||
|
|
7ab9479f2c | ||
|
|
017febed96 | ||
|
|
f7d174f2f8 | ||
|
|
b79f68a776 | ||
|
|
62abb972e9 | ||
|
|
53720dfcc7 | ||
|
|
55fc424835 | ||
|
|
7c7c6e47a9 | ||
|
|
5d8b6a5a70 | ||
|
|
4be8d7e622 | ||
|
|
d13983451a | ||
|
|
788a56c5e9 | ||
|
|
17345efb14 | ||
|
|
805b225876 | ||
|
|
845def82f5 | ||
|
|
4339ec3aa9 | ||
|
|
48553511be | ||
|
|
82a63a972d | ||
|
|
adaaf89737 | ||
|
|
00a27dc37b | ||
|
|
6252458d49 | ||
|
|
04a0e41e67 | ||
|
|
b8d4961483 | ||
|
|
bdd5109dbe | ||
|
|
da38647478 | ||
|
|
fa87e35a05 | ||
|
|
a8f9dfe0e1 | ||
|
|
875d56363c | ||
|
|
051198928e | ||
|
|
578108d586 | ||
|
|
3d04417a05 | ||
|
|
a3644a5420 | ||
|
|
d788a8eac6 | ||
|
|
3cad7787c2 | ||
|
|
ba0def3a38 | ||
|
|
394cf8d28f | ||
|
|
a6cb5f218e | ||
|
|
7bb6a8e8b1 | ||
|
|
9c65d5d65a | ||
|
|
2c24df2578 | ||
|
|
71d540023b | ||
|
|
5eb942f680 | ||
|
|
bb6ae9924c | ||
|
|
85093d6352 | ||
|
|
9030dcc111 | ||
|
|
cc8678ad58 | ||
|
|
669ec0da3d | ||
|
|
ef989779b0 | ||
|
|
f912206af8 | ||
|
|
ddb8ef82f0 | ||
|
|
0c83fd3f1a | ||
|
|
38ffb98421 | ||
|
|
0e4726b62a | ||
|
|
9c2cd31b1c | ||
|
|
ed69d24013 | ||
|
|
d12757f975 | ||
|
|
0fa645b8cc | ||
|
|
2457a23e95 | ||
|
|
ae0ecccd2e | ||
|
|
3cdab10aa0 | ||
|
|
95945c05a5 | ||
|
|
33acd78469 | ||
|
|
ca233b547a | ||
|
|
464ec3b70a | ||
|
|
bd96491d03 | ||
|
|
a5b9066fee | ||
|
|
c178236e32 | ||
|
|
f6524cf8c3 | ||
|
|
8d59d44431 | ||
|
|
8097f578f4 | ||
|
|
446fe29b15 | ||
|
|
6fbb90896b | ||
|
|
73e2123ce8 | ||
|
|
70db7080b1 | ||
|
|
9e63947e3c | ||
|
|
0dd2f34dfa | ||
|
|
07e739a364 | ||
|
|
e5c8c10029 | ||
|
|
38ae3620a2 | ||
|
|
72be80cb58 | ||
|
|
cc60b60135 | ||
|
|
447497427e | ||
|
|
18b347b4e9 | ||
|
|
29bb4fcb05 | ||
|
|
11aa48c83c | ||
|
|
f13722cc20 | ||
|
|
983382c327 | ||
|
|
1b16e1f378 | ||
|
|
494991e9fb | ||
|
|
1199c53437 | ||
|
|
6e1a8f1df2 | ||
|
|
52e5a8d3e3 | ||
|
|
0d17e05edc | ||
|
|
fa1317359a | ||
|
|
d87170db3a | ||
|
|
5756789b42 | ||
|
|
b081ca4dd0 | ||
|
|
77c980b032 | ||
|
|
05eb5ddaf8 | ||
|
|
9de09bd4f5 | ||
|
|
2f34f52536 | ||
|
|
ec3e19e66c | ||
|
|
a512287e4b | ||
|
|
48814ab134 | ||
|
|
28249924a8 | ||
|
|
e620d813b3 | ||
|
|
0db905a871 | ||
|
|
c87e26131a | ||
|
|
06c4233a54 | ||
|
|
9585723dda | ||
|
|
046ca8f732 | ||
|
|
fdd2978774 |
@@ -60,7 +60,7 @@ jobs:
|
||||
working_directory: /tmp/workspace/core
|
||||
- save_cache: *save-cache-core
|
||||
- run:
|
||||
command: npm run build -- --max-workers 1
|
||||
command: npm run build -- --ci
|
||||
working_directory: /tmp/workspace/core
|
||||
- save_cache: *save-cache-core-stencil
|
||||
- persist_to_workspace:
|
||||
@@ -91,6 +91,23 @@ jobs:
|
||||
paths:
|
||||
- "*"
|
||||
|
||||
build-angular-server:
|
||||
<<: *defaults
|
||||
steps:
|
||||
- checkout
|
||||
- attach_workspace:
|
||||
at: /tmp/workspace
|
||||
- run:
|
||||
command: npm install
|
||||
working_directory: /tmp/workspace/packages/angular-server
|
||||
- run:
|
||||
command: npm run build.prod
|
||||
working_directory: /tmp/workspace/packages/angular-server
|
||||
- persist_to_workspace:
|
||||
root: /tmp/workspace
|
||||
paths:
|
||||
- "*"
|
||||
|
||||
test-core-clean-build:
|
||||
<<: *defaults
|
||||
steps:
|
||||
@@ -119,7 +136,7 @@ jobs:
|
||||
- attach_workspace:
|
||||
at: /tmp/workspace
|
||||
- run:
|
||||
command: npm run test.spec
|
||||
command: npm run test.spec --ci
|
||||
working_directory: /tmp/workspace/core
|
||||
|
||||
test-core-treeshake:
|
||||
@@ -129,7 +146,7 @@ jobs:
|
||||
- attach_workspace:
|
||||
at: /tmp/workspace
|
||||
- run:
|
||||
command: npm run test.treeshake
|
||||
command: npm run test.treeshake --ci
|
||||
working_directory: /tmp/workspace/core
|
||||
|
||||
test-core-screenshot:
|
||||
@@ -173,6 +190,9 @@ jobs:
|
||||
- run:
|
||||
command: npm install
|
||||
working_directory: /tmp/workspace/angular/test/test-app
|
||||
- run:
|
||||
command: npm run sync
|
||||
working_directory: /tmp/workspace/angular/test/test-app
|
||||
- run:
|
||||
command: npm test
|
||||
working_directory: /tmp/workspace/angular/test/test-app
|
||||
@@ -205,7 +225,11 @@ workflows:
|
||||
|
||||
- build-angular:
|
||||
requires: [build-core]
|
||||
- build-angular-server:
|
||||
requires: [build-angular]
|
||||
- test-angular-lint:
|
||||
requires: [build-angular]
|
||||
- test-angular-e2e:
|
||||
requires: [build-angular]
|
||||
requires:
|
||||
- build-angular
|
||||
- build-angular-server
|
||||
|
||||
3
.github/ISSUE_TEMPLATE/bug_report.md
vendored
3
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -1,7 +1,7 @@
|
||||
---
|
||||
name: Bug Report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
title: 'bug: '
|
||||
labels: ''
|
||||
assignees: ''
|
||||
---
|
||||
@@ -37,6 +37,7 @@ assignees: ''
|
||||
A sample application via GitHub
|
||||
|
||||
StackBlitz (https://stackblitz.com)
|
||||
Ionic Angular StackBlitz: https://stackblitz.com/edit/ionic-v4-angular-tabs
|
||||
|
||||
Plunker (http://plnkr.co/edit/cpeRJs?p=preview)
|
||||
|
||||
|
||||
2
.github/ISSUE_TEMPLATE/feature_request.md
vendored
2
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@@ -1,7 +1,7 @@
|
||||
---
|
||||
name: Feature Request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
title: 'feat: '
|
||||
labels: ''
|
||||
assignees: ''
|
||||
---
|
||||
|
||||
2
.github/ISSUE_TEMPLATE/support_question.md
vendored
2
.github/ISSUE_TEMPLATE/support_question.md
vendored
@@ -1,7 +1,7 @@
|
||||
---
|
||||
name: Support Question
|
||||
about: Question on how to use this project
|
||||
title: ''
|
||||
title: 'support: '
|
||||
labels: 'ionitron: support'
|
||||
assignees: ''
|
||||
---
|
||||
|
||||
33
.github/PROCESS.md
vendored
33
.github/PROCESS.md
vendored
@@ -64,7 +64,7 @@ If the issue is a support question, the submitter should be redirected to our [f
|
||||
|
||||
### Incomplete Template
|
||||
|
||||
If the issue template has not been filled out completely, the issue should be closed and locked. The submitter should be informed top re-submit the issue making sure they fill the form out completely. Use the `ionitron: missing template` label to accomplish this.
|
||||
If the issue template has not been filled out completely, the issue should be closed and locked. The submitter should be informed to re-submit the issue making sure they fill the form out completely. Use the `ionitron: missing template` label to accomplish this.
|
||||
|
||||
### Issues with Open Questions
|
||||
|
||||
@@ -77,7 +77,7 @@ NOTE: be sure to perform those actions in the order stated. If you add the comme
|
||||
|
||||
If there is a response to the question, the bot will remove the `needs: reply` and apply the `triage` label. The issue will then go through the triage handling again.
|
||||
|
||||
if there is no response within 30 days, the issue will be closed and locked.
|
||||
If there is no response within 30 days, the issue will be closed and locked.
|
||||
|
||||
## Workflow
|
||||
|
||||
@@ -140,6 +140,14 @@ Once the release is ready to ship, it will get merged into `stable` and `master`
|
||||
|
||||
See the [steps for releasing](#releasing) below for detailed information on how to publish a release.
|
||||
|
||||
### Version Branches
|
||||
|
||||
Once a release has shipped and the release branch has been merged into `stable` and `master` it should also be merged into its corrsponding version branch. These version branches allow us to ship updates for specific versions of the framework (i.e. Lets us ship a bug fix that only affects 4.2.x).
|
||||
|
||||
Patch releases should be merged into their corresponding version branches. For example, a `release-4.1.1` branch should be merged into the `4.1.x` version branch and a `release-5.0.1` branch should be merged into the `5.0.x` version branch.
|
||||
|
||||
When releasing a major version such as `5.0.0 ` or a minor version such as `4.1.0` , the version branch will not exist. The version branch should be created once the release branch has been merged into `stable` and `master`. For example, when releasing `4.1.0`, the `release-4.1.0` release branch should be merged into `stable` and `master` and then the `4.1.x` version branch should be created off the latest `stable`.
|
||||
|
||||
|
||||
### Hotfix Branches
|
||||
|
||||
@@ -213,20 +221,31 @@ Hotfixes bypass `master` and should only be used for urgent fixes that can't wai
|
||||
|
||||
## Releasing
|
||||
|
||||
1. Create the release branch from `master`, for example: `release-4.1.0`.
|
||||
1. Submit a pull request from the release branch into `stable`. Do not merge this pull request yet.
|
||||
1. Create the release branch from `master`, for example: `release-4.5.0`.
|
||||
|
||||
1. For major or minor releases, create a version branch based off the latest version branch. For example, if releasing 4.5.0, create a branch called `4.5.x` based off `4.4.x`.
|
||||
|
||||
1. Submit a pull request from the release branch into the version branch. Do not merge this pull request yet.
|
||||
|
||||
1. Verify all tests are passing, fix any bugs if needed and make sure no undesired commits are in.
|
||||
|
||||
1. Navigate to the root of the repository while on the release branch.
|
||||
|
||||
1. Run `npm i` if it hasn't already been done.
|
||||
|
||||
1. Run `npm run release.prepare`
|
||||
- Select the version based on the type of commits and the [Ionic Versioning](https://ionicframework.com/docs/intro/versioning)
|
||||
- After the process completes, verify the version number in all packages (`core`, `docs`, `angular`)
|
||||
- Verify the changelog commits are accurate and follow the [proper format]((https://github.com/ionic-team/ionic/blob/master/.github/CONTRIBUTING.md#commit-message-format))
|
||||
- Commit these changes with the version number as the message, e.g. `git commit -m "4.1.0"`
|
||||
- For major or minor releases, ensure that the version number has an associated title (for example: `4.5.0 Boron`)
|
||||
- Commit these changes with the version number as the message, e.g. `git commit -m "4.5.0"`
|
||||
|
||||
1. Run `npm run release`
|
||||
|
||||
1. Click **Merge pull request**. Use the dropdown to select this option if necessary.
|
||||
|
||||
<img width="191" alt="Merge pull request button" src="https://user-images.githubusercontent.com/236501/47032669-8be1b980-d138-11e8-9a90-d1518c223184.png">
|
||||
|
||||
1. Rewrite the commit message to `merge release-4.1.0` with the proper release branch.
|
||||
1. Create a pull request and merge the release branch back into `master` using the same commit format in the last step, to ensure any changes made on the release branch get added to future releases.
|
||||
1. Rewrite the commit message to `merge release-[VERSION]` with the proper release branch. For example, if this release is for `4.5.0`, the message would be `merge release-4.5.0`.
|
||||
|
||||
1. Submit a pull request from the release branch into `master`. Merge this pull request using the same commit format in the last step, to ensure any changes made on the release branch get added to future releases.
|
||||
|
||||
47
.github/PULL_REQUEST_TEMPLATE.md
vendored
47
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -1,12 +1,51 @@
|
||||
#### Short description of what this resolves:
|
||||
<!-- Please refer to our contributing documentation for any questions on submitting a pull request, or let us know here if you need any help: https://ionicframework.com/docs/building/contributing -->
|
||||
|
||||
## Pull request checklist
|
||||
|
||||
Please check if your PR fulfills the following requirements:
|
||||
- [ ] Tests for the changes have been added (for bug fixes / features)
|
||||
- [ ] Docs have been reviewed and added / updated if needed (for bug fixes / features)
|
||||
- [ ] Build (`npm run build`) was run locally and any changes were pushed
|
||||
- [ ] Lint (`npm run lint`) has passed locally and any fixes were made for failures
|
||||
|
||||
|
||||
#### Changes proposed in this pull request:
|
||||
## Pull request type
|
||||
|
||||
<!-- Please do not submit updates to dependencies unless it fixes an issue. -->
|
||||
|
||||
<!-- Please try to limit your pull request to one type, submit multiple pull requests if needed. -->
|
||||
|
||||
Please check the type of change your PR introduces:
|
||||
- [ ] Bugfix
|
||||
- [ ] Feature
|
||||
- [ ] Code style update (formatting, renaming)
|
||||
- [ ] Refactoring (no functional changes, no api changes)
|
||||
- [ ] Build related changes
|
||||
- [ ] Documentation content changes
|
||||
- [ ] Other (please describe):
|
||||
|
||||
|
||||
## What is the current behavior?
|
||||
<!-- Please describe the current behavior that you are modifying, or link to a relevant issue. -->
|
||||
|
||||
Issue Number: N/A
|
||||
|
||||
|
||||
## What is the new behavior?
|
||||
<!-- Please describe the behavior or changes that are being added by this PR. -->
|
||||
|
||||
-
|
||||
-
|
||||
-
|
||||
|
||||
**Ionic Version**:
|
||||
## Does this introduce a breaking change?
|
||||
|
||||
**Fixes**: #
|
||||
- [ ] Yes
|
||||
- [ ] No
|
||||
|
||||
<!-- If this introduces a breaking change, please describe the impact and migration path for existing applications below. -->
|
||||
|
||||
|
||||
## Other information
|
||||
|
||||
<!-- Any other information that is important to this PR such as screenshots of how the component looks before and after the change. -->
|
||||
|
||||
9
.github/ionic-issue-bot.yml
vendored
9
.github/ionic-issue-bot.yml
vendored
@@ -118,6 +118,15 @@ labelPullRequest:
|
||||
|
||||
wrongRepo:
|
||||
repos:
|
||||
- label: "ionitron: capacitor"
|
||||
repo: capacitor
|
||||
message: >
|
||||
Thanks for the issue! We use this issue tracker exclusively for bug reports and feature requests
|
||||
associated with the Ionic Framework. It appears that this issue is associated with Capacitor.
|
||||
I am moving this issue to the Capacitor repository. Please track this issue over there.
|
||||
|
||||
|
||||
Thank you for using Ionic!
|
||||
- label: "ionitron: v3"
|
||||
repo: ionic-v3
|
||||
message: >
|
||||
|
||||
7
.gitignore
vendored
7
.gitignore
vendored
@@ -15,6 +15,7 @@ log.txt
|
||||
coverage/
|
||||
collection/
|
||||
dist/
|
||||
dist-transpiled/
|
||||
node_modules/
|
||||
tmp/
|
||||
temp/
|
||||
@@ -49,10 +50,16 @@ demos/src/**/*.ngfactory.ts
|
||||
demos/src/**/*.d.ts
|
||||
demos/src/**/*.metadata.json
|
||||
demos/src/**/*.css.shim.ts
|
||||
prerender.html
|
||||
prerender-domino.html
|
||||
prerender-hydrated.html
|
||||
prerender-static.html
|
||||
|
||||
# stencil
|
||||
angular/css/
|
||||
core/css/
|
||||
core/hydrate/
|
||||
core/loader/
|
||||
core/www/
|
||||
.stencil/
|
||||
angular/build/
|
||||
|
||||
@@ -258,11 +258,18 @@ function isVersionGreater(oldVersion, newVersion) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function copyCDNLoader(tasks, version) {
|
||||
tasks.push({
|
||||
title: `Copy CDN loader`,
|
||||
task: () => execa('node', ['copy-cdn-loader.js', version], { cwd: path.join(rootDir, 'core', 'scripts') }),
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
checkGit,
|
||||
isValidVersion,
|
||||
isVersionGreater,
|
||||
copyCDNLoader,
|
||||
packages,
|
||||
packagePath,
|
||||
prepareDevPackage,
|
||||
|
||||
@@ -116,6 +116,7 @@ async function preparePackages(packages, version, install) {
|
||||
|
||||
// update core readme with version number
|
||||
updateCoreReadme(tasks, version);
|
||||
common.copyCDNLoader(tasks, version);
|
||||
|
||||
const listr = new Listr(tasks, { showSubtasks: true });
|
||||
await listr.run();
|
||||
@@ -171,7 +172,6 @@ function updateCoreReadme(tasks, version) {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
const SEMVER_INCREMENTS = ['patch', 'minor', 'major'];
|
||||
|
||||
const isValidVersionInput = input => SEMVER_INCREMENTS.indexOf(input) !== -1 || common.isValidVersion(input);
|
||||
|
||||
@@ -7,6 +7,7 @@ const fs = require('fs-extra');
|
||||
|
||||
const common = require('./common');
|
||||
|
||||
const DIST_NPM_TAG = 'dev';
|
||||
const DIST_TAG = 'dev';
|
||||
|
||||
async function main() {
|
||||
@@ -37,7 +38,8 @@ async function main() {
|
||||
packages.forEach(package => {
|
||||
common.prepareDevPackage(tasks, package, devVersion);
|
||||
});
|
||||
common.publishPackages(tasks, packages, devVersion, DIST_TAG);
|
||||
common.copyCDNLoader(tasks, devVersion);
|
||||
common.publishPackages(tasks, packages, devVersion, DIST_NPM_TAG);
|
||||
|
||||
const listr = new Listr(tasks);
|
||||
await listr.run();
|
||||
|
||||
@@ -54,7 +54,7 @@ function publishGit(tasks, version, changelog) {
|
||||
},
|
||||
{
|
||||
title: 'Push tags to remove',
|
||||
task: () => execa('git', ['push', '--tags'], { cwd: common.rootDir })
|
||||
task: () => execa('git', ['push', '--follow-tags'], { cwd: common.rootDir })
|
||||
},
|
||||
{
|
||||
title: 'Publish Github release',
|
||||
|
||||
295
CHANGELOG.md
295
CHANGELOG.md
@@ -1,4 +1,297 @@
|
||||
# [4.2.0](https://github.com/ionic-team/ionic/compare/v4.1.2...v4.2.0) (2019-04-03)
|
||||
## [4.7.2](https://github.com/ionic-team/ionic/compare/v4.7.1...v4.7.2) (2019-08-07)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **angular:** hardware back button subscribeWithPriority triggers change detection ([#18962](https://github.com/ionic-team/ionic/issues/18962)) ([3a22105](https://github.com/ionic-team/ionic/commit/3a22105)), closes [#18959](https://github.com/ionic-team/ionic/issues/18959)
|
||||
* **angular:** nested inputs no longer conflict with each other ([#18976](https://github.com/ionic-team/ionic/issues/18976)) ([6bbdb80](https://github.com/ionic-team/ionic/commit/6bbdb80)), closes [#18248](https://github.com/ionic-team/ionic/issues/18248)
|
||||
* **range:** ion-range value now submitted with form ([#19008](https://github.com/ionic-team/ionic/issues/19008)) ([8f7853c](https://github.com/ionic-team/ionic/commit/8f7853c))
|
||||
* **reorder:** only move item if reorder happens ([#19007](https://github.com/ionic-team/ionic/issues/19007)) ([d237e80](https://github.com/ionic-team/ionic/commit/d237e80))
|
||||
* **router:** partial swipe to go back gesture no longer breaks view([#18977](https://github.com/ionic-team/ionic/issues/18977)) ([713ea8a](https://github.com/ionic-team/ionic/commit/713ea8a)), closes [#18462](https://github.com/ionic-team/ionic/issues/18462)
|
||||
* **toast:** allow loading ion-icon from asset path ([#18969](https://github.com/ionic-team/ionic/issues/18969)) ([23f327e](https://github.com/ionic-team/ionic/commit/23f327e))
|
||||
* **vue:** rename swipeEnable to swipeGesture ([#17346](https://github.com/ionic-team/ionic/issues/17346)) ([c2348f7](https://github.com/ionic-team/ionic/commit/c2348f7)), closes [#16002](https://github.com/ionic-team/ionic/issues/16002)
|
||||
|
||||
|
||||
|
||||
## [4.7.1](https://github.com/ionic-team/ionic/compare/v4.7.0...v4.7.1) (2019-07-26)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **angular:** ensure change detection fires properly ([#18896](https://github.com/ionic-team/ionic/issues/18896)) ([962783b](https://github.com/ionic-team/ionic/commit/962783b)), closes [#18894](https://github.com/ionic-team/ionic/issues/18894)
|
||||
|
||||
|
||||
|
||||
# [4.7.0 Nitrogen](https://github.com/ionic-team/ionic/compare/v4.6.2...v4.7.0) (2019-07-24)
|
||||
|
||||
|
||||
### Angular 8 Support
|
||||
|
||||
With this version comes support for Angular 8! Follow the below steps to update.
|
||||
|
||||
1. Update `@ionic/angular` and `@ionic/angular-toolkit` to the latest releases:
|
||||
|
||||
```shell
|
||||
$ npm install @ionic/angular@4.7.0
|
||||
$ npm install @ionic/angular-toolkit@2.0.0 -D
|
||||
```
|
||||
|
||||
1. Update `@angular/core` and `@angular/cli`:
|
||||
|
||||
```shell
|
||||
$ npx ng update @angular/core @angular/cli
|
||||
```
|
||||
|
||||
1. Update `@angular-devkit` dependencies:
|
||||
|
||||
```shell
|
||||
$ npm i @angular-devkit/architect@latest @angular-devkit/build-angular@latest @angular-devkit/core@latest @angular-devkit/schematics@latest
|
||||
```
|
||||
|
||||
View our [Angular 8 Update Guide](https://docs.google.com/document/d/1QOpQeDifPSg6F9WycDLcbQnpqjN96ew-Ap0_CB7CcCQ/edit?usp=sharing) for tips on potential issues!
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **angular:** copy input form classes to parent ion-item ([#18820](https://github.com/ionic-team/ionic/issues/18820)) ([53179c4](https://github.com/ionic-team/ionic/commit/53179c4)), closes [#18800](https://github.com/ionic-team/ionic/issues/18800)
|
||||
* **angular:** add the swipeGesture method for enabling or disabling the ability to swipe open a menu ([#18806](https://github.com/ionic-team/ionic/issues/18806)) ([fbfc076](https://github.com/ionic-team/ionic/commit/fbfc076)), closes [#16002](https://github.com/ionic-team/ionic/issues/16002)
|
||||
* **angular:** webview "pause", "resume", and "resize" events now trigger change detection ([#18853](https://github.com/ionic-team/ionic/issues/18853)) ([544e550](https://github.com/ionic-team/ionic/commit/544e550)), closes [#18831](https://github.com/ionic-team/ionic/issues/18831)
|
||||
* **core:** apply translucent if backdrop-filter is supported ([#18832](https://github.com/ionic-team/ionic/issues/18832)) ([6b5a59d](https://github.com/ionic-team/ionic/commit/6b5a59d)), closes [ionic-team/ionic-docs#666](https://github.com/ionic-team/ionic-docs/issues/666)
|
||||
* **datetime:** allow AM/PM to be changed ([#18684](https://github.com/ionic-team/ionic/issues/18684)) ([b7761fe](https://github.com/ionic-team/ionic/commit/b7761fe)), closes [#18585](https://github.com/ionic-team/ionic/issues/18585)
|
||||
* **datetime:** properly apply disabled classes when updating columns ([#18875](https://github.com/ionic-team/ionic/issues/18875)) ([7ba718c](https://github.com/ionic-team/ionic/commit/7ba718c)), closes [#18793](https://github.com/ionic-team/ionic/issues/18793)
|
||||
* **hardware-back-button:** hardware back button no longer erroneously restarts app ([#18794](https://github.com/ionic-team/ionic/issues/18794)) ([978cc39](https://github.com/ionic-team/ionic/commit/978cc39)), closes [#18792](https://github.com/ionic-team/ionic/issues/18792)
|
||||
* **ripple-effect:** ensure ripple is removed from components after pointer release ([#18854](https://github.com/ionic-team/ionic/issues/18854)) ([71137a2](https://github.com/ionic-team/ionic/commit/71137a2)), closes [#18836](https://github.com/ionic-team/ionic/issues/18836)
|
||||
* **searchbar:** add aria and role for improved accessibility ([#18797](https://github.com/ionic-team/ionic/issues/18797)) ([798103b](https://github.com/ionic-team/ionic/commit/798103b)), closes [#18796](https://github.com/ionic-team/ionic/issues/18796)
|
||||
* **ssr:** avoid window reference ([#18865](https://github.com/ionic-team/ionic/issues/18865)) ([23ce6fa](https://github.com/ionic-team/ionic/commit/23ce6fa))
|
||||
* **ssr:** check for client runtime method ([#18866](https://github.com/ionic-team/ionic/issues/18866)) ([c52b3b4](https://github.com/ionic-team/ionic/commit/c52b3b4))
|
||||
* **textarea:** autogrow now resets textarea back to original number of rows when text is cleared ([#18822](https://github.com/ionic-team/ionic/issues/18822)) ([26e6d6f](https://github.com/ionic-team/ionic/commit/26e6d6f)), closes [#18744](https://github.com/ionic-team/ionic/issues/18744)
|
||||
* **theming:** update components to use the proper colors for dark themes ([#18735](https://github.com/ionic-team/ionic/issues/18735)) ([045bc59](https://github.com/ionic-team/ionic/commit/045bc59)), closes [#18713](https://github.com/ionic-team/ionic/issues/18713)
|
||||
* **virtual-scroll:** card rendering is no longer distorted ([#18877](https://github.com/ionic-team/ionic/issues/18877)) ([3ef6ecf](https://github.com/ionic-team/ionic/commit/3ef6ecf)), closes [#18870](https://github.com/ionic-team/ionic/issues/18870)
|
||||
* **virtual-scroll:** element dimensions are recalculated on resize ([#18878](https://github.com/ionic-team/ionic/issues/18878)) ([c91819c](https://github.com/ionic-team/ionic/commit/c91819c))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **core:** add support for Stackblitz ([#18846](https://github.com/ionic-team/ionic/issues/18846)) ([fb18f3b](https://github.com/ionic-team/ionic/commit/fb18f3b))
|
||||
* **ssr:** add @ionic/core/hydrate app ([#18867](https://github.com/ionic-team/ionic/issues/18867)) ([815fa2e](https://github.com/ionic-team/ionic/commit/815fa2e))
|
||||
* **navigation:** add experimental shadow to iOS page transitions ([#18695](https://github.com/ionic-team/ionic/issues/18695)) ([9b075ef](https://github.com/ionic-team/ionic/commit/9b075ef)), closes [#18661](https://github.com/ionic-team/ionic/issues/18661)
|
||||
* **virtual-scroll:** adds headerHeight and footerHeight to help prevent flickering ([#18851](https://github.com/ionic-team/ionic/issues/18851)) ([0089111](https://github.com/ionic-team/ionic/commit/0089111)), closes [#17540](https://github.com/ionic-team/ionic/issues/17540)
|
||||
|
||||
|
||||
### Performance
|
||||
|
||||
* **angular:** attach entering view before first change detection and detach leaving page ([#18821](https://github.com/ionic-team/ionic/issues/18821)) ([97fec92](https://github.com/ionic-team/ionic/commit/97fec92))
|
||||
|
||||
|
||||
## [4.6.2](https://github.com/ionic-team/ionic/compare/v4.6.1...v4.6.2) (2019-07-10)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **menu-button:** hide menu button when auto hide or split pane ([#18702](https://github.com/ionic-team/ionic/issues/18702)) ([24840d4](https://github.com/ionic-team/ionic/commit/24840d4)), closes [#18666](https://github.com/ionic-team/ionic/issues/18666)
|
||||
* **menu-button:** move font-size to host for easier customization ([#18699](https://github.com/ionic-team/ionic/issues/18699)) ([876ab41](https://github.com/ionic-team/ionic/commit/876ab41)), closes [#18667](https://github.com/ionic-team/ionic/issues/18667)
|
||||
* **overlays:** fallback to step color if overlay background variable is unset ([#18709](https://github.com/ionic-team/ionic/issues/18709)) ([f16b118](https://github.com/ionic-team/ionic/commit/f16b118)), closes [#18658](https://github.com/ionic-team/ionic/issues/18658)
|
||||
* **virtual-scroll:** remove runOutsideAngular error ([#18752](https://github.com/ionic-team/ionic/issues/18752)) ([8beeff2](https://github.com/ionic-team/ionic/commit/8beeff2)), closes [#18746](https://github.com/ionic-team/ionic/issues/18746)
|
||||
* **vue:** update imports for types and ionicons ([f56fea6](https://github.com/ionic-team/ionic/commit/f56fea6)), closes [#18701](https://github.com/ionic-team/ionic/issues/18701)
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* **all:** minify better by using arrow functions ([#18730](https://github.com/ionic-team/ionic/issues/18730)) ([03c1d19](https://github.com/ionic-team/ionic/commit/03c1d19))
|
||||
|
||||
|
||||
|
||||
## [4.6.1](https://github.com/ionic-team/ionic/compare/v4.6.0...v4.6.1) (2019-07-09)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **app:** add hydrated to hide white screen with multiple ionic dependencies ([#18649](https://github.com/ionic-team/ionic/issues/18649))
|
||||
* **datetime:** datetime no longer reports having a value if none is set ([#18541](https://github.com/ionic-team/ionic/issues/18541)) ([92e0f98](https://github.com/ionic-team/ionic/commit/92e0f98)), closes [#17979](https://github.com/ionic-team/ionic/issues/17979) [#18540](https://github.com/ionic-team/ionic/issues/18540)
|
||||
* **fab-button:** set opacity on disabled fab button ([#18685](https://github.com/ionic-team/ionic/issues/18685)) ([6042b39](https://github.com/ionic-team/ionic/commit/6042b39)), closes [#18682](https://github.com/ionic-team/ionic/issues/18682)
|
||||
* **icon:** load icons properly with baseHref ([#18650](https://github.com/ionic-team/ionic/issues/18650)), ([#18637](https://github.com/ionic-team/ionic/issues/18637))
|
||||
* **icon:** bind icon name properly ([#18707](https://github.com/ionic-team/ionic/issues/18707))
|
||||
* **infinite-scroll:** fix scroll listener ([0d58101](https://github.com/ionic-team/ionic/commit/0d58101))
|
||||
* **item:** do not disable entire item if there are multiple inputs ([#18696](https://github.com/ionic-team/ionic/issues/18696)) ([dfa2b13](https://github.com/ionic-team/ionic/commit/dfa2b13)), closes [#18655](https://github.com/ionic-team/ionic/issues/18655) [#18670](https://github.com/ionic-team/ionic/issues/18670)
|
||||
* **router-link:** add missing target prop ([#18659](https://github.com/ionic-team/ionic/issues/18659)) ([1f51ab2](https://github.com/ionic-team/ionic/commit/1f51ab2)), closes [#18655](https://github.com/ionic-team/ionic/issues/18655)
|
||||
* **router-outlet:** fix swipe to go back ([b69fb69](https://github.com/ionic-team/ionic/commit/b69fb69))
|
||||
* **scss:** copy all scss files ([36a58df](https://github.com/ionic-team/ionic/commit/36a58df))
|
||||
* **searchbar:** proper styling after navigating ([#18642](https://github.com/ionic-team/ionic/issues/18642))
|
||||
* **slides:** use correct order for pushing slides dynamically ([#18633](https://github.com/ionic-team/ionic/issues/18633))
|
||||
* **tabs:** select proper tab by default and do not emit tab change if selectedTab is undefined ([03c834c](https://github.com/ionic-team/ionic/commit/03c834c))
|
||||
* **overlay:** make create opts optional ([44c88ad](https://github.com/ionic-team/ionic/commit/44c88ad))
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* **angular:** skip zone ([e059fc8](https://github.com/ionic-team/ionic/commit/e059fc8))
|
||||
|
||||
|
||||
|
||||
# [4.6.0 Carbon](https://github.com/ionic-team/ionic/compare/v4.5.0...v4.6.0) (2019-06-26)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **button:** default opacity for disabled clear buttons ([#18560](https://github.com/ionic-team/ionic/issues/18560)) ([f48dc3d](https://github.com/ionic-team/ionic/commit/f48dc3d)), closes [#18555](https://github.com/ionic-team/ionic/issues/18555)
|
||||
* **button:** update solid buttons to use tint and shade colors ([#18537](https://github.com/ionic-team/ionic/issues/18537)) ([26ecf2b](https://github.com/ionic-team/ionic/commit/26ecf2b))
|
||||
* **menu:** change ARIA role from complementary to navigation ([#18330](https://github.com/ionic-team/ionic/issues/18330)) ([9e4346b](https://github.com/ionic-team/ionic/commit/9e4346b)), closes [#18318](https://github.com/ionic-team/ionic/issues/18318)
|
||||
* **segment:** apply hover properly for segment with color ([#18549](https://github.com/ionic-team/ionic/issues/18549)) ([78e477b](https://github.com/ionic-team/ionic/commit/78e477b))
|
||||
* **segment:** default ripple to currentColor ([#18547](https://github.com/ionic-team/ionic/issues/18547)) ([832306c](https://github.com/ionic-team/ionic/commit/832306c))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **components:** add missing button/a props to components that render them ([#17883](https://github.com/ionic-team/ionic/issues/17883)) ([eca4121](https://github.com/ionic-team/ionic/commit/eca4121)), closes [#16848](https://github.com/ionic-team/ionic/issues/16848) [#16889](https://github.com/ionic-team/ionic/issues/16889)
|
||||
* **fab-button:** add hover state using tint colors ([#18536](https://github.com/ionic-team/ionic/issues/18536)) ([ad00679](https://github.com/ionic-team/ionic/commit/ad00679)), closes [#17624](https://github.com/ionic-team/ionic/issues/17624)
|
||||
* **item:** add hover and focused states ([#18606](https://github.com/ionic-team/ionic/issues/18606)) ([8a88dd2](https://github.com/ionic-team/ionic/commit/8a88dd2)), closes [#18279](https://github.com/ionic-team/ionic/issues/18279) [#17624](https://github.com/ionic-team/ionic/issues/17624)
|
||||
* **router-link:** add router-link and deprecate anchor ([#18620](https://github.com/ionic-team/ionic/issues/18620)) ([d4c7b03](https://github.com/ionic-team/ionic/commit/d4c7b03))
|
||||
|
||||
|
||||
### Enhancements
|
||||
|
||||
* **stencil:** update to Stencil One to improve app performance 🎉🎊 ([b40f7d3](https://github.com/ionic-team/ionic/commit/b40f7d3))
|
||||
|
||||
|
||||
|
||||
# [4.5.0 Boron](https://github.com/ionic-team/ionic/compare/v4.4.2...v4.5.0) (2019-06-12)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **angular:** ensure all NavigationExtras values are preserved when navigating ([#18468](https://github.com/ionic-team/ionic/issues/18468)) ([7610787](https://github.com/ionic-team/ionic/commit/7610787)), closes [#18469](https://github.com/ionic-team/ionic/issues/18469)
|
||||
* **button:** set opacity on the host element for disabled button ([#18509](https://github.com/ionic-team/ionic/issues/18509)) ([320719b](https://github.com/ionic-team/ionic/commit/320719b)), closes [#16965](https://github.com/ionic-team/ionic/issues/16965)
|
||||
* **button:** use correct border-radius on menu and back button ([#18501](https://github.com/ionic-team/ionic/issues/18501)) ([055e125](https://github.com/ionic-team/ionic/commit/055e125)), closes [#17624](https://github.com/ionic-team/ionic/issues/17624)
|
||||
* **button:** use correct size on a dynamic button in an item ([#18395](https://github.com/ionic-team/ionic/issues/18395)) ([a3e23fc](https://github.com/ionic-team/ionic/commit/a3e23fc)), closes [#18085](https://github.com/ionic-team/ionic/issues/18085)
|
||||
* **card:** remove white space from bottom of card ([#18328](https://github.com/ionic-team/ionic/issues/18328)) ([d53e7aa](https://github.com/ionic-team/ionic/commit/d53e7aa))
|
||||
* **content:** prevent ion-searchbar from receiving padding adjustment when keyboard is open ([#18008](https://github.com/ionic-team/ionic/issues/18008)) ([b2290a6](https://github.com/ionic-team/ionic/commit/b2290a6)), closes [#18007](https://github.com/ionic-team/ionic/issues/18007)
|
||||
* **datetime:** recalculate time columns on change ([#18380](https://github.com/ionic-team/ionic/issues/18380)) ([292b24a](https://github.com/ionic-team/ionic/commit/292b24a))
|
||||
* **item:** start align the content under stacked and floating labels ([#18379](https://github.com/ionic-team/ionic/issues/18379)) ([f0af707](https://github.com/ionic-team/ionic/commit/f0af707)), closes [#16375](https://github.com/ionic-team/ionic/issues/16375)
|
||||
* **item:** inherit overflow to allow better customization ([#18502](https://github.com/ionic-team/ionic/issues/18502)) ([8d2a47e](https://github.com/ionic-team/ionic/commit/8d2a47e)), closes [#17670](https://github.com/ionic-team/ionic/issues/17670)
|
||||
* **item:** use a step color if the activated background is not set ([#18450](https://github.com/ionic-team/ionic/issues/18450)) ([1899c13](https://github.com/ionic-team/ionic/commit/1899c13)), closes [#18449](https://github.com/ionic-team/ionic/issues/18449)
|
||||
* **item-sliding:** use the correct gesture direction and side for rtl ([#18366](https://github.com/ionic-team/ionic/issues/18366)) ([4545100](https://github.com/ionic-team/ionic/commit/4545100)), closes [#17012](https://github.com/ionic-team/ionic/issues/17012)
|
||||
* **label:** include the ion-text-wrap class styles for larger font ([#18374](https://github.com/ionic-team/ionic/issues/18374)) ([4bba540](https://github.com/ionic-team/ionic/commit/4bba540))
|
||||
* **platform:** prevent error with Platform.is on Android 4.4 ([#18387](https://github.com/ionic-team/ionic/issues/18387)) ([54bdb36](https://github.com/ionic-team/ionic/commit/54bdb36))
|
||||
* **react:** ensure element exists in controller before dismissing it ([0fd3e5d](https://github.com/ionic-team/ionic/commit/0fd3e5d))
|
||||
* **slides:** resolve issue where double tap to zoom was enabled by default ([10de1da](https://github.com/ionic-team/ionic/commit/10de1da)), closes [#18035](https://github.com/ionic-team/ionic/issues/18035)
|
||||
* **tabs:** allow selection on enter and spacebar press ([#18381](https://github.com/ionic-team/ionic/issues/18381)) ([11cde99](https://github.com/ionic-team/ionic/commit/11cde99)), closes [#18363](https://github.com/ionic-team/ionic/issues/18363)
|
||||
* **textarea:** inherit white-space for better customization ([#18508](https://github.com/ionic-team/ionic/issues/18508)) ([a583902](https://github.com/ionic-team/ionic/commit/a583902)), closes [#18495](https://github.com/ionic-team/ionic/issues/18495)
|
||||
* **virtual-scroll:** do not crash with an empty cell list ([#17799](https://github.com/ionic-team/ionic/issues/17799)) ([20c146e](https://github.com/ionic-team/ionic/commit/20c146e))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **back-button:** add variables and support for focused and hover states ([#18451](https://github.com/ionic-team/ionic/issues/18451)) ([58672fb](https://github.com/ionic-team/ionic/commit/58672fb)), closes [#18465](https://github.com/ionic-team/ionic/issues/18465)
|
||||
* **button:** add variables for customizing hover state ([#18499](https://github.com/ionic-team/ionic/issues/18499)) ([5c5934b](https://github.com/ionic-team/ionic/commit/5c5934b)), closes [#17974](https://github.com/ionic-team/ionic/issues/17974)
|
||||
* **item-divider:** add inner padding CSS variables ([#18490](https://github.com/ionic-team/ionic/issues/18490)) ([35c143a](https://github.com/ionic-team/ionic/commit/35c143a)), closes [#18484](https://github.com/ionic-team/ionic/issues/18484)
|
||||
* **menu-button:** add variables for hover and focused states ([#18434](https://github.com/ionic-team/ionic/issues/18434)) ([5ba0aa9](https://github.com/ionic-team/ionic/commit/5ba0aa9)), closes [#18279](https://github.com/ionic-team/ionic/issues/18279)
|
||||
* **searchbar:** add cancel button options ([b959e0b](https://github.com/ionic-team/ionic/commit/b959e0b))
|
||||
* **toast:** allow html content ([#18423](https://github.com/ionic-team/ionic/issues/18423)) ([c8104a2](https://github.com/ionic-team/ionic/commit/c8104a2))
|
||||
|
||||
|
||||
|
||||
## [4.4.2](https://github.com/ionic-team/ionic/compare/v4.4.1...v4.4.2) (2019-05-22)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **angular:** account for query params and fragments within a string when navigating ([#18356](https://github.com/ionic-team/ionic/issues/18356)) ([b79f68a](https://github.com/ionic-team/ionic/commit/b79f68a))
|
||||
|
||||
|
||||
|
||||
## [4.4.1](https://github.com/ionic-team/ionic/compare/v4.4.0...v4.4.1) (2019-05-22)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **angular:** ensure active page is not removed from change detection ([#18299](https://github.com/ionic-team/ionic/issues/18299)) ([b8d4961](https://github.com/ionic-team/ionic/commit/b8d4961)), closes [#18293](https://github.com/ionic-team/ionic/issues/18293)
|
||||
* **angular:** preserve queryParams and fragment when going back ([#18298](https://github.com/ionic-team/ionic/issues/18298)) ([bdd5109](https://github.com/ionic-team/ionic/commit/bdd5109)), closes [#16744](https://github.com/ionic-team/ionic/issues/16744)
|
||||
* **buttons:** use theme/color toolbar colors for buttons ([#18191](https://github.com/ionic-team/ionic/issues/18191)) ([0511989](https://github.com/ionic-team/ionic/commit/0511989)), closes [#18184](https://github.com/ionic-team/ionic/issues/18184) [#17840](https://github.com/ionic-team/ionic/issues/17840)
|
||||
* **datetime:** update label direction in RTL ([#18340](https://github.com/ionic-team/ionic/issues/18340)) ([17345ef](https://github.com/ionic-team/ionic/commit/17345ef))
|
||||
* **fab:** position fab buttons properly in RTL ([#18325](https://github.com/ionic-team/ionic/issues/18325)) ([845def8](https://github.com/ionic-team/ionic/commit/845def8)), references [#17012](https://github.com/ionic-team/ionic/issues/17012)
|
||||
* **icon:** remove stroke and move fill to host element ([#18241](https://github.com/ionic-team/ionic/issues/18241)) ([394cf8d](https://github.com/ionic-team/ionic/commit/394cf8d)), closes [#16483](https://github.com/ionic-team/ionic/issues/16483)
|
||||
* **input:** keep entire input in view when scrolling with keyboard open ([#18253](https://github.com/ionic-team/ionic/issues/18253)) ([3cad778](https://github.com/ionic-team/ionic/commit/3cad778)), closes [#17457](https://github.com/ionic-team/ionic/issues/17457)
|
||||
* **label:** position floating/stacked labels properly in RTL ([#18315](https://github.com/ionic-team/ionic/issues/18315)) ([00a27dc](https://github.com/ionic-team/ionic/commit/00a27dc)), references [#17012](https://github.com/ionic-team/ionic/issues/17012)
|
||||
* **loading:** allow html content ([#18242](https://github.com/ionic-team/ionic/issues/18242)) ([a6cb5f2](https://github.com/ionic-team/ionic/commit/a6cb5f2)), closes [#18135](https://github.com/ionic-team/ionic/issues/18135)
|
||||
* **overlay:** hide scrollbars on non-scrollable content ([#16767](https://github.com/ionic-team/ionic/issues/16767)) ([875d563](https://github.com/ionic-team/ionic/commit/875d563)), closes [#14178](https://github.com/ionic-team/ionic/issues/14178)
|
||||
* **picker:** update the column positions in RTL ([#18339](https://github.com/ionic-team/ionic/issues/18339)) ([788a56c](https://github.com/ionic-team/ionic/commit/788a56c)), closes [#17012](https://github.com/ionic-team/ionic/issues/17012)
|
||||
* **range:** update border-radius on range pin for RTL ([#18321](https://github.com/ionic-team/ionic/issues/18321)) ([4855351](https://github.com/ionic-team/ionic/commit/4855351)), closes [#17012](https://github.com/ionic-team/ionic/issues/17012)
|
||||
* **searchbar:** position buttons properly in RTL ([#18325](https://github.com/ionic-team/ionic/issues/18325)) ([845def8](https://github.com/ionic-team/ionic/commit/845def8)), references [#17012](https://github.com/ionic-team/ionic/issues/17012)
|
||||
* **segment:** update segment border for RTL ([#18326](https://github.com/ionic-team/ionic/issues/18326)) ([805b225](https://github.com/ionic-team/ionic/commit/805b225)), closes [#17012](https://github.com/ionic-team/ionic/issues/17012)
|
||||
* **slides:** allow clicks to propagate to buttons ([#16728](https://github.com/ionic-team/ionic/issues/16728)) ([a8f9dfe](https://github.com/ionic-team/ionic/commit/a8f9dfe))
|
||||
* **tab-button:** apply background-focused when tabbing into tab button ([#17502](https://github.com/ionic-team/ionic/issues/17502)) ([d788a8e](https://github.com/ionic-team/ionic/commit/d788a8e)), closes [#17042](https://github.com/ionic-team/ionic/issues/17042)
|
||||
* **tabs:** position badge properly in RTL (only in Chrome) ([#18325](https://github.com/ionic-team/ionic/issues/18325)) ([845def8](https://github.com/ionic-team/ionic/commit/845def8)), references [#17012](https://github.com/ionic-team/ionic/issues/17012)
|
||||
* **tabs:** select the tab called by the select method after initialization ([#18300](https://github.com/ionic-team/ionic/issues/18300)) ([da38647](https://github.com/ionic-team/ionic/commit/da38647)), closes [#17957](https://github.com/ionic-team/ionic/issues/17957)
|
||||
* **toggle:** position toggle icon properly in RTL ([#18325](https://github.com/ionic-team/ionic/issues/18325)) ([845def8](https://github.com/ionic-team/ionic/commit/845def8)), references [#17012](https://github.com/ionic-team/ionic/issues/17012)
|
||||
* **toolbar:** update md toolbar button spacing and padding to match spec ([#17537](https://github.com/ionic-team/ionic/issues/17537)) ([fa87e35](https://github.com/ionic-team/ionic/commit/fa87e35)), closes [#16950](https://github.com/ionic-team/ionic/issues/16950) [#14444](https://github.com/ionic-team/ionic/issues/14444)
|
||||
|
||||
|
||||
|
||||
# [4.4.0 Beryllium](https://github.com/ionic-team/ionic/compare/v4.3.1...v4.4.0) (2019-05-08)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **button:** apply round property to button sizes in iOS ([#18125](https://github.com/ionic-team/ionic/issues/18125)) ([ae0eccc](https://github.com/ionic-team/ionic/commit/ae0eccc)), closes [#18108](https://github.com/ionic-team/ionic/issues/18108)
|
||||
* **datetime:** default to current date when value is null ([#18105](https://github.com/ionic-team/ionic/issues/18105)) ([ca233b5](https://github.com/ionic-team/ionic/commit/ca233b5)), closes [#18099](https://github.com/ionic-team/ionic/issues/18099)
|
||||
* **input:** clear on edit from inside native input ([#17115](https://github.com/ionic-team/ionic/issues/17115)) ([85093d6](https://github.com/ionic-team/ionic/commit/85093d6)), closes [#17055](https://github.com/ionic-team/ionic/issues/17055)
|
||||
* **item:** use the global activated background for md ripple color ([#16752](https://github.com/ionic-team/ionic/issues/16752)) ([95945c0](https://github.com/ionic-team/ionic/commit/95945c0)), closes [#16585](https://github.com/ionic-team/ionic/issues/16585)
|
||||
* **label:** use primary color on focus for md input labels ([#18183](https://github.com/ionic-team/ionic/issues/18183)) ([ddb8ef8](https://github.com/ionic-team/ionic/commit/ddb8ef8)), closes [#15602](https://github.com/ionic-team/ionic/issues/15602)
|
||||
* **menu** add prefixed transform for side menu animation ([#18128](https://github.com/ionic-team/ionic/issues/18128)) ([2457a23](https://github.com/ionic-team/ionic/commit/2457a23)), closes [#17729](https://github.com/ionic-team/ionic/issues/17729)
|
||||
* **reorder-group:** remove required parameter for the complete method ([#18084](https://github.com/ionic-team/ionic/issues/18084)) ([bd96491](https://github.com/ionic-team/ionic/commit/bd96491)), closes [#16302](https://github.com/ionic-team/ionic/issues/16302)
|
||||
* **segment:** decrease icon size on ios and stretch segment buttons to fill height ([#17751](https://github.com/ionic-team/ionic/issues/17751)) ([0fa645b](https://github.com/ionic-team/ionic/commit/0fa645b)), closes [#17069](https://github.com/ionic-team/ionic/issues/17069)
|
||||
* **textarea:** reposition textarea when keyboard appears ([#18098](https://github.com/ionic-team/ionic/issues/18098)) ([3cdab10](https://github.com/ionic-team/ionic/commit/3cdab10)), closes [#17847](https://github.com/ionic-team/ionic/issues/17847)
|
||||
* **toast:** allow button-color CSS variable to be overridden ([#18133](https://github.com/ionic-team/ionic/issues/18133)) ([0c83fd3](https://github.com/ionic-team/ionic/commit/0c83fd3)), closes [#18127](https://github.com/ionic-team/ionic/issues/18127)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **card:** add button functionality ([#17997](https://github.com/ionic-team/ionic/issues/17997)) ([669ec0d](https://github.com/ionic-team/ionic/commit/669ec0d)), closes [#17773](https://github.com/ionic-team/ionic/issues/17773)
|
||||
* **img:** add ionImgWillLoad event and emit ionImgDidLoad when image is loaded ([#18159](https://github.com/ionic-team/ionic/issues/18159)) ([38ffb98](https://github.com/ionic-team/ionic/commit/38ffb98)), closes [#17652](https://github.com/ionic-team/ionic/issues/17652) [#18161](https://github.com/ionic-team/ionic/issues/18161)
|
||||
* **item-sliding:** add open method ([#17964](https://github.com/ionic-team/ionic/issues/17964)) ([f912206](https://github.com/ionic-team/ionic/commit/f912206)), closes [#17899](https://github.com/ionic-team/ionic/issues/17899)
|
||||
* **menu-button:** add css variables for padding ([#18188](https://github.com/ionic-team/ionic/issues/18188)) ([ef98977](https://github.com/ionic-team/ionic/commit/ef98977)), closes [#18187](https://github.com/ionic-team/ionic/issues/18187)
|
||||
* **refresher:** add pullFactor property to control speed ([#16697](https://github.com/ionic-team/ionic/issues/16697)) ([9030dcc](https://github.com/ionic-team/ionic/commit/9030dcc)), closes [#15425](https://github.com/ionic-team/ionic/issues/15425)
|
||||
* **searchbar:** add disabled property ([#17935](https://github.com/ionic-team/ionic/issues/17935)) ([a5b9066](https://github.com/ionic-team/ionic/commit/a5b9066)), closes [#17921](https://github.com/ionic-team/ionic/issues/17921)
|
||||
* **textarea:** add option to expand textarea as value changes ([#16916](https://github.com/ionic-team/ionic/issues/16916)) ([cc8678a](https://github.com/ionic-team/ionic/commit/cc8678a))
|
||||
|
||||
|
||||
|
||||
## [4.3.1](https://github.com/ionic-team/ionic/compare/v4.3.0...v4.3.1) (2019-04-26)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **angular:** support replaceUrl with angular <7.2 ([#18106](https://github.com/ionic-team/ionic/issues/18106)) ([eb3cbe4](https://github.com/ionic-team/ionic/commit/eb3cbe4))
|
||||
* **security:** sanitize components using innerHTML ([#18146](https://github.com/ionic-team/ionic/issues/18146)) ([b839e6f](https://github.com/ionic-team/ionic/commit/b839e6f))
|
||||
|
||||
|
||||
|
||||
# [4.3.0 Lithium](https://github.com/ionic-team/ionic/compare/v4.2.0...v4.3.0) (2019-04-17)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **action-sheet:** default buttons to empty array ([9e63947](https://github.com/ionic-team/ionic/commit/9e63947))
|
||||
* **angular:** back button correctly goes back to proper tab ([#18005](https://github.com/ionic-team/ionic/issues/18005)) ([52e5a8d](https://github.com/ionic-team/ionic/commit/52e5a8d)), closes [#17278](https://github.com/ionic-team/ionic/issues/17278) [#15216](https://github.com/ionic-team/ionic/issues/15216)
|
||||
* **components:** add mode classes to components for use in shadow elements ([#17838](https://github.com/ionic-team/ionic/issues/17838)) ([e5c8c10](https://github.com/ionic-team/ionic/commit/e5c8c10)), closes [#17608](https://github.com/ionic-team/ionic/issues/17608)
|
||||
* **datetime:** date strings no longer revert to previous day ([#18018](https://github.com/ionic-team/ionic/issues/18018)) ([cc60b60](https://github.com/ionic-team/ionic/commit/cc60b60)), closes [#17977](https://github.com/ionic-team/ionic/issues/17977)
|
||||
* **input:** prevent input from losing focus when tapping clear button ([#18004](https://github.com/ionic-team/ionic/issues/18004)) ([29bb4fc](https://github.com/ionic-team/ionic/commit/29bb4fc)), closes [#18002](https://github.com/ionic-team/ionic/issues/18002)
|
||||
* **item:** use the correct input highlight for an inset line item ([#18052](https://github.com/ionic-team/ionic/issues/18052)) ([72be80c](https://github.com/ionic-team/ionic/commit/72be80c)), closes [#18051](https://github.com/ionic-team/ionic/issues/18051)
|
||||
* **item-sliding:** hide closed side options while dragging side options open ([#17986](https://github.com/ionic-team/ionic/issues/17986)) ([f13722c](https://github.com/ionic-team/ionic/commit/f13722c)), closes [#17822](https://github.com/ionic-team/ionic/issues/17822)
|
||||
* **slides:** allow zoom to work ([18b347b](https://github.com/ionic-team/ionic/commit/18b347b)), closes [#17981](https://github.com/ionic-team/ionic/issues/17981)
|
||||
* **slides:** expose interface to provide custom animations ([#17959](https://github.com/ionic-team/ionic/issues/17959)) ([4474974](https://github.com/ionic-team/ionic/commit/4474974)), closes [#16616](https://github.com/ionic-team/ionic/issues/16616)
|
||||
* **textarea:** float label when a value is changed async ([#18024](https://github.com/ionic-team/ionic/issues/18024)) ([494991e](https://github.com/ionic-team/ionic/commit/494991e)), closes [#17555](https://github.com/ionic-team/ionic/issues/17555) [#17559](https://github.com/ionic-team/ionic/issues/17559)
|
||||
* **textarea:** update label alignment for inputs and textareas ([#18042](https://github.com/ionic-team/ionic/issues/18042)) ([38ae362](https://github.com/ionic-team/ionic/commit/38ae362)), closes [#16187](https://github.com/ionic-team/ionic/issues/16187)
|
||||
* **vue:** use direction type from core ([#17901](https://github.com/ionic-team/ionic/issues/17901)) ([fa13173](https://github.com/ionic-team/ionic/commit/fa13173))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **toast:** add header and additional custom toast buttons ([#17147](https://github.com/ionic-team/ionic/issues/17147)) ([6e1a8f1](https://github.com/ionic-team/ionic/commit/6e1a8f1)), closes [#16791](https://github.com/ionic-team/ionic/issues/16791) [#16237](https://github.com/ionic-team/ionic/issues/16237) [#17611](https://github.com/ionic-team/ionic/issues/17611)
|
||||
* **toast:** add variables to change position start/end of toast ([#17961](https://github.com/ionic-team/ionic/issues/17961)) ([07e739a](https://github.com/ionic-team/ionic/commit/07e739a)), closes [#17854](https://github.com/ionic-team/ionic/issues/17854)
|
||||
|
||||
|
||||
|
||||
# [4.2.0 Helium](https://github.com/ionic-team/ionic/compare/v4.1.2...v4.2.0) (2019-04-03)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
@@ -182,13 +182,14 @@ These have been renamed to the following, and moved from the button element to t
|
||||
|
||||
In addition, several sets of mutually exclusive boolean attributes have been combined into a single string attribute.
|
||||
|
||||
The `small` and `large` attributes are now combined under the `size` attribute. The `clear`, `outline`, and `solid` attributes have been combined under `fill`. And, lastly, the `full` and `block` attributes have been combined under `expand`.
|
||||
The `small` and `large` attributes are now combined under the `size` attribute. The `clear`, `outline`, and `solid` attributes have been combined under `fill`. The `full` and `block` attributes have been combined under `expand`. And, lastly, the `round` attribute is now used under `shape`.
|
||||
|
||||
| Old Property | New Property | Property Behavior |
|
||||
| --------------------------- | ------------ | --------------------------- |
|
||||
| `small`, `large` | `size` | Sets the button size. |
|
||||
| `clear`, `outline`, `solid` | `fill` | Sets the button fill style. |
|
||||
| `full`, `block` | `expand` | Sets the button width. |
|
||||
| `round` | `shape` | Sets the button shape. |
|
||||
|
||||
|
||||
**Old Usage Example:**
|
||||
@@ -225,6 +226,10 @@ The `small` and `large` attributes are now combined under the `size` attribute.
|
||||
<ion-button full>
|
||||
Full-width Button
|
||||
</ion-button>
|
||||
|
||||
<ion-button round>
|
||||
Round Button
|
||||
</ion-button>
|
||||
```
|
||||
|
||||
**New Usage Example:**
|
||||
@@ -251,6 +256,10 @@ The `small` and `large` attributes are now combined under the `size` attribute.
|
||||
<ion-button expand="full">
|
||||
Full-width Button
|
||||
</ion-button>
|
||||
|
||||
<ion-button shape="round">
|
||||
Round Button
|
||||
</ion-button>
|
||||
```
|
||||
|
||||
|
||||
@@ -774,6 +783,26 @@ The option component should now be written as an `ion-item-option`. Previously i
|
||||
|
||||
The `getSlidingPercent` method has been renamed to `getSlidingRatio` since the function is returning a ratio of the open amount of the item compared to the width of the options.
|
||||
|
||||
### Arguments Changed
|
||||
|
||||
The `ionDrag` event no longer gets the sliding item as an argument. It now takes an event with a property `details` which contains two properties `amount` and `ratio` reflecting the absolute and ratio values of the sliding action respectively.
|
||||
|
||||
**Old Usage Example:**
|
||||
|
||||
```typescript
|
||||
dragged(item: ItemSliding) {
|
||||
console.log(item.getSlidingPercent());
|
||||
console.log(item.getOpenAmount());
|
||||
}
|
||||
```
|
||||
|
||||
**New Usage Example:**
|
||||
```typescript
|
||||
dragged(ev: { details: { amount: number, ratio: number } }) {
|
||||
console.log(ev.details.ratio);
|
||||
console.log(ev.details.amount);
|
||||
}
|
||||
```
|
||||
|
||||
## Label
|
||||
|
||||
@@ -1065,11 +1094,11 @@ async openLoading() {
|
||||
let loading = this.loadingCtrl.create({
|
||||
content: 'Loading...'
|
||||
});
|
||||
|
||||
|
||||
await loading.present();
|
||||
|
||||
|
||||
const { role, data } = await loading.onDidDismiss();
|
||||
|
||||
|
||||
console.log('Loading dismissed!');
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ionic/angular",
|
||||
"version": "4.2.0",
|
||||
"version": "4.7.2",
|
||||
"description": "Angular specific wrappers for @ionic/core",
|
||||
"keywords": [
|
||||
"ionic",
|
||||
@@ -19,6 +19,10 @@
|
||||
"type": "git",
|
||||
"url": "https://github.com/ionic-team/ionic.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/ionic-team/ionic/issues"
|
||||
},
|
||||
"homepage": "https://ionicframework.com/",
|
||||
"scripts": {
|
||||
"build": "npm run clean && npm run build.core && npm run build.ng && npm run clean-generated",
|
||||
"build.core": "node scripts/build-core.js",
|
||||
@@ -38,29 +42,29 @@
|
||||
"validate": "npm i && npm run lint && npm run test && npm run build"
|
||||
},
|
||||
"module": "dist/fesm5.js",
|
||||
"main": "dist/fesm5.js",
|
||||
"main": "dist/fesm5.cjs.js",
|
||||
"types": "dist/core.d.ts",
|
||||
"files": [
|
||||
"dist/",
|
||||
"css/"
|
||||
],
|
||||
"dependencies": {
|
||||
"@ionic/core": "4.2.0",
|
||||
"@ionic/core": "4.7.2",
|
||||
"tslib": "^1.9.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@angular-devkit/core": "^7.2.1",
|
||||
"@angular-devkit/schematics": "^7.2.1",
|
||||
"@angular/core": "^7.2.1",
|
||||
"@angular/common": "^7.2.1",
|
||||
"@angular/forms": "^7.2.1",
|
||||
"@angular/router": "^7.2.1",
|
||||
"@angular/compiler": "^7.2.1",
|
||||
"@angular/compiler-cli": "^7.2.1",
|
||||
"@angular/platform-browser": "^7.2.1",
|
||||
"@angular/platform-browser-dynamic": "^7.2.1",
|
||||
"@angular-devkit/core": "7.2.1 - 8",
|
||||
"@angular-devkit/schematics": "7.2.1 - 8",
|
||||
"@angular/core": "7.2.1 - 8",
|
||||
"@angular/common": "7.2.1 - 8",
|
||||
"@angular/forms": "7.2.1 - 8",
|
||||
"@angular/router": "7.2.1 - 8",
|
||||
"@angular/compiler": "7.2.1 - 8",
|
||||
"@angular/compiler-cli": "7.2.1 - 8",
|
||||
"@angular/platform-browser": "7.2.1 - 8",
|
||||
"@angular/platform-browser-dynamic": "7.2.1 - 8",
|
||||
"rxjs": ">=6.2.0",
|
||||
"zone.js": "^0.8.26"
|
||||
"zone.js": ">=0.8.26"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-devkit/core": "^7.2.1",
|
||||
@@ -73,17 +77,17 @@
|
||||
"@angular/platform-browser": "^7.2.1",
|
||||
"@angular/platform-browser-dynamic": "^7.2.1",
|
||||
"@angular/router": "^7.2.1",
|
||||
"@types/node": "~10.12.0",
|
||||
"@types/node": "~12.0.12",
|
||||
"fs-extra": "^7.0.0",
|
||||
"glob": "^7.1.3",
|
||||
"rollup": "^1.1.2",
|
||||
"rollup-plugin-node-resolve": "^4.0.0",
|
||||
"rxjs": "^6.2.0",
|
||||
"glob": "^7.1.4",
|
||||
"rollup": "~1.17.0",
|
||||
"rollup-plugin-node-resolve": "~5.2.0",
|
||||
"rxjs": "^6.5.2",
|
||||
"tsickle": "^0.34.0",
|
||||
"tslint": "^5.12.1",
|
||||
"tslint-ionic-rules": "0.0.21",
|
||||
"typescript": "3.2.4",
|
||||
"zone.js": "^0.8.28"
|
||||
"typescript": "~3.2.2",
|
||||
"zone.js": "~0.8.26"
|
||||
},
|
||||
"schematics": "./dist/schematics/collection.json"
|
||||
}
|
||||
|
||||
@@ -15,3 +15,7 @@
|
||||
npm run build.link ../ionic-conference-app
|
||||
|
||||
When the command above is ran from the `angular` directory, it will build `@ionic/angular` and copy the `dist` directory to the correct location of another local project. In the example above, the end result is that it copies the `dist` directory to `../ionic-conference-app/node_modules/@ionic/angular/dist`. The path given should be relative to the root of this mono repo.
|
||||
|
||||
## package.json note
|
||||
|
||||
The `package.json` file in this directory references __Ionic 3__ and is in here to get GitHub to properly show the Used By counts on the repo. __Do not remove it!__
|
||||
|
||||
6
angular/scripts/clean.js
vendored
6
angular/scripts/clean.js
vendored
@@ -1,12 +1,12 @@
|
||||
const fs = require('fs-extra');
|
||||
const path = require('path');
|
||||
|
||||
const ROOT_DIR = path.join(__dirname, '..');
|
||||
|
||||
const cleanDirs = [
|
||||
'dist'
|
||||
path.join(ROOT_DIR, 'dist')
|
||||
];
|
||||
|
||||
cleanDirs.forEach(dir => {
|
||||
const cleanDir = path.join(__dirname, '../', dir);
|
||||
fs.removeSync(cleanDir);
|
||||
fs.emptyDirSync(dir);
|
||||
});
|
||||
|
||||
16
angular/scripts/package.json
Normal file
16
angular/scripts/package.json
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "ionic-angular",
|
||||
"version": "`gulp package` generates dist/package.json from this template using the root ./package.json",
|
||||
"description": "",
|
||||
"keywords": [],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/ionic-team/ionic.git"
|
||||
},
|
||||
"license": "MIT",
|
||||
"main": "umd/index.js",
|
||||
"module": "index.js",
|
||||
"es2015": "es2015/index.js",
|
||||
"peerDependencies": {
|
||||
}
|
||||
}
|
||||
@@ -2,15 +2,13 @@ import resolve from 'rollup-plugin-node-resolve';
|
||||
|
||||
export default {
|
||||
input: 'build/es2015/core.js',
|
||||
output: {
|
||||
file: 'dist/fesm2015.js',
|
||||
format: 'es'
|
||||
},
|
||||
external: (id) => {
|
||||
// inline @ionic/core deps
|
||||
if (id === '@ionic/core') {
|
||||
return false;
|
||||
output: [
|
||||
{
|
||||
file: 'dist/fesm2015.js',
|
||||
format: 'es'
|
||||
}
|
||||
],
|
||||
external: (id) => {
|
||||
// anything else is external
|
||||
// Windows: C:\xxxxxx\xxx
|
||||
const colonPosition = 1;
|
||||
|
||||
@@ -4,6 +4,15 @@ const newConfig = {
|
||||
...config,
|
||||
input: 'build/es5/core.js',
|
||||
};
|
||||
newConfig.output.file = 'dist/fesm5.js';
|
||||
newConfig.output = [
|
||||
{
|
||||
file: 'dist/fesm5.js',
|
||||
format: 'es'
|
||||
},
|
||||
{
|
||||
file: 'dist/fesm5.cjs.js',
|
||||
format: 'cjs'
|
||||
}
|
||||
];
|
||||
|
||||
export { newConfig as default };
|
||||
|
||||
@@ -1,55 +1,39 @@
|
||||
import { defineCustomElements } from '@ionic/core/loader';
|
||||
import { NgZone } from '@angular/core';
|
||||
import { applyPolyfills, defineCustomElements } from '@ionic/core/loader';
|
||||
|
||||
import { Config } from './providers/config';
|
||||
import { IonicWindow } from './types/interfaces';
|
||||
import { raf } from './util/util';
|
||||
|
||||
export function appInitialize(config: Config, doc: Document) {
|
||||
export const appInitialize = (config: Config, doc: Document, zone: NgZone) => {
|
||||
return (): any => {
|
||||
const win: IonicWindow | undefined = doc.defaultView as any;
|
||||
if (win) {
|
||||
const Ionic = win.Ionic = win.Ionic || {};
|
||||
|
||||
Ionic.config = config;
|
||||
Ionic.asyncQueue = false;
|
||||
|
||||
Ionic.ael = (elm, eventName, cb, opts) => {
|
||||
if (elm.__zone_symbol__addEventListener && skipZone(eventName)) {
|
||||
elm.__zone_symbol__addEventListener(eventName, cb, opts);
|
||||
} else {
|
||||
elm.addEventListener(eventName, cb, opts);
|
||||
}
|
||||
Ionic.config = {
|
||||
...config,
|
||||
_zoneGate: (h: any) => zone.run(h)
|
||||
};
|
||||
|
||||
Ionic.rel = (elm, eventName, cb, opts) => {
|
||||
if (elm.__zone_symbol__removeEventListener && skipZone(eventName)) {
|
||||
elm.__zone_symbol__removeEventListener(eventName, cb, opts);
|
||||
} else {
|
||||
elm.removeEventListener(eventName, cb, opts);
|
||||
}
|
||||
};
|
||||
const aelFn = '__zone_symbol__addEventListener' in (doc.body as any)
|
||||
? '__zone_symbol__addEventListener'
|
||||
: 'addEventListener';
|
||||
|
||||
return defineCustomElements(win, {
|
||||
exclude: ['ion-tabs', 'ion-tab']
|
||||
return applyPolyfills().then(() => {
|
||||
return defineCustomElements(win, {
|
||||
exclude: ['ion-tabs', 'ion-tab'],
|
||||
syncQueue: true,
|
||||
raf,
|
||||
jmp: (h: any) => zone.runOutsideAngular(h),
|
||||
ael(elm, eventName, cb, opts) {
|
||||
(elm as any)[aelFn](eventName, cb, opts);
|
||||
},
|
||||
rel(elm, eventName, cb, opts) {
|
||||
elm.removeEventListener(eventName, cb, opts);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const SKIP_ZONE = [
|
||||
'scroll',
|
||||
'resize',
|
||||
|
||||
'touchstart',
|
||||
'touchmove',
|
||||
'touchend',
|
||||
|
||||
'mousedown',
|
||||
'mousemove',
|
||||
'mouseup',
|
||||
|
||||
'ionStyle',
|
||||
];
|
||||
|
||||
function skipZone(eventName: string) {
|
||||
return SKIP_ZONE.indexOf(eventName) >= 0;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -25,8 +25,8 @@ export class BooleanValueAccessor extends ValueAccessor {
|
||||
setIonicClasses(this.el);
|
||||
}
|
||||
|
||||
@HostListener('ionChange', ['$event.target.checked'])
|
||||
_handleIonChange(value: any) {
|
||||
this.handleChangeEvent(value);
|
||||
@HostListener('ionChange', ['$event.target'])
|
||||
_handleIonChange(el: any) {
|
||||
this.handleChangeEvent(el, el.checked);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,9 +20,9 @@ export class NumericValueAccessor extends ValueAccessor {
|
||||
super(el);
|
||||
}
|
||||
|
||||
@HostListener('ionChange', ['$event.target.value'])
|
||||
_handleIonChange(value: any) {
|
||||
this.handleChangeEvent(value);
|
||||
@HostListener('ionChange', ['$event.target'])
|
||||
_handleIonChange(el: any) {
|
||||
this.handleChangeEvent(el, el.value);
|
||||
}
|
||||
|
||||
registerOnChange(fn: (_: number | null) => void) {
|
||||
|
||||
@@ -20,8 +20,8 @@ export class RadioValueAccessor extends ValueAccessor {
|
||||
super(el);
|
||||
}
|
||||
|
||||
@HostListener('ionSelect', ['$event.target.checked'])
|
||||
_handleIonSelect(value: any) {
|
||||
this.handleChangeEvent(value);
|
||||
@HostListener('ionSelect', ['$event.target'])
|
||||
_handleIonSelect(el: any) {
|
||||
this.handleChangeEvent(el, el.checked);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,8 +20,8 @@ export class SelectValueAccessor extends ValueAccessor {
|
||||
super(el);
|
||||
}
|
||||
|
||||
@HostListener('ionChange', ['$event.target.value'])
|
||||
_handleChangeEvent(value: any) {
|
||||
this.handleChangeEvent(value);
|
||||
@HostListener('ionChange', ['$event.target'])
|
||||
_handleChangeEvent(el: any) {
|
||||
this.handleChangeEvent(el, el.value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,8 +20,8 @@ export class TextValueAccessor extends ValueAccessor {
|
||||
super(el);
|
||||
}
|
||||
|
||||
@HostListener('ionChange', ['$event.target.value'])
|
||||
_handleInputEvent(value: any) {
|
||||
this.handleChangeEvent(value);
|
||||
@HostListener('ionChange', ['$event.target'])
|
||||
_handleInputEvent(el: any) {
|
||||
this.handleChangeEvent(el, el.value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { ElementRef, HostListener } from '@angular/core';
|
||||
import { ControlValueAccessor } from '@angular/forms';
|
||||
|
||||
import { raf } from '../../util/util';
|
||||
|
||||
export class ValueAccessor implements ControlValueAccessor {
|
||||
|
||||
private onChange: (value: any) => void = () => {/**/};
|
||||
@@ -14,18 +16,22 @@ export class ValueAccessor implements ControlValueAccessor {
|
||||
setIonicClasses(this.el);
|
||||
}
|
||||
|
||||
handleChangeEvent(value: any) {
|
||||
if (value !== this.lastValue) {
|
||||
this.lastValue = value;
|
||||
this.onChange(value);
|
||||
handleChangeEvent(el: HTMLElement, value: any) {
|
||||
if (el === this.el.nativeElement) {
|
||||
if (value !== this.lastValue) {
|
||||
this.lastValue = value;
|
||||
this.onChange(value);
|
||||
}
|
||||
setIonicClasses(this.el);
|
||||
}
|
||||
setIonicClasses(this.el);
|
||||
}
|
||||
|
||||
@HostListener('ionBlur')
|
||||
_handleBlurEvent() {
|
||||
this.onTouched();
|
||||
setIonicClasses(this.el);
|
||||
@HostListener('ionBlur', ['$event.target'])
|
||||
_handleBlurEvent(el: any) {
|
||||
if (el === this.el.nativeElement) {
|
||||
this.onTouched();
|
||||
setIonicClasses(this.el);
|
||||
}
|
||||
}
|
||||
|
||||
registerOnChange(fn: (value: any) => void) {
|
||||
@@ -41,8 +47,8 @@ export class ValueAccessor implements ControlValueAccessor {
|
||||
}
|
||||
}
|
||||
|
||||
export function setIonicClasses(element: ElementRef) {
|
||||
requestAnimationFrame(() => {
|
||||
export const setIonicClasses = (element: ElementRef) => {
|
||||
raf(() => {
|
||||
const input = element.nativeElement as HTMLElement;
|
||||
const classes = getClasses(input);
|
||||
setClasses(input, classes);
|
||||
@@ -52,9 +58,9 @@ export function setIonicClasses(element: ElementRef) {
|
||||
setClasses(item, classes);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
function getClasses(element: HTMLElement) {
|
||||
const getClasses = (element: HTMLElement) => {
|
||||
const classList = element.classList;
|
||||
const classes = [];
|
||||
for (let i = 0; i < classList.length; i++) {
|
||||
@@ -64,9 +70,9 @@ function getClasses(element: HTMLElement) {
|
||||
}
|
||||
}
|
||||
return classes;
|
||||
}
|
||||
};
|
||||
|
||||
function setClasses(element: HTMLElement, classes: string[]) {
|
||||
const setClasses = (element: HTMLElement, classes: string[]) => {
|
||||
const classList = element.classList;
|
||||
|
||||
classList.remove(
|
||||
@@ -78,8 +84,8 @@ function setClasses(element: HTMLElement, classes: string[]) {
|
||||
'ion-pristine'
|
||||
);
|
||||
classList.add(...classes);
|
||||
}
|
||||
};
|
||||
|
||||
function startsWith(input: string, search: string): boolean {
|
||||
const startsWith = (input: string, search: string): boolean => {
|
||||
return input.substr(0, search.length) === search;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Attribute, ChangeDetectorRef, ComponentFactoryResolver, ComponentRef, Directive, ElementRef, EventEmitter, Injector, NgZone, OnDestroy, OnInit, Optional, Output, SkipSelf, ViewContainerRef } from '@angular/core';
|
||||
import { Location } from '@angular/common';
|
||||
import { Attribute, ComponentFactoryResolver, ComponentRef, Directive, ElementRef, EventEmitter, Injector, NgZone, OnDestroy, OnInit, Optional, Output, SkipSelf, ViewContainerRef } from '@angular/core';
|
||||
import { ActivatedRoute, ChildrenOutletContexts, OutletContext, PRIMARY_OUTLET, Router } from '@angular/router';
|
||||
import { BehaviorSubject, Observable } from 'rxjs';
|
||||
import { distinctUntilChanged, filter, switchMap } from 'rxjs/operators';
|
||||
@@ -56,9 +57,9 @@ export class IonRouterOutlet implements OnDestroy, OnInit {
|
||||
private resolver: ComponentFactoryResolver,
|
||||
@Attribute('name') name: string,
|
||||
@Optional() @Attribute('tabs') tabs: string,
|
||||
private changeDetector: ChangeDetectorRef,
|
||||
private config: Config,
|
||||
private navCtrl: NavController,
|
||||
commonLocation: Location,
|
||||
elementRef: ElementRef,
|
||||
router: Router,
|
||||
zone: NgZone,
|
||||
@@ -68,7 +69,7 @@ export class IonRouterOutlet implements OnDestroy, OnInit {
|
||||
this.nativeEl = elementRef.nativeElement;
|
||||
this.name = name || PRIMARY_OUTLET;
|
||||
this.tabsPrefix = tabs === 'true' ? getUrl(router, activatedRoute) : undefined;
|
||||
this.stackCtrl = new StackController(this.tabsPrefix, this.nativeEl, router, navCtrl, zone);
|
||||
this.stackCtrl = new StackController(this.tabsPrefix, this.nativeEl, router, navCtrl, zone, commonLocation);
|
||||
parentContexts.onChildOutletCreated(this.name, this as any);
|
||||
}
|
||||
|
||||
@@ -92,7 +93,7 @@ export class IonRouterOutlet implements OnDestroy, OnInit {
|
||||
if ((this.nativeEl as any).componentOnReady) {
|
||||
this.nativeEl.componentOnReady().then(() => {
|
||||
if (this._swipeGesture === undefined) {
|
||||
this.swipeGesture = this.config.getBoolean('swipeBackEnabled', this.nativeEl.mode === 'ios');
|
||||
this.swipeGesture = this.config.getBoolean('swipeBackEnabled', (this.nativeEl as any).mode === 'ios');
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -141,6 +142,20 @@ export class IonRouterOutlet implements OnDestroy, OnInit {
|
||||
if (this.activated) {
|
||||
if (this.activatedView) {
|
||||
this.activatedView.savedData = new Map(this.getContext()!.children['contexts']);
|
||||
|
||||
/**
|
||||
* Ensure we are saving the NavigationExtras
|
||||
* data otherwise it will be lost
|
||||
*/
|
||||
this.activatedView.savedExtras = {};
|
||||
const context = this.getContext()!;
|
||||
|
||||
if (context.route) {
|
||||
const contextSnapshot = context.route.snapshot;
|
||||
|
||||
this.activatedView.savedExtras.queryParams = contextSnapshot.queryParams;
|
||||
this.activatedView.savedExtras.fragment = contextSnapshot.fragment;
|
||||
}
|
||||
}
|
||||
const c = this.component;
|
||||
this.activatedView = null;
|
||||
@@ -194,8 +209,6 @@ export class IonRouterOutlet implements OnDestroy, OnInit {
|
||||
// Store references to the proxy by component
|
||||
this.proxyMap.set(cmpRef.instance, activatedRouteProxy);
|
||||
this.currentActivatedRoute$.next({ component: cmpRef.instance, activatedRoute });
|
||||
|
||||
this.changeDetector.markForCheck();
|
||||
}
|
||||
|
||||
this.activatedView = enteringView;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { Location } from '@angular/common';
|
||||
import { ComponentRef, NgZone } from '@angular/core';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { RouterDirection } from '@ionic/core';
|
||||
@@ -22,6 +23,7 @@ export class StackController {
|
||||
private router: Router,
|
||||
private navCtrl: NavController,
|
||||
private zone: NgZone,
|
||||
private location: Location
|
||||
) {
|
||||
this.tabsPrefix = tabsPrefix !== undefined ? toSegments(tabsPrefix) : undefined;
|
||||
}
|
||||
@@ -29,7 +31,7 @@ export class StackController {
|
||||
createView(ref: ComponentRef<any>, activatedRoute: ActivatedRoute): RouteView {
|
||||
const url = getUrl(this.router, activatedRoute);
|
||||
const element = (ref && ref.location && ref.location.nativeElement) as HTMLElement;
|
||||
const unlistenEvents = bindLifecycleEvents(ref.instance, element);
|
||||
const unlistenEvents = bindLifecycleEvents(this.zone, ref.instance, element);
|
||||
return {
|
||||
id: this.nextId++,
|
||||
stackId: computeStackId(this.tabsPrefix, url),
|
||||
@@ -57,9 +59,25 @@ export class StackController {
|
||||
direction = 'back';
|
||||
animation = undefined;
|
||||
}
|
||||
|
||||
const viewsSnapshot = this.views.slice();
|
||||
|
||||
const currentNavigation = this.router.getCurrentNavigation();
|
||||
let currentNavigation;
|
||||
|
||||
const router = (this.router as any);
|
||||
|
||||
// Angular >= 7.2.0
|
||||
if (router.getCurrentNavigation) {
|
||||
currentNavigation = router.getCurrentNavigation();
|
||||
|
||||
// Angular < 7.2.0
|
||||
} else if (
|
||||
router.navigations &&
|
||||
router.navigations.value
|
||||
) {
|
||||
currentNavigation = router.navigations.value;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the navigation action
|
||||
* sets `replaceUrl: true`
|
||||
@@ -77,16 +95,36 @@ export class StackController {
|
||||
}
|
||||
}
|
||||
|
||||
const reused = this.views.includes(enteringView);
|
||||
const views = this.insertView(enteringView, direction);
|
||||
return this.wait(async () => {
|
||||
await this.transition(enteringView, leavingView, animation, this.canGoBack(1), false);
|
||||
await cleanupAsync(enteringView, views, viewsSnapshot);
|
||||
return {
|
||||
enteringView,
|
||||
direction,
|
||||
animation,
|
||||
tabSwitch
|
||||
};
|
||||
|
||||
// Trigger change detection before transition starts
|
||||
// This will call ngOnInit() the first time too, just after the view
|
||||
// was attached to the dom, but BEFORE the transition starts
|
||||
if (!reused) {
|
||||
enteringView.ref.changeDetectorRef.detectChanges();
|
||||
}
|
||||
|
||||
// Wait until previous transitions finish
|
||||
return this.zone.runOutsideAngular(() => {
|
||||
return this.wait(() => {
|
||||
// disconnect leaving page from change detection to
|
||||
// reduce jank during the page transition
|
||||
if (leavingView) {
|
||||
leavingView.ref.changeDetectorRef.detach();
|
||||
}
|
||||
// In case the enteringView is the same as the leavingPage we need to reattach()
|
||||
enteringView.ref.changeDetectorRef.reattach();
|
||||
|
||||
return this.transition(enteringView, leavingView, animation, this.canGoBack(1), false)
|
||||
.then(() => cleanupAsync(enteringView, views, viewsSnapshot, this.location))
|
||||
.then(() => ({
|
||||
enteringView,
|
||||
direction,
|
||||
animation,
|
||||
tabSwitch
|
||||
}));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -101,32 +139,50 @@ export class StackController {
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
const view = views[views.length - deep - 1];
|
||||
return this.navCtrl.navigateBack(view.url).then(() => true);
|
||||
let url = view.url;
|
||||
|
||||
const viewSavedData = view.savedData;
|
||||
if (viewSavedData) {
|
||||
const primaryOutlet = viewSavedData.get('primary');
|
||||
if (
|
||||
primaryOutlet &&
|
||||
primaryOutlet.route &&
|
||||
primaryOutlet.route._routerState &&
|
||||
primaryOutlet.route._routerState.snapshot &&
|
||||
primaryOutlet.route._routerState.snapshot.url
|
||||
) {
|
||||
url = primaryOutlet.route._routerState.snapshot.url;
|
||||
}
|
||||
}
|
||||
|
||||
return this.navCtrl.navigateBack(url, view.savedExtras).then(() => true);
|
||||
});
|
||||
}
|
||||
|
||||
async startBackTransition() {
|
||||
startBackTransition() {
|
||||
const leavingView = this.activeView;
|
||||
if (leavingView) {
|
||||
const views = this.getStack(leavingView.stackId);
|
||||
const enteringView = views[views.length - 2];
|
||||
enteringView.ref.changeDetectorRef.reattach();
|
||||
await this.wait(() => {
|
||||
return this.wait(() => {
|
||||
return this.transition(
|
||||
enteringView, // entering view
|
||||
leavingView, // leaving view
|
||||
'back',
|
||||
true,
|
||||
this.canGoBack(2),
|
||||
true
|
||||
);
|
||||
});
|
||||
}
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
endBackTransition(shouldComplete: boolean) {
|
||||
if (shouldComplete) {
|
||||
this.skipTransition = true;
|
||||
this.pop(1);
|
||||
} else if (this.activeView) {
|
||||
cleanup(this.activeView, this.views, this.views, this.location);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,7 +212,7 @@ export class StackController {
|
||||
return this.views.slice();
|
||||
}
|
||||
|
||||
private async transition(
|
||||
private transition(
|
||||
enteringView: RouteView | undefined,
|
||||
leavingView: RouteView | undefined,
|
||||
direction: 'forward' | 'back' | undefined,
|
||||
@@ -165,7 +221,10 @@ export class StackController {
|
||||
) {
|
||||
if (this.skipTransition) {
|
||||
this.skipTransition = false;
|
||||
return;
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
if (leavingView === enteringView) {
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
const enteringEl = enteringView ? enteringView.element : undefined;
|
||||
const leavingEl = leavingView ? leavingView.element : undefined;
|
||||
@@ -176,15 +235,17 @@ export class StackController {
|
||||
containerEl.appendChild(enteringEl);
|
||||
}
|
||||
|
||||
await containerEl.componentOnReady();
|
||||
await containerEl.commit(enteringEl, leavingEl, {
|
||||
deepWait: true,
|
||||
duration: direction === undefined ? 0 : undefined,
|
||||
direction,
|
||||
showGoBack,
|
||||
progressAnimation
|
||||
});
|
||||
if ((containerEl as any).commit) {
|
||||
return containerEl.commit(enteringEl, leavingEl, {
|
||||
deepWait: true,
|
||||
duration: direction === undefined ? 0 : undefined,
|
||||
direction,
|
||||
showGoBack,
|
||||
progressAnimation
|
||||
});
|
||||
}
|
||||
}
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
private async wait<T>(task: () => Promise<T>): Promise<T> {
|
||||
@@ -197,26 +258,41 @@ export class StackController {
|
||||
}
|
||||
}
|
||||
|
||||
function cleanupAsync(activeRoute: RouteView, views: RouteView[], viewsSnapshot: RouteView[]) {
|
||||
return new Promise(resolve => {
|
||||
requestAnimationFrame(() => {
|
||||
cleanup(activeRoute, views, viewsSnapshot);
|
||||
resolve();
|
||||
const cleanupAsync = (activeRoute: RouteView, views: RouteView[], viewsSnapshot: RouteView[], location: Location) => {
|
||||
if (typeof (requestAnimationFrame as any) === 'function') {
|
||||
return new Promise<any>(resolve => {
|
||||
requestAnimationFrame(() => {
|
||||
cleanup(activeRoute, views, viewsSnapshot, location);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
return Promise.resolve();
|
||||
};
|
||||
|
||||
function cleanup(activeRoute: RouteView, views: RouteView[], viewsSnapshot: RouteView[]) {
|
||||
const cleanup = (activeRoute: RouteView, views: RouteView[], viewsSnapshot: RouteView[], location: Location) => {
|
||||
viewsSnapshot
|
||||
.filter(view => !views.includes(view))
|
||||
.forEach(destroyView);
|
||||
|
||||
views.forEach(view => {
|
||||
if (view !== activeRoute) {
|
||||
/**
|
||||
* In the event that a user navigated multiple
|
||||
* times in rapid succession, we want to make sure
|
||||
* we don't pre-emptively detach a view while
|
||||
* it is in mid-transition.
|
||||
*
|
||||
* In this instance we also do not care about query
|
||||
* params or fragments as it will be the same view regardless
|
||||
*/
|
||||
const locationWithoutParams = location.path().split('?')[0];
|
||||
const locationWithoutFragment = locationWithoutParams.split('#')[0];
|
||||
|
||||
if (view !== activeRoute && view.url !== locationWithoutFragment) {
|
||||
const element = view.element;
|
||||
element.setAttribute('aria-hidden', 'true');
|
||||
element.classList.add('ion-page-hidden');
|
||||
view.ref.changeDetectorRef.detach();
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { ComponentRef } from '@angular/core';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { ActivatedRoute, NavigationExtras, Router } from '@angular/router';
|
||||
import { NavDirection, RouterDirection } from '@ionic/core';
|
||||
|
||||
export function insertView(views: RouteView[], view: RouteView, direction: RouterDirection) {
|
||||
export const insertView = (views: RouteView[], view: RouteView, direction: RouterDirection) => {
|
||||
if (direction === 'root') {
|
||||
return setRoot(views, view);
|
||||
} else if (direction === 'forward') {
|
||||
@@ -10,15 +10,15 @@ export function insertView(views: RouteView[], view: RouteView, direction: Route
|
||||
} else {
|
||||
return setBack(views, view);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function setRoot(views: RouteView[], view: RouteView) {
|
||||
const setRoot = (views: RouteView[], view: RouteView) => {
|
||||
views = views.filter(v => v.stackId !== view.stackId);
|
||||
views.push(view);
|
||||
return views;
|
||||
}
|
||||
};
|
||||
|
||||
function setForward(views: RouteView[], view: RouteView) {
|
||||
const setForward = (views: RouteView[], view: RouteView) => {
|
||||
const index = views.indexOf(view);
|
||||
if (index >= 0) {
|
||||
views = views.filter(v => v.stackId !== view.stackId || v.id <= view.id);
|
||||
@@ -26,30 +26,30 @@ function setForward(views: RouteView[], view: RouteView) {
|
||||
views.push(view);
|
||||
}
|
||||
return views;
|
||||
}
|
||||
};
|
||||
|
||||
function setBack(views: RouteView[], view: RouteView) {
|
||||
const setBack = (views: RouteView[], view: RouteView) => {
|
||||
const index = views.indexOf(view);
|
||||
if (index >= 0) {
|
||||
return views.filter(v => v.stackId !== view.stackId || v.id <= view.id);
|
||||
} else {
|
||||
return setRoot(views, view);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export function getUrl(router: Router, activatedRoute: ActivatedRoute) {
|
||||
export const getUrl = (router: Router, activatedRoute: ActivatedRoute) => {
|
||||
const urlTree = router.createUrlTree(['.'], { relativeTo: activatedRoute });
|
||||
return router.serializeUrl(urlTree);
|
||||
}
|
||||
};
|
||||
|
||||
export function isTabSwitch(enteringView: RouteView, leavingView: RouteView | undefined) {
|
||||
export const isTabSwitch = (enteringView: RouteView, leavingView: RouteView | undefined) => {
|
||||
if (!leavingView) {
|
||||
return true;
|
||||
}
|
||||
return enteringView.stackId !== leavingView.stackId;
|
||||
}
|
||||
};
|
||||
|
||||
export function computeStackId(prefixUrl: string[] | undefined, url: string) {
|
||||
export const computeStackId = (prefixUrl: string[] | undefined, url: string) => {
|
||||
if (!prefixUrl) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -63,22 +63,22 @@ export function computeStackId(prefixUrl: string[] | undefined, url: string) {
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
||||
export function toSegments(path: string): string[] {
|
||||
export const toSegments = (path: string) => {
|
||||
return path
|
||||
.split('/')
|
||||
.map(s => s.trim())
|
||||
.filter(s => s !== '');
|
||||
}
|
||||
};
|
||||
|
||||
export function destroyView(view: RouteView | undefined) {
|
||||
export const destroyView = (view: RouteView | undefined) => {
|
||||
if (view) {
|
||||
// TODO lifecycle event
|
||||
view.ref.destroy();
|
||||
view.unlistenEvents();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export interface StackEvent {
|
||||
enteringView: RouteView;
|
||||
@@ -94,5 +94,6 @@ export interface RouteView {
|
||||
element: HTMLElement;
|
||||
ref: ComponentRef<any>;
|
||||
savedData?: any;
|
||||
savedExtras?: NavigationExtras;
|
||||
unlistenEvents: () => void;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,9 @@ export function proxyInputs(Cmp: any, inputs: string[]) {
|
||||
inputs.forEach(item => {
|
||||
Object.defineProperty(Prototype, item, {
|
||||
get() { return this.el[item]; },
|
||||
set(val: any) { this.el[item] = val; },
|
||||
set(val: any) {
|
||||
this.z.runOutsideAngular(() => this.el[item] = val);
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -16,7 +18,7 @@ export function proxyMethods(Cmp: any, methods: string[]) {
|
||||
methods.forEach(methodName => {
|
||||
Prototype[methodName] = function() {
|
||||
const args = arguments;
|
||||
return this.el.componentOnReady().then((el: any) => el[methodName].apply(el, args));
|
||||
return this.z.runOutsideAngular(() => this.el[methodName].apply(this.el, args));
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
import { ChangeDetectionStrategy, Component, ContentChild, ElementRef, EmbeddedViewRef, IterableDiffer, IterableDiffers, NgZone, SimpleChanges, TrackByFunction } from '@angular/core';
|
||||
import { Cell, CellType, HeaderFn, ItemHeightFn } from '@ionic/core';
|
||||
import { Cell, CellType, FooterHeightFn, HeaderFn, HeaderHeightFn, ItemHeightFn } from '@ionic/core';
|
||||
|
||||
import { proxyInputs, proxyMethods } from '../proxies-utils';
|
||||
|
||||
@@ -75,7 +75,7 @@ export declare interface IonVirtualScroll {
|
||||
|
||||
/**
|
||||
* An optional function that maps each item within their height.
|
||||
* When this function is provides, heavy optimizations and fast path can be taked by
|
||||
* When this function is provided, heavy optimizations and fast path can be taked by
|
||||
* `ion-virtual-scroll` leading to massive performance improvements.
|
||||
*
|
||||
* This function allows to skip all DOM reads, which can be Doing so leads
|
||||
@@ -83,6 +83,16 @@ export declare interface IonVirtualScroll {
|
||||
*/
|
||||
itemHeight?: ItemHeightFn;
|
||||
|
||||
/**
|
||||
* An optional function that maps each item header within their height.
|
||||
*/
|
||||
headerHeight?: HeaderHeightFn;
|
||||
|
||||
/**
|
||||
* An optional function that maps each item footer within their height.
|
||||
*/
|
||||
footerHeight?: FooterHeightFn;
|
||||
|
||||
/**
|
||||
* Same as `ngForTrackBy` which can be used on `ngFor`.
|
||||
*/
|
||||
@@ -114,6 +124,8 @@ export declare interface IonVirtualScroll {
|
||||
'footerFn',
|
||||
'items',
|
||||
'itemHeight',
|
||||
'headerHeight',
|
||||
'footerHeight',
|
||||
'trackBy'
|
||||
]
|
||||
})
|
||||
@@ -128,7 +140,7 @@ export class IonVirtualScroll {
|
||||
@ContentChild(VirtualFooter) ftrTmp!: VirtualFooter;
|
||||
|
||||
constructor(
|
||||
private zone: NgZone,
|
||||
private z: NgZone,
|
||||
private iterableDiffers: IterableDiffers,
|
||||
elementRef: ElementRef,
|
||||
) {
|
||||
@@ -162,7 +174,7 @@ export class IonVirtualScroll {
|
||||
}
|
||||
|
||||
private nodeRender(el: HTMLElement | null, cell: Cell, index: number): HTMLElement {
|
||||
return this.zone.run(() => {
|
||||
return this.z.run(() => {
|
||||
let node: EmbeddedViewRef<VirtualContext>;
|
||||
if (!el) {
|
||||
node = this.itmTmp.viewContainer.createEmbeddedView(
|
||||
@@ -194,7 +206,7 @@ export class IonVirtualScroll {
|
||||
}
|
||||
}
|
||||
|
||||
function getElement(view: EmbeddedViewRef<VirtualContext>): HTMLElement {
|
||||
const getElement = (view: EmbeddedViewRef<VirtualContext>): HTMLElement => {
|
||||
const rootNodes = view.rootNodes;
|
||||
for (let i = 0; i < rootNodes.length; i++) {
|
||||
if (rootNodes[i].nodeType === 1) {
|
||||
@@ -202,7 +214,7 @@ function getElement(view: EmbeddedViewRef<VirtualContext>): HTMLElement {
|
||||
}
|
||||
}
|
||||
throw new Error('virtual element was not created');
|
||||
}
|
||||
};
|
||||
|
||||
proxyInputs(IonVirtualScroll, [
|
||||
'approxItemHeight',
|
||||
@@ -211,7 +223,9 @@ proxyInputs(IonVirtualScroll, [
|
||||
'headerFn',
|
||||
'footerFn',
|
||||
'items',
|
||||
'itemHeight'
|
||||
'itemHeight',
|
||||
'headerHeight',
|
||||
'footerHeight'
|
||||
]);
|
||||
|
||||
proxyMethods(IonVirtualScroll, [
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { CommonModule, DOCUMENT } from '@angular/common';
|
||||
import { APP_INITIALIZER, ModuleWithProviders, NgModule } from '@angular/core';
|
||||
import { APP_INITIALIZER, ModuleWithProviders, NgModule, NgZone } from '@angular/core';
|
||||
import { IonicConfig } from '@ionic/core';
|
||||
|
||||
import { appInitialize } from './app-initialize';
|
||||
@@ -142,7 +142,8 @@ export class IonicModule {
|
||||
multi: true,
|
||||
deps: [
|
||||
ConfigToken,
|
||||
DOCUMENT
|
||||
DOCUMENT,
|
||||
NgZone
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { DOCUMENT } from '@angular/common';
|
||||
import { Inject, Injectable } from '@angular/core';
|
||||
import { ActionSheetOptions } from '@ionic/core';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { ActionSheetOptions, actionSheetController } from '@ionic/core';
|
||||
|
||||
import { OverlayBaseController } from '../util/overlay';
|
||||
|
||||
@@ -8,7 +7,7 @@ import { OverlayBaseController } from '../util/overlay';
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class ActionSheetController extends OverlayBaseController<ActionSheetOptions, HTMLIonActionSheetElement> {
|
||||
constructor(@Inject(DOCUMENT) doc: any) {
|
||||
super('ion-action-sheet-controller', doc);
|
||||
constructor() {
|
||||
super(actionSheetController);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { DOCUMENT } from '@angular/common';
|
||||
import { Inject, Injectable } from '@angular/core';
|
||||
import { AlertOptions } from '@ionic/core';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { AlertOptions, alertController } from '@ionic/core';
|
||||
|
||||
import { OverlayBaseController } from '../util/overlay';
|
||||
|
||||
@@ -8,7 +7,7 @@ import { OverlayBaseController } from '../util/overlay';
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class AlertController extends OverlayBaseController<AlertOptions, HTMLIonAlertElement> {
|
||||
constructor(@Inject(DOCUMENT) doc: any) {
|
||||
super('ion-alert-controller', doc);
|
||||
constructor() {
|
||||
super(alertController);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,10 +34,10 @@ export class AngularFrameworkDelegate implements FrameworkDelegate {
|
||||
) {}
|
||||
|
||||
attachViewToDom(container: any, component: any, params?: any, cssClasses?: string[]): Promise<any> {
|
||||
return new Promise(resolve => {
|
||||
this.zone.run(() => {
|
||||
return this.zone.run(() => {
|
||||
return new Promise(resolve => {
|
||||
const el = attachView(
|
||||
this.resolver, this.injector, this.location, this.appRef,
|
||||
this.zone, this.resolver, this.injector, this.location, this.appRef,
|
||||
this.elRefMap, this.elEventsMap,
|
||||
container, component, params, cssClasses
|
||||
);
|
||||
@@ -47,8 +47,8 @@ export class AngularFrameworkDelegate implements FrameworkDelegate {
|
||||
}
|
||||
|
||||
removeViewFromDom(_container: any, component: any): Promise<void> {
|
||||
return new Promise(resolve => {
|
||||
this.zone.run(() => {
|
||||
return this.zone.run(() => {
|
||||
return new Promise(resolve => {
|
||||
const componentRef = this.elRefMap.get(component);
|
||||
if (componentRef) {
|
||||
componentRef.destroy();
|
||||
@@ -65,7 +65,8 @@ export class AngularFrameworkDelegate implements FrameworkDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
export function attachView(
|
||||
export const attachView = (
|
||||
zone: NgZone,
|
||||
resolver: ComponentFactoryResolver,
|
||||
injector: Injector,
|
||||
location: ViewContainerRef | undefined,
|
||||
@@ -73,7 +74,7 @@ export function attachView(
|
||||
elRefMap: WeakMap<HTMLElement, any>,
|
||||
elEventsMap: WeakMap<HTMLElement, () => void>,
|
||||
container: any, component: any, params: any, cssClasses: string[] | undefined
|
||||
) {
|
||||
) => {
|
||||
const factory = resolver.resolveComponentFactory(component);
|
||||
const childInjector = Injector.create({
|
||||
providers: getProviders(params),
|
||||
@@ -93,7 +94,7 @@ export function attachView(
|
||||
hostElement.classList.add(clazz);
|
||||
}
|
||||
}
|
||||
const unbindEvents = bindLifecycleEvents(instance, hostElement);
|
||||
const unbindEvents = bindLifecycleEvents(zone, instance, hostElement);
|
||||
container.appendChild(hostElement);
|
||||
|
||||
if (!location) {
|
||||
@@ -103,7 +104,7 @@ export function attachView(
|
||||
elRefMap.set(hostElement, componentRef);
|
||||
elEventsMap.set(hostElement, unbindEvents);
|
||||
return hostElement;
|
||||
}
|
||||
};
|
||||
|
||||
const LIFECYCLES = [
|
||||
LIFECYCLE_WILL_ENTER,
|
||||
@@ -113,26 +114,22 @@ const LIFECYCLES = [
|
||||
LIFECYCLE_WILL_UNLOAD
|
||||
];
|
||||
|
||||
export function bindLifecycleEvents(instance: any, element: HTMLElement) {
|
||||
const unregisters = LIFECYCLES.map(eventName => {
|
||||
const handler = (ev: any) => {
|
||||
if (typeof instance[eventName] === 'function') {
|
||||
instance[eventName](ev.detail);
|
||||
}
|
||||
};
|
||||
element.addEventListener(eventName, handler);
|
||||
return () => {
|
||||
element.removeEventListener(eventName, handler);
|
||||
};
|
||||
export const bindLifecycleEvents = (zone: NgZone, instance: any, element: HTMLElement) => {
|
||||
return zone.run(() => {
|
||||
const unregisters = LIFECYCLES
|
||||
.filter(eventName => typeof instance[eventName] === 'function')
|
||||
.map(eventName => {
|
||||
const handler = (ev: any) => instance[eventName](ev.detail);
|
||||
element.addEventListener(eventName, handler);
|
||||
return () => element.removeEventListener(eventName, handler);
|
||||
});
|
||||
return () => unregisters.forEach(fn => fn());
|
||||
});
|
||||
return () => {
|
||||
unregisters.forEach(fn => fn());
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
const NavParamsToken = new InjectionToken<any>('NavParamsToken');
|
||||
|
||||
function getProviders(params: {[key: string]: any}) {
|
||||
const getProviders = (params: {[key: string]: any}) => {
|
||||
return [
|
||||
{
|
||||
provide: NavParamsToken, useValue: params
|
||||
@@ -141,8 +138,8 @@ function getProviders(params: {[key: string]: any}) {
|
||||
provide: NavParams, useFactory: provideNavParamsInjectable, deps: [NavParamsToken]
|
||||
}
|
||||
];
|
||||
}
|
||||
};
|
||||
|
||||
function provideNavParamsInjectable(params: {[key: string]: any}) {
|
||||
const provideNavParamsInjectable = (params: {[key: string]: any}) => {
|
||||
return new NavParams(params);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -42,7 +42,7 @@ export class Config {
|
||||
|
||||
export const ConfigToken = new InjectionToken<any>('USERCONFIG');
|
||||
|
||||
function getConfig(): CoreConfig | null {
|
||||
const getConfig = (): CoreConfig | null => {
|
||||
if (typeof (window as any) !== 'undefined') {
|
||||
const Ionic = (window as IonicWindow).Ionic;
|
||||
if (Ionic && Ionic.config) {
|
||||
@@ -50,4 +50,4 @@ function getConfig(): CoreConfig | null {
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -22,7 +22,7 @@ export class DomController {
|
||||
}
|
||||
}
|
||||
|
||||
function getQueue() {
|
||||
const getQueue = () => {
|
||||
const win = typeof (window as any) !== 'undefined' ? window : null as any;
|
||||
|
||||
if (win != null) {
|
||||
@@ -41,6 +41,6 @@ function getQueue() {
|
||||
read: (cb: any) => cb(),
|
||||
write: (cb: any) => cb()
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
export type RafCallback = (timeStamp?: number) => void;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { DOCUMENT } from '@angular/common';
|
||||
import { Inject, Injectable } from '@angular/core';
|
||||
import { LoadingOptions } from '@ionic/core';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { LoadingOptions, loadingController } from '@ionic/core';
|
||||
|
||||
import { OverlayBaseController } from '../util/overlay';
|
||||
|
||||
@@ -8,7 +7,7 @@ import { OverlayBaseController } from '../util/overlay';
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class LoadingController extends OverlayBaseController<LoadingOptions, HTMLIonLoadingElement> {
|
||||
constructor(@Inject(DOCUMENT) doc: any) {
|
||||
super('ion-loading-controller', doc);
|
||||
constructor() {
|
||||
super(loadingController);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,9 +59,21 @@ export class MenuController {
|
||||
* @param shouldEnable True if it should be swipe-able, false if not.
|
||||
* @param [menuId] Optionally get the menu by its id, or side.
|
||||
* @return Returns the instance of the menu, which is useful for chaining.
|
||||
* @deprecated Use swipeGesture() instead
|
||||
*/
|
||||
swipeEnable(shouldEnable: boolean, menuId?: string): Promise<HTMLIonMenuElement> {
|
||||
return proxyMethod(CTRL, this.doc, 'swipeEnable', shouldEnable, menuId);
|
||||
console.warn('MenuController.swipeEnable is deprecated. Use MenuController.swipeGesture() instead');
|
||||
return this.swipeGesture(shouldEnable, menuId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to enable or disable the ability to swipe open the menu.
|
||||
* @param shouldEnable True if it should be swipe-able, false if not.
|
||||
* @param [menuId] Optionally get the menu by its id, or side.
|
||||
* @return Returns the instance of the menu, which is useful for chaining.
|
||||
*/
|
||||
swipeGesture(shouldEnable: boolean, menuId?: string): Promise<HTMLIonMenuElement> {
|
||||
return proxyMethod(CTRL, this.doc, 'swipeGesture', shouldEnable, menuId);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { DOCUMENT } from '@angular/common';
|
||||
import { ComponentFactoryResolver, Inject, Injectable, Injector } from '@angular/core';
|
||||
import { ModalOptions } from '@ionic/core';
|
||||
import { ComponentFactoryResolver, Injectable, Injector } from '@angular/core';
|
||||
import { ModalOptions, modalController } from '@ionic/core';
|
||||
|
||||
import { OverlayBaseController } from '../util/overlay';
|
||||
|
||||
@@ -13,9 +12,8 @@ export class ModalController extends OverlayBaseController<ModalOptions, HTMLIon
|
||||
private angularDelegate: AngularDelegate,
|
||||
private resolver: ComponentFactoryResolver,
|
||||
private injector: Injector,
|
||||
@Inject(DOCUMENT) doc: any
|
||||
) {
|
||||
super('ion-modal-controller', doc);
|
||||
super(modalController);
|
||||
}
|
||||
|
||||
create(opts: ModalOptions): Promise<HTMLIonModalElement> {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Location } from '@angular/common';
|
||||
import { Injectable, Optional } from '@angular/core';
|
||||
import { NavigationExtras, NavigationStart, Router, UrlTree } from '@angular/router';
|
||||
import { NavigationExtras, NavigationStart, Router, UrlSerializer, UrlTree } from '@angular/router';
|
||||
import { NavDirection, RouterDirection } from '@ionic/core';
|
||||
|
||||
import { IonRouterOutlet } from '../directives/navigation/ion-router-outlet';
|
||||
@@ -29,6 +29,7 @@ export class NavController {
|
||||
constructor(
|
||||
platform: Platform,
|
||||
private location: Location,
|
||||
private serializer: UrlSerializer,
|
||||
@Optional() private router?: Router,
|
||||
) {
|
||||
// Subscribe to router events to detect direction
|
||||
@@ -49,12 +50,12 @@ export class NavController {
|
||||
|
||||
/**
|
||||
* This method uses Angular's [Router](https://angular.io/api/router/Router) under the hood,
|
||||
* it's equivalent to call `this.router.navigateByUrl()`, but it's explicit about the **direction** of the transition.
|
||||
* it's equivalent to calling `this.router.navigateByUrl()`, but it's explicit about the **direction** of the transition.
|
||||
*
|
||||
* Going **forward** means that a new page it's going to be pushed to the stack of the outlet (ion-router-outlet),
|
||||
* Going **forward** means that a new page is going to be pushed to the stack of the outlet (ion-router-outlet),
|
||||
* and that it will show a "forward" animation by default.
|
||||
*
|
||||
* Navigating forward can also be trigger in a declarative manner by using the `[routerDirection]` directive:
|
||||
* Navigating forward can also be triggered in a declarative manner by using the `[routerDirection]` directive:
|
||||
*
|
||||
* ```html
|
||||
* <a routerLink="/path/to/page" routerDirection="forward">Link</a>
|
||||
@@ -67,17 +68,17 @@ export class NavController {
|
||||
|
||||
/**
|
||||
* This method uses Angular's [Router](https://angular.io/api/router/Router) under the hood,
|
||||
* it's equivalent to call:
|
||||
* it's equivalent to calling:
|
||||
*
|
||||
* ```ts
|
||||
* this.navController.setDirection('back');
|
||||
* this.router.navigateByUrl(path);
|
||||
* ```
|
||||
*
|
||||
* Going **back** means that all the pages in the stack until the navigated page is found will be pop,
|
||||
* Going **back** means that all the pages in the stack until the navigated page is found will be popped,
|
||||
* and that it will show a "back" animation by default.
|
||||
*
|
||||
* Navigating back can also be trigger in a declarative manner by using the `[routerDirection]` directive:
|
||||
* Navigating back can also be triggered in a declarative manner by using the `[routerDirection]` directive:
|
||||
*
|
||||
* ```html
|
||||
* <a routerLink="/path/to/page" routerDirection="back">Link</a>
|
||||
@@ -90,7 +91,7 @@ export class NavController {
|
||||
|
||||
/**
|
||||
* This method uses Angular's [Router](https://angular.io/api/router/Router) under the hood,
|
||||
* it's equivalent to call:
|
||||
* it's equivalent to calling:
|
||||
*
|
||||
* ```ts
|
||||
* this.navController.setDirection('root');
|
||||
@@ -100,7 +101,7 @@ export class NavController {
|
||||
* Going **root** means that all existing pages in the stack will be removed,
|
||||
* and the navigated page will become the single page in the stack.
|
||||
*
|
||||
* Navigating root can also be trigger in a declarative manner by using the `[routerDirection]` directive:
|
||||
* Navigating root can also be triggered in a declarative manner by using the `[routerDirection]` directive:
|
||||
*
|
||||
* ```html
|
||||
* <a routerLink="/path/to/page" routerDirection="root">Link</a>
|
||||
@@ -113,7 +114,8 @@ export class NavController {
|
||||
|
||||
/**
|
||||
* Same as [Location](https://angular.io/api/common/Location)'s back() method.
|
||||
* It will use the standard `window.history.back()` under the hood, but featuring a `back` animation.
|
||||
* It will use the standard `window.history.back()` under the hood, but featuring a `back` animation
|
||||
* by default.
|
||||
*/
|
||||
back(options: AnimationOptions = { animated: true, animationDirection: 'back' }) {
|
||||
this.setDirection('back', options.animated, options.animationDirection);
|
||||
@@ -121,9 +123,9 @@ export class NavController {
|
||||
}
|
||||
|
||||
/**
|
||||
* This methods goes back in the context of ionic's stack navigation.
|
||||
* This methods goes back in the context of Ionic's stack navigation.
|
||||
*
|
||||
* It recursivelly finds the top active `ion-router-outlet` and calls `pop()`.
|
||||
* It recursively finds the top active `ion-router-outlet` and calls `pop()`.
|
||||
* This is the recommended way to go back when you are using `ion-router-outlet`.
|
||||
*/
|
||||
async pop() {
|
||||
@@ -139,11 +141,11 @@ export class NavController {
|
||||
}
|
||||
|
||||
/**
|
||||
* This methods specifies the direction of the next navigation performed by the angular router.
|
||||
* This methods specifies the direction of the next navigation performed by the Angular router.
|
||||
*
|
||||
* `setDirection()` does not trigger any transition, it just sets a set of flags to be consumed by `ion-router-outlet`.
|
||||
* `setDirection()` does not trigger any transition, it just sets some flags to be consumed by `ion-router-outlet`.
|
||||
*
|
||||
* It's recommended to use `navigateForward()`, `navigateBack()` and `navigateBack()` instead of `setDirection()`.
|
||||
* It's recommended to use `navigateForward()`, `navigateBack()` and `navigateRoot()` instead of `setDirection()`.
|
||||
*/
|
||||
setDirection(direction: RouterDirection, animated?: boolean, animationDirection?: 'forward' | 'back') {
|
||||
this.direction = direction;
|
||||
@@ -184,12 +186,34 @@ export class NavController {
|
||||
if (Array.isArray(url)) {
|
||||
return this.router!.navigate(url, options);
|
||||
} else {
|
||||
return this.router!.navigateByUrl(url, options);
|
||||
|
||||
/**
|
||||
* navigateByUrl ignores any properties that
|
||||
* would change the url, so things like queryParams
|
||||
* would be ignored unless we create a url tree
|
||||
* More Info: https://github.com/angular/angular/issues/18798
|
||||
*/
|
||||
const urlTree = this.serializer.parse(url.toString());
|
||||
|
||||
if (options.queryParams !== undefined) {
|
||||
urlTree.queryParams = { ...options.queryParams };
|
||||
}
|
||||
|
||||
if (options.fragment !== undefined) {
|
||||
urlTree.fragment = options.fragment;
|
||||
}
|
||||
|
||||
/**
|
||||
* `navigateByUrl` will still apply `NavigationExtras` properties
|
||||
* that do not modify the url, such as `replaceUrl` which is why
|
||||
* `options` is passed in here.
|
||||
*/
|
||||
return this.router!.navigateByUrl(urlTree, options);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getAnimation(direction: RouterDirection, animated: boolean | undefined, animationDirection: 'forward' | 'back' | undefined): NavDirection | undefined {
|
||||
const getAnimation = (direction: RouterDirection, animated: boolean | undefined, animationDirection: 'forward' | 'back' | undefined): NavDirection | undefined => {
|
||||
if (animated === false) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -202,7 +226,7 @@ function getAnimation(direction: RouterDirection, animated: boolean | undefined,
|
||||
return 'forward';
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
||||
const DEFAULT_DIRECTION = 'auto';
|
||||
const DEFAULT_ANIMATED = undefined;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { DOCUMENT } from '@angular/common';
|
||||
import { Inject, Injectable } from '@angular/core';
|
||||
import { PickerOptions } from '@ionic/core';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { PickerOptions, pickerController } from '@ionic/core';
|
||||
|
||||
import { OverlayBaseController } from '../util/overlay';
|
||||
|
||||
@@ -8,7 +7,7 @@ import { OverlayBaseController } from '../util/overlay';
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class PickerController extends OverlayBaseController<PickerOptions, HTMLIonPickerElement> {
|
||||
constructor(@Inject(DOCUMENT) doc: any) {
|
||||
super('ion-picker-controller', doc);
|
||||
constructor() {
|
||||
super(pickerController);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { DOCUMENT } from '@angular/common';
|
||||
import { Inject, Injectable } from '@angular/core';
|
||||
import { Inject, Injectable, NgZone } from '@angular/core';
|
||||
import { BackButtonEventDetail, Platforms, getPlatforms, isPlatform } from '@ionic/core';
|
||||
import { Subject, Subscription } from 'rxjs';
|
||||
|
||||
@@ -42,29 +42,30 @@ export class Platform {
|
||||
*/
|
||||
resize = new Subject<void>();
|
||||
|
||||
constructor(@Inject(DOCUMENT) private doc: any) {
|
||||
this.win = doc.defaultView;
|
||||
constructor(@Inject(DOCUMENT) private doc: any, zone: NgZone) {
|
||||
zone.run(() => {
|
||||
this.win = doc.defaultView;
|
||||
this.backButton.subscribeWithPriority = function(priority, callback) {
|
||||
return this.subscribe(ev => (
|
||||
ev.register(priority, () => zone.run(callback))
|
||||
));
|
||||
};
|
||||
|
||||
this.backButton.subscribeWithPriority = function(priority, callback) {
|
||||
return this.subscribe(ev => {
|
||||
ev.register(priority, callback);
|
||||
});
|
||||
};
|
||||
proxyEvent(this.pause, doc, 'pause');
|
||||
proxyEvent(this.resume, doc, 'resume');
|
||||
proxyEvent(this.backButton, doc, 'ionBackButton');
|
||||
proxyEvent(this.resize, this.win, 'resize');
|
||||
|
||||
proxyEvent(this.pause, doc, 'pause');
|
||||
proxyEvent(this.resume, doc, 'resume');
|
||||
proxyEvent(this.backButton, doc, 'ionBackButton');
|
||||
proxyEvent(this.resize, this.win, 'resize');
|
||||
|
||||
let readyResolve: (value: string) => void;
|
||||
this._readyPromise = new Promise(res => { readyResolve = res; });
|
||||
if (this.win && this.win['cordova']) {
|
||||
doc.addEventListener('deviceready', () => {
|
||||
readyResolve('cordova');
|
||||
}, { once: true });
|
||||
} else {
|
||||
readyResolve!('dom');
|
||||
}
|
||||
let readyResolve: (value: string) => void;
|
||||
this._readyPromise = new Promise(res => { readyResolve = res; });
|
||||
if (this.win && this.win['cordova']) {
|
||||
doc.addEventListener('deviceready', () => {
|
||||
readyResolve('cordova');
|
||||
}, { once: true });
|
||||
} else {
|
||||
readyResolve!('dom');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { DOCUMENT } from '@angular/common';
|
||||
import { ComponentFactoryResolver, Inject, Injectable, Injector } from '@angular/core';
|
||||
import { PopoverOptions } from '@ionic/core';
|
||||
import { ComponentFactoryResolver, Injectable, Injector } from '@angular/core';
|
||||
import { PopoverOptions, popoverController } from '@ionic/core';
|
||||
|
||||
import { OverlayBaseController } from '../util/overlay';
|
||||
|
||||
@@ -13,9 +12,8 @@ export class PopoverController extends OverlayBaseController<PopoverOptions, HTM
|
||||
private angularDelegate: AngularDelegate,
|
||||
private resolver: ComponentFactoryResolver,
|
||||
private injector: Injector,
|
||||
@Inject(DOCUMENT) doc: any
|
||||
) {
|
||||
super('ion-popover-controller', doc);
|
||||
super(popoverController);
|
||||
}
|
||||
|
||||
create(opts: PopoverOptions): Promise<HTMLIonPopoverElement> {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { DOCUMENT } from '@angular/common';
|
||||
import { Inject, Injectable } from '@angular/core';
|
||||
import { ToastOptions } from '@ionic/core';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { ToastOptions, toastController } from '@ionic/core';
|
||||
|
||||
import { OverlayBaseController } from '../util/overlay';
|
||||
|
||||
@@ -8,7 +7,7 @@ import { OverlayBaseController } from '../util/overlay';
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class ToastController extends OverlayBaseController<ToastOptions, HTMLIonToastElement> {
|
||||
constructor(@Inject(DOCUMENT) doc: any) {
|
||||
super('ion-toast-controller', doc);
|
||||
constructor() {
|
||||
super(toastController);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
|
||||
export interface IonicGlobal {
|
||||
config?: any;
|
||||
ael?: (elm: any, eventName: string, cb: (ev: Event) => void, opts: any) => void;
|
||||
raf?: (ts: number) => void;
|
||||
rel?: (elm: any, eventName: string, cb: (ev: Event) => void, opts: any) => void;
|
||||
asyncQueue?: boolean;
|
||||
}
|
||||
|
||||
export interface IonicWindow extends Window {
|
||||
Ionic: IonicGlobal;
|
||||
__zone_symbol__requestAnimationFrame: (ts: number) => void;
|
||||
__zone_symbol__requestAnimationFrame?: (ts: FrameRequestCallback) => number;
|
||||
}
|
||||
|
||||
export interface HTMLStencilElement extends HTMLElement {
|
||||
componentOnReady(): Promise<this>;
|
||||
forceUpdate(): void;
|
||||
}
|
||||
|
||||
@@ -25,9 +25,6 @@ export class IonicRouteStrategy implements RouteReuseStrategy {
|
||||
if (future.routeConfig !== curr.routeConfig) {
|
||||
return false;
|
||||
}
|
||||
if (future.component !== curr.component) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// checking router params
|
||||
const futureParams = future.params;
|
||||
|
||||
@@ -1,26 +1,32 @@
|
||||
import { proxyMethod } from './util';
|
||||
|
||||
export class OverlayBaseController<Opts, Overlay> {
|
||||
constructor(private ctrl: string, private doc: Document) {}
|
||||
interface ControllerShape<Opts, HTMLElm> {
|
||||
create(options: Opts): Promise<HTMLElm>;
|
||||
dismiss(data?: any, role?: string, id?: string): Promise<boolean>;
|
||||
getTop(): Promise<HTMLElm | undefined>;
|
||||
}
|
||||
|
||||
export class OverlayBaseController<Opts, Overlay> implements ControllerShape<Opts, Overlay> {
|
||||
constructor(private ctrl: ControllerShape<Opts, Overlay>) {}
|
||||
|
||||
/**
|
||||
* Creates a new overlay
|
||||
*/
|
||||
create(opts?: Opts): Promise<Overlay> {
|
||||
return proxyMethod(this.ctrl, this.doc, 'create', opts);
|
||||
create(opts?: Opts) {
|
||||
// TODO: next major release opts is not optional
|
||||
return this.ctrl.create((opts || {}) as any);
|
||||
}
|
||||
|
||||
/**
|
||||
* When `id` is not provided, it dismisses the top overlay.
|
||||
*/
|
||||
dismiss(data?: any, role?: string, id?: string): Promise<void> {
|
||||
return proxyMethod(this.ctrl, this.doc, 'dismiss', data, role, id);
|
||||
dismiss(data?: any, role?: string, id?: string) {
|
||||
return this.ctrl.dismiss(data, role, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the top overlay.
|
||||
*/
|
||||
getTop(): Promise<Overlay | undefined> {
|
||||
return proxyMethod(this.ctrl, this.doc, 'getTop');
|
||||
getTop() {
|
||||
return this.ctrl.getTop();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,29 @@
|
||||
import { HTMLStencilElement } from '../types/interfaces';
|
||||
|
||||
export function proxyMethod(ctrlName: string, doc: Document, methodName: string, ...args: any[]) {
|
||||
declare const __zone_symbol__requestAnimationFrame: any;
|
||||
declare const requestAnimationFrame: any;
|
||||
|
||||
export const raf = (h: any) => {
|
||||
if (typeof __zone_symbol__requestAnimationFrame === 'function') {
|
||||
return __zone_symbol__requestAnimationFrame(h);
|
||||
}
|
||||
if (typeof requestAnimationFrame === 'function') {
|
||||
return requestAnimationFrame(h);
|
||||
}
|
||||
return setTimeout(h);
|
||||
};
|
||||
|
||||
export const proxyMethod = (ctrlName: string, doc: Document, methodName: string, ...args: any[]) => {
|
||||
const controller = ensureElementInBody(ctrlName, doc);
|
||||
return controller.componentOnReady()
|
||||
.then(() => (controller as any)[methodName].apply(controller, args));
|
||||
}
|
||||
};
|
||||
|
||||
export function ensureElementInBody(elementName: string, doc: Document) {
|
||||
export const ensureElementInBody = (elementName: string, doc: Document) => {
|
||||
let element = doc.querySelector(elementName);
|
||||
if (!element) {
|
||||
element = doc.createElement(elementName);
|
||||
doc.body.appendChild(element);
|
||||
}
|
||||
return element as HTMLStencilElement;
|
||||
}
|
||||
};
|
||||
|
||||
1
angular/test/test-app/.npmrc
Normal file
1
angular/test/test-app/.npmrc
Normal file
@@ -0,0 +1 @@
|
||||
package-lock=false
|
||||
@@ -13,18 +13,25 @@
|
||||
"build": {
|
||||
"builder": "@angular-devkit/build-angular:browser",
|
||||
"options": {
|
||||
"outputPath": "dist/test-app",
|
||||
"outputPath": "dist/browser",
|
||||
"index": "src/index.html",
|
||||
"main": "src/main.ts",
|
||||
"polyfills": "src/polyfills.ts",
|
||||
"tsConfig": "src/tsconfig.app.json",
|
||||
"tsConfig": "tsconfig.app.json",
|
||||
"assets": [
|
||||
"src/favicon.ico",
|
||||
"src/assets"
|
||||
],
|
||||
"styles": [
|
||||
"src/styles.css"
|
||||
{
|
||||
"glob": "**/*",
|
||||
"input": "src/assets",
|
||||
"output": "assets"
|
||||
},
|
||||
{
|
||||
"glob": "**/*.svg",
|
||||
"input": "node_modules/ionicons/dist/ionicons/svg",
|
||||
"output": "./svg"
|
||||
}
|
||||
],
|
||||
"styles": ["src/styles.css"],
|
||||
"scripts": []
|
||||
},
|
||||
"configurations": {
|
||||
@@ -77,37 +84,13 @@
|
||||
"options": {
|
||||
"main": "src/test.ts",
|
||||
"polyfills": "src/polyfills.ts",
|
||||
"tsConfig": "src/tsconfig.spec.json",
|
||||
"karmaConfig": "src/karma.conf.js",
|
||||
"styles": [
|
||||
"src/styles.css"
|
||||
],
|
||||
"tsConfig": "tsconfig.spec.json",
|
||||
"karmaConfig": "karma.conf.js",
|
||||
"styles": ["src/styles.css"],
|
||||
"scripts": [],
|
||||
"assets": [
|
||||
"src/favicon.ico",
|
||||
"src/assets"
|
||||
]
|
||||
"assets": ["src/favicon.ico", "src/assets"]
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"builder": "@angular-devkit/build-angular:tslint",
|
||||
"options": {
|
||||
"tsConfig": [
|
||||
"src/tsconfig.app.json",
|
||||
"src/tsconfig.spec.json"
|
||||
],
|
||||
"exclude": [
|
||||
"**/node_modules/**"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"test-app-e2e": {
|
||||
"root": "e2e/",
|
||||
"projectType": "application",
|
||||
"prefix": "",
|
||||
"architect": {
|
||||
"e2e": {
|
||||
"builder": "@angular-devkit/build-angular:protractor",
|
||||
"options": {
|
||||
@@ -117,20 +100,39 @@
|
||||
"configurations": {
|
||||
"production": {
|
||||
"devServerTarget": "test-app:serve:production"
|
||||
},
|
||||
"ci": {
|
||||
"devServerTarget": "test-app:serve:ci"
|
||||
}
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"builder": "@angular-devkit/build-angular:tslint",
|
||||
"options": {
|
||||
"tsConfig": "e2e/tsconfig.e2e.json",
|
||||
"exclude": [
|
||||
"**/node_modules/**"
|
||||
]
|
||||
"tsConfig": ["tsconfig.app.json", "tsconfig.spec.json"],
|
||||
"exclude": ["**/node_modules/**"]
|
||||
}
|
||||
},
|
||||
"server": {
|
||||
"builder": "@angular-devkit/build-angular:server",
|
||||
"options": {
|
||||
"outputPath": "dist/server",
|
||||
"main": "src/main.server.ts",
|
||||
"tsConfig": "tsconfig.server.json"
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"fileReplacements": [
|
||||
{
|
||||
"src": "src/environments/environment.ts",
|
||||
"replaceWith": "src/environments/environment.prod.ts"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"defaultProject": "test-app"
|
||||
}
|
||||
}
|
||||
|
||||
12
angular/test/test-app/browserslist
Normal file
12
angular/test/test-app/browserslist
Normal file
@@ -0,0 +1,12 @@
|
||||
# This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
|
||||
# For additional information regarding the format and rule options, please see:
|
||||
# https://github.com/browserslist/browserslist#queries
|
||||
|
||||
# You can see what browsers were selected by your queries by running:
|
||||
# npx browserslist
|
||||
|
||||
> 0.5%
|
||||
last 2 versions
|
||||
Firefox ESR
|
||||
not dead
|
||||
not IE 9-11 # For IE 9-11 support, remove 'not'.
|
||||
@@ -1,19 +1,22 @@
|
||||
// @ts-check
|
||||
// Protractor configuration file, see link for more information
|
||||
// https://github.com/angular/protractor/blob/master/lib/config.ts
|
||||
|
||||
const { SpecReporter } = require('jasmine-spec-reporter');
|
||||
|
||||
/**
|
||||
* @type { import("protractor").Config }
|
||||
*/
|
||||
exports.config = {
|
||||
allScriptsTimeout: 11000,
|
||||
specs: [
|
||||
'./**/*.e2e-spec.ts'
|
||||
'./src/**/*.e2e-spec.ts'
|
||||
],
|
||||
capabilities: {
|
||||
browserName: 'chrome',
|
||||
|
||||
chromeOptions: {
|
||||
args: [ "--headless", "--disable-gpu", "--window-size=400,1000", "--start-maximized" ]
|
||||
}
|
||||
'browserName': 'chrome'
|
||||
},
|
||||
chromeOptions: {
|
||||
args: [ "--headless", "--disable-gpu", "--window-size=400,1000", "--start-maximized" ]
|
||||
},
|
||||
directConnect: true,
|
||||
baseUrl: 'http://localhost:4200/',
|
||||
@@ -25,8 +28,8 @@ exports.config = {
|
||||
},
|
||||
onPrepare() {
|
||||
require('ts-node').register({
|
||||
project: require('path').join(__dirname, './tsconfig.e2e.json')
|
||||
project: require('path').join(__dirname, './tsconfig.json')
|
||||
});
|
||||
jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -4,12 +4,13 @@ import { handleErrorMessages, setProperty, getText, waitTime } from './utils';
|
||||
describe('form', () => {
|
||||
|
||||
afterEach(() => {
|
||||
handleErrorMessages();
|
||||
return handleErrorMessages();
|
||||
});
|
||||
|
||||
describe('change', () => {
|
||||
beforeEach(async () => {
|
||||
await browser.get('/form');
|
||||
await waitTime(30);
|
||||
});
|
||||
|
||||
it('should have default values', async () => {
|
||||
@@ -81,6 +82,7 @@ describe('form', () => {
|
||||
describe('blur', () => {
|
||||
beforeEach(async () => {
|
||||
await browser.get('/form#blur');
|
||||
await waitTime(30);
|
||||
});
|
||||
|
||||
it('ion-toggle should change only after blur', async () => {
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
import { browser, element, by } from 'protractor';
|
||||
import { getProperty, setProperty, handleErrorMessages } from './utils';
|
||||
import { getProperty, setProperty, handleErrorMessages, waitTime } from './utils';
|
||||
|
||||
describe('inputs', () => {
|
||||
|
||||
beforeEach(async () => {
|
||||
await browser.get('/inputs');
|
||||
await waitTime(30);
|
||||
});
|
||||
afterEach(() => {
|
||||
handleErrorMessages();
|
||||
return handleErrorMessages();
|
||||
});
|
||||
|
||||
it('should have default value', async () => {
|
||||
@@ -59,4 +60,10 @@ describe('inputs', () => {
|
||||
expect(await element(by.css('#select-note')).getText()).toEqual('playstation');
|
||||
expect(await element(by.css('#range-note')).getText()).toEqual('20');
|
||||
});
|
||||
|
||||
it('nested components should not interfere with NgModel', async () => {
|
||||
expect(await element(by.css('#range-note')).getText()).toEqual('10');
|
||||
await element(by.css('#nested-toggle')).click();
|
||||
expect(await element(by.css('#range-note')).getText()).toEqual('10');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -5,9 +5,10 @@ describe('modals', () => {
|
||||
|
||||
beforeEach(async () => {
|
||||
await browser.get('/modals');
|
||||
await waitTime(30);
|
||||
});
|
||||
afterEach(() => {
|
||||
handleErrorMessages();
|
||||
return handleErrorMessages();
|
||||
});
|
||||
|
||||
it('should open standalone modal and close', async () => {
|
||||
|
||||
@@ -4,9 +4,44 @@ import { handleErrorMessages, waitTime, testStack } from './utils';
|
||||
describe('navigation', () => {
|
||||
|
||||
afterEach(() => {
|
||||
handleErrorMessages();
|
||||
return handleErrorMessages();
|
||||
});
|
||||
|
||||
// TODO: Fix flaky tests
|
||||
xit ('should swipe and abort', async () => {
|
||||
await browser.get('/router-link?ionic:mode=ios');
|
||||
await waitTime(500);
|
||||
await element(by.css('#routerLink')).click();
|
||||
await waitTime(500);
|
||||
await swipeLeft(5);
|
||||
await waitTime(500);
|
||||
|
||||
const pageHidden = element(by.css('app-router-link'));
|
||||
expect(await pageHidden.getAttribute('aria-hidden')).toEqual('true');
|
||||
expect(await pageHidden.getAttribute('class')).toEqual('ion-page ion-page-hidden');
|
||||
|
||||
const pageVisible = element(by.css('app-router-link-page'));
|
||||
expect(await pageVisible.getAttribute('aria-hidden')).toEqual(null);
|
||||
expect(await pageVisible.getAttribute('class')).toEqual('ion-page can-go-back');
|
||||
});
|
||||
|
||||
xit ('should swipe and go back', async () => {
|
||||
await browser.get('/router-link?ionic:mode=ios');
|
||||
await waitTime(500);
|
||||
await element(by.css('#routerLink')).click();
|
||||
await waitTime(500);
|
||||
await testStack('ion-router-outlet', ['app-router-link', 'app-router-link-page']);
|
||||
|
||||
await swipeLeft(300);
|
||||
|
||||
await waitTime(1000);
|
||||
await testStack('ion-router-outlet', ['app-router-link']);
|
||||
|
||||
const page = element(by.css('app-router-link'));
|
||||
expect(await page.getAttribute('aria-hidden')).toEqual(null);
|
||||
expect(await page.getAttribute('class')).toEqual('ion-page');
|
||||
})
|
||||
|
||||
it('should navigate correctly', async () => {
|
||||
await browser.get('/navigation/page1');
|
||||
await waitTime(2000);
|
||||
@@ -22,3 +57,17 @@ describe('navigation', () => {
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
function swipeLeft(end: number) {
|
||||
return browser.driver.touchActions()
|
||||
.tapAndHold({x: 5, y: 1})
|
||||
.move({x: 6, y: 1})
|
||||
.move({x: 7, y: 1})
|
||||
.move({x: 8, y: 1})
|
||||
.move({x: 30, y: 1})
|
||||
.move({x: 300, y: 1})
|
||||
.move({x: end, y: 1})
|
||||
.move({x: end, y: 1})
|
||||
.release({x: end, y: 1})
|
||||
.perform();
|
||||
}
|
||||
@@ -4,7 +4,7 @@ import { waitTime, handleErrorMessages, goBack } from './utils';
|
||||
describe('nested-outlet', () => {
|
||||
|
||||
afterEach(() => {
|
||||
handleErrorMessages();
|
||||
return handleErrorMessages();
|
||||
});
|
||||
|
||||
it('should navigate correctly', async () => {
|
||||
|
||||
@@ -4,7 +4,7 @@ import { handleErrorMessages, waitTime } from './utils';
|
||||
describe('providers', () => {
|
||||
|
||||
afterEach(() => {
|
||||
handleErrorMessages();
|
||||
return handleErrorMessages();
|
||||
});
|
||||
|
||||
it('should load all providers', async () => {
|
||||
@@ -12,6 +12,9 @@ describe('providers', () => {
|
||||
|
||||
expect(await element(by.css('#is-loaded')).getText()).toEqual('true');
|
||||
expect(await element(by.css('#is-ready')).getText()).toEqual('true');
|
||||
expect(await element(by.css('#is-paused')).getText()).toEqual('true');
|
||||
expect(await element(by.css('#is-resumed')).getText()).toEqual('true');
|
||||
expect(await element(by.css('#is-resized')).getText()).toEqual('true');
|
||||
expect(await element(by.css('#is-testing')).getText()).toEqual('false');
|
||||
expect(await element(by.css('#is-desktop')).getText()).toEqual('true');
|
||||
expect(await element(by.css('#is-mobile')).getText()).toEqual('false');
|
||||
|
||||
@@ -1,13 +1,61 @@
|
||||
import { browser, element, by } from 'protractor';
|
||||
import { waitTime, testStack, testLifeCycle, handleErrorMessages } from './utils';
|
||||
import { browser, element, by, protractor } from 'protractor';
|
||||
import { waitTime, testStack, testLifeCycle, handleErrorMessages, getText } from './utils';
|
||||
|
||||
const EC = protractor.ExpectedConditions;
|
||||
|
||||
describe('router-link params and fragments', () => {
|
||||
const queryParam = 'A&=#Y';
|
||||
const fragment = 'myDiv1';
|
||||
const id = 'MyPageID==';
|
||||
|
||||
afterEach(() => {
|
||||
return handleErrorMessages();
|
||||
});
|
||||
|
||||
it('should go to a page with properly encoded values', async () => {
|
||||
await browser.get('/router-link?ionic:_testing=true');
|
||||
await element(by.css('#queryParamsFragment')).click();
|
||||
|
||||
const expectedRoute = `${encodeURIComponent(id)}?token=${encodeURIComponent(queryParam)}#${encodeURIComponent(fragment)}`;
|
||||
|
||||
browser.wait(EC.urlContains(expectedRoute), 5000);
|
||||
});
|
||||
|
||||
it('should return to a page with preserved query param and fragment', async () => {
|
||||
await browser.get('/router-link?ionic:_testing=true');
|
||||
await waitTime(30);
|
||||
await element(by.css('#queryParamsFragment')).click();
|
||||
await waitTime(400);
|
||||
await element(by.css('#goToPage3')).click();
|
||||
|
||||
browser.wait(EC.urlContains('router-link-page3'), 5000);
|
||||
await waitTime(400);
|
||||
|
||||
await element(by.css('#goBackFromPage3')).click();
|
||||
|
||||
const expectedRoute = `${encodeURIComponent(id)}?token=${encodeURIComponent(queryParam)}#${encodeURIComponent(fragment)}`;
|
||||
browser.wait(EC.urlContains(expectedRoute), 5000);
|
||||
});
|
||||
|
||||
it('should preserve query param and fragment with defaultHref string', async () => {
|
||||
await browser.get('/router-link-page3?ionic:_testing=true');
|
||||
await waitTime(30);
|
||||
|
||||
await element(by.css('#goBackFromPage3')).click();
|
||||
|
||||
const expectedRoute = '?token=ABC#fragment';
|
||||
browser.wait(EC.urlContains(expectedRoute), 5000);
|
||||
});
|
||||
});
|
||||
|
||||
describe('router-link', () => {
|
||||
|
||||
beforeEach(async () => {
|
||||
await browser.get('/router-link');
|
||||
await waitTime(30);
|
||||
});
|
||||
afterEach(() => {
|
||||
handleErrorMessages();
|
||||
return handleErrorMessages();
|
||||
});
|
||||
|
||||
|
||||
@@ -25,18 +73,6 @@ describe('router-link', () => {
|
||||
it('should go forward with ion-button[routerLink]', async () => {
|
||||
await element(by.css('#routerLink')).click();
|
||||
await testForward();
|
||||
|
||||
// test go back
|
||||
await element(by.css('ion-back-button')).click();
|
||||
await waitTime(500);
|
||||
|
||||
await testStack('ion-router-outlet', ['app-router-link']);
|
||||
await testLifeCycle('app-router-link', {
|
||||
ionViewWillEnter: 2,
|
||||
ionViewDidEnter: 2,
|
||||
ionViewWillLeave: 1,
|
||||
ionViewDidLeave: 1,
|
||||
});
|
||||
});
|
||||
|
||||
it('should go forward with a[routerLink]', async () => {
|
||||
@@ -77,7 +113,6 @@ describe('router-link', () => {
|
||||
|
||||
it('should go back with ion-button[routerLink][routerDirection=back]', async () => {
|
||||
await element(by.css('#routerLink-back')).click();
|
||||
await testBack();
|
||||
});
|
||||
|
||||
it('should go back with a[routerLink][routerDirection=back]', async () => {
|
||||
@@ -93,21 +128,25 @@ describe('router-link', () => {
|
||||
});
|
||||
|
||||
async function testForward() {
|
||||
await waitTime(500);
|
||||
await waitTime(2500);
|
||||
await testStack('ion-router-outlet', ['app-router-link', 'app-router-link-page']);
|
||||
await testLifeCycle('app-router-link', {
|
||||
ionViewWillEnter: 1,
|
||||
ionViewDidEnter: 1,
|
||||
ionViewWillLeave: 1,
|
||||
ionViewDidLeave: 1,
|
||||
});
|
||||
await testLifeCycle('app-router-link-page', {
|
||||
ionViewWillEnter: 1,
|
||||
ionViewDidEnter: 1,
|
||||
ionViewWillLeave: 0,
|
||||
ionViewDidLeave: 0,
|
||||
});
|
||||
expect(await getText(`app-router-link-page #canGoBack`)).toEqual('true');
|
||||
|
||||
await browser.navigate().back();
|
||||
await waitTime(100);
|
||||
await testStack('ion-router-outlet', ['app-router-link']);
|
||||
await testLifeCycle('app-router-link', {
|
||||
ionViewWillEnter: 2,
|
||||
ionViewDidEnter: 2,
|
||||
ionViewWillLeave: 1,
|
||||
ionViewDidLeave: 1,
|
||||
});
|
||||
}
|
||||
|
||||
async function testRoot() {
|
||||
@@ -119,6 +158,17 @@ async function testRoot() {
|
||||
ionViewWillLeave: 0,
|
||||
ionViewDidLeave: 0,
|
||||
});
|
||||
expect(await getText(`app-router-link-page #canGoBack`)).toEqual('false');
|
||||
|
||||
await browser.navigate().back();
|
||||
await waitTime(100);
|
||||
await testStack('ion-router-outlet', ['app-router-link']);
|
||||
await testLifeCycle('app-router-link', {
|
||||
ionViewWillEnter: 1,
|
||||
ionViewDidEnter: 1,
|
||||
ionViewWillLeave: 0,
|
||||
ionViewDidLeave: 0,
|
||||
});
|
||||
}
|
||||
|
||||
async function testBack() {
|
||||
@@ -130,4 +180,15 @@ async function testBack() {
|
||||
ionViewWillLeave: 0,
|
||||
ionViewDidLeave: 0,
|
||||
});
|
||||
expect(await getText(`app-router-link-page #canGoBack`)).toEqual('false');
|
||||
|
||||
await browser.navigate().back();
|
||||
await waitTime(100);
|
||||
await testStack('ion-router-outlet', ['app-router-link']);
|
||||
await testLifeCycle('app-router-link', {
|
||||
ionViewWillEnter: 1,
|
||||
ionViewDidEnter: 1,
|
||||
ionViewWillLeave: 0,
|
||||
ionViewDidLeave: 0,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -5,9 +5,10 @@ describe('slides', () => {
|
||||
|
||||
beforeEach(async () => {
|
||||
await browser.get('/slides');
|
||||
await waitTime(30);
|
||||
});
|
||||
afterEach(() => {
|
||||
handleErrorMessages();
|
||||
return handleErrorMessages();
|
||||
});
|
||||
|
||||
it('should change index on slide change', async () => {
|
||||
|
||||
@@ -3,11 +3,12 @@ import { waitTime, testStack, handleErrorMessages } from './utils';
|
||||
|
||||
describe('tabs', () => {
|
||||
afterEach(() => {
|
||||
handleErrorMessages();
|
||||
return handleErrorMessages();
|
||||
});
|
||||
describe('entry url - /tabs', () => {
|
||||
beforeEach(async () => {
|
||||
await browser.get('/tabs');
|
||||
await waitTime(30);
|
||||
});
|
||||
|
||||
it('should redirect and load tab-account', async () => {
|
||||
@@ -19,7 +20,7 @@ describe('tabs', () => {
|
||||
it('should simulate stack + double tab click', async () => {
|
||||
let tab = await getSelectedTab() as ElementFinder;
|
||||
await tab.$('#goto-tab1-page2').click();
|
||||
await testTabTitle('Tab 1 - Page 2');
|
||||
await testTabTitle('Tab 1 - Page 2 (1)');
|
||||
await testStack('ion-tabs ion-router-outlet', ['app-tabs-tab1', 'app-tabs-tab1-nested']);
|
||||
await testState(1, 'account');
|
||||
expect(await tab.$('ion-back-button').isDisplayed()).toBe(true);
|
||||
@@ -30,7 +31,7 @@ describe('tabs', () => {
|
||||
await testState(2, 'contact');
|
||||
|
||||
await element(by.css('#tab-button-account')).click();
|
||||
tab = await testTabTitle('Tab 1 - Page 2');
|
||||
tab = await testTabTitle('Tab 1 - Page 2 (1)');
|
||||
await testStack('ion-tabs ion-router-outlet', ['app-tabs-tab1', 'app-tabs-tab1-nested', 'app-tabs-tab2']);
|
||||
await testState(3, 'account');
|
||||
expect(await tab.$('ion-back-button').isDisplayed()).toBe(true);
|
||||
@@ -44,7 +45,7 @@ describe('tabs', () => {
|
||||
it('should simulate stack + back button click', async () => {
|
||||
const tab = await getSelectedTab();
|
||||
await tab.$('#goto-tab1-page2').click();
|
||||
await testTabTitle('Tab 1 - Page 2');
|
||||
await testTabTitle('Tab 1 - Page 2 (1)');
|
||||
await testState(1, 'account');
|
||||
|
||||
await element(by.css('#tab-button-contact')).click();
|
||||
@@ -52,7 +53,7 @@ describe('tabs', () => {
|
||||
await testState(2, 'contact');
|
||||
|
||||
await element(by.css('#tab-button-account')).click();
|
||||
await testTabTitle('Tab 1 - Page 2');
|
||||
await testTabTitle('Tab 1 - Page 2 (1)');
|
||||
await testState(3, 'account');
|
||||
|
||||
await element(by.css('ion-back-button')).click();
|
||||
@@ -61,6 +62,33 @@ describe('tabs', () => {
|
||||
await testState(3, 'account');
|
||||
});
|
||||
|
||||
it('should navigate deep then go home', async () => {
|
||||
let tab = await getSelectedTab();
|
||||
await tab.$('#goto-tab1-page2').click();
|
||||
tab = await testTabTitle('Tab 1 - Page 2 (1)');
|
||||
|
||||
await tab.$('#goto-next').click();
|
||||
tab = await testTabTitle('Tab 1 - Page 2 (2)');
|
||||
|
||||
await element(by.css('#tab-button-contact')).click();
|
||||
tab = await testTabTitle('Tab 2 - Page 1');
|
||||
|
||||
await element(by.css('#tab-button-account')).click();
|
||||
await testTabTitle('Tab 1 - Page 2 (2)');
|
||||
await testStack('ion-tabs ion-router-outlet', [
|
||||
'app-tabs-tab1',
|
||||
'app-tabs-tab1-nested',
|
||||
'app-tabs-tab1-nested',
|
||||
'app-tabs-tab2'
|
||||
]);
|
||||
await element(by.css('#tab-button-account')).click();
|
||||
await testTabTitle('Tab 1 - Page 1');
|
||||
await testStack('ion-tabs ion-router-outlet', [
|
||||
'app-tabs-tab1',
|
||||
'app-tabs-tab2'
|
||||
]);
|
||||
});
|
||||
|
||||
it('should switch tabs and go back', async () => {
|
||||
await element(by.css('#tab-button-contact')).click();
|
||||
const tab = await testTabTitle('Tab 2 - Page 1');
|
||||
@@ -75,7 +103,7 @@ describe('tabs', () => {
|
||||
const tab = await testTabTitle('Tab 2 - Page 1');
|
||||
|
||||
await tab.$('#goto-tab1-page2').click();
|
||||
await testTabTitle('Tab 1 - Page 2');
|
||||
await testTabTitle('Tab 1 - Page 2 (1)');
|
||||
await testStack('ion-tabs ion-router-outlet', ['app-tabs-tab2', 'app-tabs-tab1-nested']);
|
||||
});
|
||||
|
||||
@@ -96,13 +124,14 @@ describe('tabs', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('entry url - /tabs/account/nested/12', () => {
|
||||
describe('entry url - /tabs/account/nested/1', () => {
|
||||
beforeEach(async () => {
|
||||
await browser.get('/tabs/account/nested/12');
|
||||
await browser.get('/tabs/account/nested/1');
|
||||
await waitTime(30);
|
||||
});
|
||||
|
||||
it('should only display the back-button when there is a page in the stack', async () => {
|
||||
let tab = await testTabTitle('Tab 1 - Page 2') as ElementFinder;
|
||||
let tab = await testTabTitle('Tab 1 - Page 2 (1)') as ElementFinder;
|
||||
await testStack('ion-tabs ion-router-outlet', ['app-tabs-tab1-nested']);
|
||||
expect(await tab.$('ion-back-button').isDisplayed()).toBe(false);
|
||||
|
||||
@@ -110,14 +139,38 @@ describe('tabs', () => {
|
||||
tab = await testTabTitle('Tab 1 - Page 1');
|
||||
|
||||
await tab.$('#goto-tab1-page2').click();
|
||||
tab = await testTabTitle('Tab 1 - Page 2');
|
||||
tab = await testTabTitle('Tab 1 - Page 2 (1)');
|
||||
expect(await tab.$('ion-back-button').isDisplayed()).toBe(true);
|
||||
});
|
||||
|
||||
it('should not reuse the same page', async () => {
|
||||
let tab = await testTabTitle('Tab 1 - Page 2 (1)') as ElementFinder;
|
||||
await tab.$('#goto-next').click();
|
||||
tab = await testTabTitle('Tab 1 - Page 2 (2)');
|
||||
await tab.$('#goto-next').click();
|
||||
tab = await testTabTitle('Tab 1 - Page 2 (3)');
|
||||
|
||||
await testStack('ion-tabs ion-router-outlet',[
|
||||
'app-tabs-tab1-nested',
|
||||
'app-tabs-tab1-nested',
|
||||
'app-tabs-tab1-nested'
|
||||
]);
|
||||
|
||||
await tab.$('ion-back-button').click();
|
||||
tab = await testTabTitle('Tab 1 - Page 2 (2)');
|
||||
await tab.$('ion-back-button').click();
|
||||
tab = await testTabTitle('Tab 1 - Page 2 (1)');
|
||||
|
||||
expect(await tab.$('ion-back-button').isDisplayed()).toBe(false);
|
||||
|
||||
await testStack('ion-tabs ion-router-outlet', ['app-tabs-tab1-nested']);
|
||||
});
|
||||
});
|
||||
|
||||
describe('entry url - /tabs/lazy', () => {
|
||||
beforeEach(async () => {
|
||||
await browser.get('/tabs/lazy');
|
||||
await waitTime(30);
|
||||
});
|
||||
|
||||
it('should not display the back-button if coming from a different stack', async () => {
|
||||
@@ -125,11 +178,32 @@ describe('tabs', () => {
|
||||
await testStack('ion-tabs ion-router-outlet', ['app-tabs-tab3']);
|
||||
|
||||
await tab.$('#goto-tab1-page2').click();
|
||||
tab = await testTabTitle('Tab 1 - Page 2');
|
||||
tab = await testTabTitle('Tab 1 - Page 2 (1)');
|
||||
await testStack('ion-tabs ion-router-outlet', ['app-tabs-tab3', 'app-tabs-tab1-nested']);
|
||||
expect(await tab.$('ion-back-button').isDisplayed()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('enter url - /tabs/contact/one', () => {
|
||||
beforeEach(async () => {
|
||||
await browser.get('/tabs/contact/one');
|
||||
await waitTime(30);
|
||||
});
|
||||
|
||||
it('should return to correct tab after going to page in different outlet', async () => {
|
||||
const tab = await getSelectedTab();
|
||||
await tab.$('#goto-nested-page1').click();
|
||||
|
||||
await waitTime(600);
|
||||
await testStack('app-nested-outlet ion-router-outlet', ['app-nested-outlet-page']);
|
||||
|
||||
const nestedOutlet = await element(by.css('app-nested-outlet'));
|
||||
const backButton = await nestedOutlet.$('ion-back-button');
|
||||
await backButton.click();
|
||||
|
||||
await testTabTitle('Tab 2 - Page 1');
|
||||
});
|
||||
})
|
||||
});
|
||||
|
||||
async function testState(count: number, tab: string) {
|
||||
@@ -137,7 +211,7 @@ async function testState(count: number, tab: string) {
|
||||
}
|
||||
|
||||
async function testTabTitle(title: string) {
|
||||
await waitTime(600);
|
||||
await waitTime(1000);
|
||||
const tab = await getSelectedTab();
|
||||
expect(await tab.$('ion-title').getText()).toEqual(title);
|
||||
return tab;
|
||||
|
||||
@@ -37,29 +37,30 @@ export interface LifeCycleCount {
|
||||
}
|
||||
|
||||
export function handleErrorMessages() {
|
||||
browser.manage().logs().get('browser').then(function(browserLog) {
|
||||
let severWarnings = false;
|
||||
|
||||
for (let i; i <= browserLog.length - 1; i++) {
|
||||
if (browserLog[i].level.name === 'SEVERE') {
|
||||
console.log('\n' + browserLog[i].level.name);
|
||||
console.log('(Possibly exception) \n' + browserLog[i].message);
|
||||
|
||||
severWarnings = true;
|
||||
}
|
||||
return browser.manage().logs().get('browser').then(function (browserLog) {
|
||||
for (let i = 0; i <= browserLog.length - 1; i++) {
|
||||
if (browserLog[i].level.name_ === 'SEVERE') {
|
||||
fail(browserLog[i].message);
|
||||
}
|
||||
}
|
||||
|
||||
expect(severWarnings).toBe(false);
|
||||
});
|
||||
}
|
||||
|
||||
export async function testLifeCycle(selector: string, expected: LifeCycleCount) {
|
||||
await waitTime(50);
|
||||
expect(await getText(`${selector} #ngOnInit`)).toEqual('1');
|
||||
expect(await getText(`${selector} #ionViewWillEnter`)).toEqual(expected.ionViewWillEnter.toString());
|
||||
expect(await getText(`${selector} #ionViewDidEnter`)).toEqual(expected.ionViewDidEnter.toString());
|
||||
expect(await getText(`${selector} #ionViewWillLeave`)).toEqual(expected.ionViewWillLeave.toString());
|
||||
expect(await getText(`${selector} #ionViewDidLeave`)).toEqual(expected.ionViewDidLeave.toString());
|
||||
const results = await Promise.all([
|
||||
getText(`${selector} #ngOnInit`),
|
||||
getText(`${selector} #ionViewWillEnter`),
|
||||
getText(`${selector} #ionViewDidEnter`),
|
||||
getText(`${selector} #ionViewWillLeave`),
|
||||
getText(`${selector} #ionViewDidLeave`),
|
||||
]);
|
||||
|
||||
expect(results[0]).toEqual('1');
|
||||
expect(results[1]).toEqual(expected.ionViewWillEnter.toString());
|
||||
expect(results[2]).toEqual(expected.ionViewDidEnter.toString());
|
||||
expect(results[3]).toEqual(expected.ionViewWillLeave.toString());
|
||||
expect(results[4]).toEqual(expected.ionViewDidLeave.toString());
|
||||
}
|
||||
|
||||
export async function testStack(selector: string, expected: string[]) {
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
import { browser, element, by } from 'protractor';
|
||||
import { handleErrorMessages } from './utils';
|
||||
import { handleErrorMessages, waitTime } from './utils';
|
||||
|
||||
describe('view-child', () => {
|
||||
|
||||
beforeEach(async () => {
|
||||
await browser.get('/view-child');
|
||||
await waitTime(30);
|
||||
});
|
||||
afterEach(() => {
|
||||
handleErrorMessages();
|
||||
return handleErrorMessages();
|
||||
});
|
||||
|
||||
it('should get a reference to all children', async () => {
|
||||
|
||||
18
angular/test/test-app/e2e/src/virtual-scroll.e2e-spec.ts
Normal file
18
angular/test/test-app/e2e/src/virtual-scroll.e2e-spec.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { browser, element, by } from 'protractor';
|
||||
import { waitTime, handleErrorMessages } from './utils';
|
||||
|
||||
describe('virtual-scroll', () => {
|
||||
afterEach(() => {
|
||||
return handleErrorMessages();
|
||||
});
|
||||
beforeEach(async () => {
|
||||
await browser.get('/virtual-scroll');
|
||||
await waitTime(30);
|
||||
});
|
||||
|
||||
it('should open virtual-scroll', () => {
|
||||
const virtualElements = element.all(by.css('ion-virtual-scroll > *'));
|
||||
expect(virtualElements.count()).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
});
|
||||
11108
angular/test/test-app/package-lock.json
generated
11108
angular/test/test-app/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,51 +1,63 @@
|
||||
{
|
||||
"name": "test-app",
|
||||
"name": "ionic-angular-test-app",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"ng": "ng",
|
||||
"start": "npm run sync && ng serve",
|
||||
"sync:build": "sh scripts/build-ionic.sh",
|
||||
"sync": "sh scripts/sync.sh",
|
||||
"build": "ng build --prod --no-progress",
|
||||
"build": "npm run sync && ng build --prod --no-progress",
|
||||
"test": "ng e2e --prod",
|
||||
"test.dev": "npm run sync && ng e2e",
|
||||
"lint": "ng lint",
|
||||
"postinstall": "npm run sync"
|
||||
"postinstall": "npm run sync",
|
||||
"compile:server": "webpack --config webpack.server.config.js --progress --colors",
|
||||
"serve:ssr": "node dist/server",
|
||||
"build:ssr": "npm run build:client-and-server-bundles && npm run compile:server",
|
||||
"build:client-and-server-bundles": "npm run build && ng run test-app:server:production"
|
||||
},
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@angular/animations": "~7.2.1",
|
||||
"@angular/common": "~7.2.1",
|
||||
"@angular/compiler": "~7.2.1",
|
||||
"@angular/core": "~7.2.1",
|
||||
"@angular/forms": "~7.2.1",
|
||||
"@angular/platform-browser": "~7.2.1",
|
||||
"@angular/platform-browser-dynamic": "~7.2.1",
|
||||
"@angular/router": "~7.2.1",
|
||||
"@ionic/angular": "^4.0.0-rc.1",
|
||||
"@angular/animations": "~8.2.0",
|
||||
"@angular/common": "~8.2.0",
|
||||
"@angular/compiler": "~8.2.0",
|
||||
"@angular/core": "~8.2.0",
|
||||
"@angular/forms": "~8.2.0",
|
||||
"@angular/platform-browser": "~8.2.0",
|
||||
"@angular/platform-browser-dynamic": "~8.2.0",
|
||||
"@angular/platform-server": "~8.2.0",
|
||||
"@angular/router": "~8.2.0",
|
||||
"@ionic/angular": "^4.7.0",
|
||||
"@ionic/angular-server": "^0.0.2",
|
||||
"@nguniversal/express-engine": "~8.1.1",
|
||||
"@nguniversal/module-map-ngfactory-loader": "~8.1.1",
|
||||
"core-js": "^2.6.2",
|
||||
"rxjs": "~6.3.3",
|
||||
"express": "^4.15.2",
|
||||
"rxjs": "~6.5.2",
|
||||
"tslib": "^1.9.0",
|
||||
"zone.js": "~0.8.26"
|
||||
"zone.js": "~0.10.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-devkit/build-angular": "~0.12.2",
|
||||
"@angular/cli": "~7.2.1",
|
||||
"@angular/compiler-cli": "~7.2.1",
|
||||
"@angular/language-service": "~7.2.1",
|
||||
"@types/node": "~8.9.4",
|
||||
"@types/jasmine": "~2.8.8",
|
||||
"@angular-devkit/build-angular": "~0.802.0",
|
||||
"@angular/cli": "~8.2.0",
|
||||
"@angular/compiler-cli": "~8.2.0",
|
||||
"@angular/language-service": "~8.2.0",
|
||||
"@types/jasmine": "~3.3.16",
|
||||
"@types/jasminewd2": "~2.0.3",
|
||||
"codelyzer": "~4.5.0",
|
||||
"@types/node": "~12.6.8",
|
||||
"codelyzer": "^5.0.1",
|
||||
"jasmine-core": "~2.99.1",
|
||||
"jasmine-spec-reporter": "~4.2.1",
|
||||
"karma": "~3.1.4",
|
||||
"karma-chrome-launcher": "~2.2.0",
|
||||
"karma-coverage-istanbul-reporter": "~2.0.1",
|
||||
"karma-jasmine": "~1.1.2",
|
||||
"karma-jasmine-html-reporter": "^0.2.2",
|
||||
"karma": "~4.2.0",
|
||||
"karma-chrome-launcher": "~3.0.0",
|
||||
"karma-coverage-istanbul-reporter": "~2.1.0",
|
||||
"karma-jasmine": "~2.0.1",
|
||||
"karma-jasmine-html-reporter": "^1.4.2",
|
||||
"protractor": "~5.4.2",
|
||||
"ts-node": "~7.0.0",
|
||||
"tslint": "~5.12.1",
|
||||
"typescript": "~3.2.4"
|
||||
"ts-loader": "^5.2.0",
|
||||
"ts-node": "~8.3.0",
|
||||
"tslint": "~5.18.0",
|
||||
"typescript": "~3.5.3",
|
||||
"webpack-cli": "^3.1.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,14 @@ popd
|
||||
pushd angular
|
||||
npm link @ionic/core
|
||||
npm run build
|
||||
npm link
|
||||
popd
|
||||
|
||||
# Build angular-server
|
||||
pushd packages/angular-server
|
||||
npm link @ionic/core
|
||||
npm link @ionic/angular
|
||||
npm run build
|
||||
popd
|
||||
|
||||
popd
|
||||
|
||||
@@ -1,14 +1,25 @@
|
||||
# Copy angular dist
|
||||
rm -rf node_modules/@ionic/angular/dist
|
||||
rm -rf node_modules/@ionic/angular
|
||||
mkdir node_modules/@ionic/angular
|
||||
cp -a ../../dist node_modules/@ionic/angular/dist
|
||||
cp -a ../../css node_modules/@ionic/angular/css
|
||||
cp -a ../../package.json node_modules/@ionic/angular/package.json
|
||||
|
||||
# Copy core dist
|
||||
rm -rf node_modules/@ionic/core/dist
|
||||
# Copy angular server
|
||||
rm -rf node_modules/@ionic/angular-server
|
||||
mkdir node_modules/@ionic/angular-server
|
||||
cp -a ../../../packages/angular-server/dist node_modules/@ionic/angular-server/dist
|
||||
cp -a ../../../packages/angular-server/package.json node_modules/@ionic/angular-server/package.json
|
||||
|
||||
# # Copy core dist
|
||||
rm -rf node_modules/@ionic/core
|
||||
mkdir node_modules/@ionic/core
|
||||
cp -a ../../../core/css node_modules/@ionic/core/css
|
||||
cp -a ../../../core/dist node_modules/@ionic/core/dist
|
||||
cp -a ../../../core/hydrate node_modules/@ionic/core/hydrate
|
||||
cp -a ../../../core/loader node_modules/@ionic/core/loader
|
||||
cp -a ../../../core/package.json node_modules/@ionic/core/package.json
|
||||
|
||||
# Copy ionicons
|
||||
# # Copy ionicons
|
||||
rm -rf node_modules/ionicons
|
||||
cp -a ../../../core/node_modules/ionicons node_modules/ionicons
|
||||
|
||||
58
angular/test/test-app/server.ts
Normal file
58
angular/test/test-app/server.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
/**
|
||||
* *** NOTE ON IMPORTING FROM ANGULAR AND NGUNIVERSAL IN THIS FILE ***
|
||||
*
|
||||
* If your application uses third-party dependencies, you'll need to
|
||||
* either use Webpack or the Angular CLI's `bundleDependencies` feature
|
||||
* in order to adequately package them for use on the server without a
|
||||
* node_modules directory.
|
||||
*
|
||||
* However, due to the nature of the CLI's `bundleDependencies`, importing
|
||||
* Angular in this file will create a different instance of Angular than
|
||||
* the version in the compiled application code. This leads to unavoidable
|
||||
* conflicts. Therefore, please do not explicitly import from @angular or
|
||||
* @nguniversal in this file. You can export any needed resources
|
||||
* from your application's main.server.ts file, as seen below with the
|
||||
* import for `ngExpressEngine`.
|
||||
*/
|
||||
|
||||
import 'zone.js/dist/zone-node';
|
||||
|
||||
import * as express from 'express';
|
||||
import {join} from 'path';
|
||||
|
||||
// Express server
|
||||
const app = express();
|
||||
|
||||
const PORT = process.env.PORT || 4000;
|
||||
const DIST_FOLDER = join(process.cwd(), 'dist/browser');
|
||||
|
||||
// * NOTE :: leave this as require() since this file is built Dynamically from webpack
|
||||
const {AppServerModuleNgFactory, LAZY_MODULE_MAP, ngExpressEngine, provideModuleMap} = require('./dist/server/main');
|
||||
|
||||
// Our Universal express-engine (found @ https://github.com/angular/universal/tree/master/modules/express-engine)
|
||||
app.engine('html', ngExpressEngine({
|
||||
bootstrap: AppServerModuleNgFactory,
|
||||
providers: [
|
||||
provideModuleMap(LAZY_MODULE_MAP)
|
||||
]
|
||||
}));
|
||||
|
||||
app.set('view engine', 'html');
|
||||
app.set('views', DIST_FOLDER);
|
||||
|
||||
// Example Express Rest API endpoints
|
||||
// app.get('/api/**', (req, res) => { });
|
||||
// Serve static files from /browser
|
||||
app.get('*.*', express.static(DIST_FOLDER, {
|
||||
maxAge: '1y'
|
||||
}));
|
||||
|
||||
// All regular routes use the Universal engine
|
||||
app.get('*', (req, res) => {
|
||||
res.render('index', { req });
|
||||
});
|
||||
|
||||
// Start up the Node server
|
||||
app.listen(PORT, () => {
|
||||
console.log(`Node Express server listening on http://localhost:${PORT}`);
|
||||
});
|
||||
10
angular/test/test-app/src/app/alert/alert.component.html
Normal file
10
angular/test/test-app/src/app/alert/alert.component.html
Normal file
@@ -0,0 +1,10 @@
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>
|
||||
Alert test
|
||||
</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content padding>
|
||||
<p>Change Detections: <span id="counter">{{counter()}}</span></p>
|
||||
</ion-content>
|
||||
39
angular/test/test-app/src/app/alert/alert.component.ts
Normal file
39
angular/test/test-app/src/app/alert/alert.component.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import { Component, NgZone } from '@angular/core';
|
||||
import { AlertController } from '@ionic/angular';
|
||||
import { NavComponent } from '../nav/nav.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-alert',
|
||||
templateUrl: './alert.component.html',
|
||||
})
|
||||
export class AlertComponent {
|
||||
|
||||
changes = 0;
|
||||
|
||||
constructor(
|
||||
private alertCtrl: AlertController
|
||||
) { }
|
||||
|
||||
counter() {
|
||||
this.changes++;
|
||||
return Math.floor(this.changes / 2);
|
||||
}
|
||||
|
||||
async openAlert() {
|
||||
const alert = await this.alertCtrl.create({
|
||||
header: 'Hello',
|
||||
message: 'Some text',
|
||||
buttons: [
|
||||
{
|
||||
role: 'cancel',
|
||||
text: 'Cancel',
|
||||
handler: () => {
|
||||
console.log(NgZone.isInAngularZone());
|
||||
NgZone.assertInAngularZone();
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
await alert.present();
|
||||
}
|
||||
}
|
||||
@@ -4,11 +4,9 @@ import { InputsComponent } from './inputs/inputs.component';
|
||||
import { ModalComponent } from './modal/modal.component';
|
||||
import { RouterLinkComponent } from './router-link/router-link.component';
|
||||
import { RouterLinkPageComponent } from './router-link-page/router-link-page.component';
|
||||
import { RouterLinkPage2Component } from './router-link-page2/router-link-page2.component';
|
||||
import { RouterLinkPage3Component } from './router-link-page3/router-link-page3.component';
|
||||
import { HomePageComponent } from './home-page/home-page.component';
|
||||
import { TabsComponent } from './tabs/tabs.component';
|
||||
import { TabsTab1Component } from './tabs-tab1/tabs-tab1.component';
|
||||
import { TabsTab1NestedComponent } from './tabs-tab1-nested/tabs-tab1-nested.component';
|
||||
import { TabsTab2Component } from './tabs-tab2/tabs-tab2.component';
|
||||
import { VirtualScrollComponent } from './virtual-scroll/virtual-scroll.component';
|
||||
import { VirtualScrollDetailComponent } from './virtual-scroll-detail/virtual-scroll-detail.component';
|
||||
import { NestedOutletComponent } from './nested-outlet/nested-outlet.component';
|
||||
@@ -21,9 +19,11 @@ import { FormComponent } from './form/form.component';
|
||||
import { NavigationPage1Component } from './navigation-page1/navigation-page1.component';
|
||||
import { NavigationPage2Component } from './navigation-page2/navigation-page2.component';
|
||||
import { NavigationPage3Component } from './navigation-page3/navigation-page3.component';
|
||||
import { AlertComponent } from './alert/alert.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{ path: '', component: HomePageComponent },
|
||||
{ path: 'alerts', component: AlertComponent },
|
||||
{ path: 'inputs', component: InputsComponent },
|
||||
{ path: 'form', component: FormComponent },
|
||||
{ path: 'modals', component: ModalComponent },
|
||||
@@ -31,6 +31,8 @@ const routes: Routes = [
|
||||
{ path: 'providers', component: ProvidersComponent },
|
||||
{ path: 'router-link', component: RouterLinkComponent },
|
||||
{ path: 'router-link-page', component: RouterLinkPageComponent },
|
||||
{ path: 'router-link-page2/:id', component: RouterLinkPage2Component },
|
||||
{ path: 'router-link-page3', component: RouterLinkPage3Component },
|
||||
{ path: 'slides', component: SlidesComponent },
|
||||
{ path: 'virtual-scroll', component: VirtualScrollComponent },
|
||||
{ path: 'virtual-scroll-detail/:itemId', component: VirtualScrollDetailComponent },
|
||||
@@ -45,40 +47,7 @@ const routes: Routes = [
|
||||
},
|
||||
{
|
||||
path: 'tabs',
|
||||
component: TabsComponent,
|
||||
children: [
|
||||
{
|
||||
path: 'account',
|
||||
children: [
|
||||
{
|
||||
path: 'nested/:id',
|
||||
component: TabsTab1NestedComponent
|
||||
},
|
||||
{
|
||||
path: '',
|
||||
component: TabsTab1Component
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: 'contact',
|
||||
children: [
|
||||
{
|
||||
path: 'one',
|
||||
component: TabsTab2Component
|
||||
},
|
||||
{
|
||||
path: '',
|
||||
redirectTo: 'one',
|
||||
pathMatch: 'full'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: 'lazy',
|
||||
loadChildren: './tabs-lazy/tabs-lazy.module#TabsLazyModule'
|
||||
}
|
||||
]
|
||||
loadChildren: () => import('./tabs/tabs.module').then(m => m.TabsPageModule)
|
||||
},
|
||||
{
|
||||
path: 'nested-outlet',
|
||||
|
||||
@@ -1,21 +1,20 @@
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { ReactiveFormsModule } from '@angular/forms';
|
||||
import { RouteReuseStrategy } from '@angular/router';
|
||||
|
||||
import { AppRoutingModule } from './app-routing.module';
|
||||
import { AppComponent } from './app.component';
|
||||
import { IonicModule } from '@ionic/angular';
|
||||
import { IonicModule, IonicRouteStrategy } from '@ionic/angular';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { InputsComponent } from './inputs/inputs.component';
|
||||
import { ModalComponent } from './modal/modal.component';
|
||||
import { ModalExampleComponent } from './modal-example/modal-example.component';
|
||||
import { RouterLinkComponent } from './router-link/router-link.component';
|
||||
import { RouterLinkPageComponent } from './router-link-page/router-link-page.component';
|
||||
import { RouterLinkPage2Component } from './router-link-page2/router-link-page2.component';
|
||||
import { RouterLinkPage3Component } from './router-link-page3/router-link-page3.component';
|
||||
import { HomePageComponent } from './home-page/home-page.component';
|
||||
import { TabsComponent } from './tabs/tabs.component';
|
||||
import { TabsTab1Component } from './tabs-tab1/tabs-tab1.component';
|
||||
import { TabsTab2Component } from './tabs-tab2/tabs-tab2.component';
|
||||
import { TabsTab1NestedComponent } from './tabs-tab1-nested/tabs-tab1-nested.component';
|
||||
import { VirtualScrollComponent } from './virtual-scroll/virtual-scroll.component';
|
||||
import { VirtualScrollDetailComponent } from './virtual-scroll-detail/virtual-scroll-detail.component';
|
||||
import { VirtualScrollInnerComponent } from './virtual-scroll-inner/virtual-scroll-inner.component';
|
||||
@@ -30,6 +29,7 @@ import { FormComponent } from './form/form.component';
|
||||
import { NavigationPage1Component } from './navigation-page1/navigation-page1.component';
|
||||
import { NavigationPage2Component } from './navigation-page2/navigation-page2.component';
|
||||
import { NavigationPage3Component } from './navigation-page3/navigation-page3.component';
|
||||
import { AlertComponent } from './alert/alert.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
@@ -39,11 +39,9 @@ import { NavigationPage3Component } from './navigation-page3/navigation-page3.co
|
||||
ModalExampleComponent,
|
||||
RouterLinkComponent,
|
||||
RouterLinkPageComponent,
|
||||
RouterLinkPage2Component,
|
||||
RouterLinkPage3Component,
|
||||
HomePageComponent,
|
||||
TabsComponent,
|
||||
TabsTab1Component,
|
||||
TabsTab2Component,
|
||||
TabsTab1NestedComponent,
|
||||
VirtualScrollComponent,
|
||||
VirtualScrollDetailComponent,
|
||||
VirtualScrollInnerComponent,
|
||||
@@ -57,10 +55,11 @@ import { NavigationPage3Component } from './navigation-page3/navigation-page3.co
|
||||
FormComponent,
|
||||
NavigationPage1Component,
|
||||
NavigationPage2Component,
|
||||
NavigationPage3Component
|
||||
NavigationPage3Component,
|
||||
AlertComponent
|
||||
],
|
||||
imports: [
|
||||
BrowserModule,
|
||||
BrowserModule.withServerTransition({ appId: 'serverApp' }),
|
||||
AppRoutingModule,
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
@@ -70,7 +69,9 @@ import { NavigationPage3Component } from './navigation-page3/navigation-page3.co
|
||||
ModalExampleComponent,
|
||||
NavComponent
|
||||
],
|
||||
providers: [],
|
||||
providers: [
|
||||
{ provide: RouteReuseStrategy, useClass: IonicRouteStrategy },
|
||||
],
|
||||
bootstrap: [AppComponent]
|
||||
})
|
||||
export class AppModule { }
|
||||
|
||||
19
angular/test/test-app/src/app/app.server.module.ts
Normal file
19
angular/test/test-app/src/app/app.server.module.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { ServerModule } from '@angular/platform-server';
|
||||
|
||||
import { IonicServerModule } from '@ionic/angular-server';
|
||||
|
||||
import { AppModule } from './app.module';
|
||||
import { AppComponent } from './app.component';
|
||||
import { ModuleMapLoaderModule } from '@nguniversal/module-map-ngfactory-loader';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
AppModule,
|
||||
ServerModule,
|
||||
ModuleMapLoaderModule,
|
||||
IonicServerModule
|
||||
],
|
||||
bootstrap: [AppComponent],
|
||||
})
|
||||
export class AppServerModule {}
|
||||
@@ -20,7 +20,9 @@ export class FormComponent {
|
||||
input2: ['Default Value'],
|
||||
checkbox: [false],
|
||||
range: [5, Validators.min(10)],
|
||||
}, {updateOn: window.location.hash === '#blur' ? 'blur' : 'change'});
|
||||
}, {
|
||||
updateOn: typeof (window as any) !== 'undefined' && window.location.hash === '#blur' ? 'blur' : 'change'
|
||||
});
|
||||
}
|
||||
|
||||
onSubmit(_ev) {
|
||||
|
||||
@@ -7,6 +7,11 @@
|
||||
</ion-header>
|
||||
<ion-content>
|
||||
<ion-list>
|
||||
<ion-item routerLink="/alerts">
|
||||
<ion-label>
|
||||
Alerts test
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
<ion-item routerLink="/inputs">
|
||||
<ion-label>
|
||||
Inputs test
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content>
|
||||
<p>Change Detections: <span id="counter">{{counter()}}</span></p>
|
||||
<ion-list>
|
||||
|
||||
<ion-item>
|
||||
@@ -89,10 +90,12 @@
|
||||
<ion-range [(ngModel)]="range"></ion-range>
|
||||
<ion-note slot="end" id="range-note">{{range}}</ion-note>
|
||||
</ion-item>
|
||||
|
||||
|
||||
<ion-item color="dark">
|
||||
<ion-label>Range Mirror</ion-label>
|
||||
<ion-range [(ngModel)]="range"></ion-range>
|
||||
<ion-range [(ngModel)]="range">
|
||||
<ion-toggle slot="start" id="nested-toggle" [(ngModel)]="toggle"></ion-toggle>
|
||||
</ion-range>
|
||||
<ion-note slot="end">{{range}}</ion-note>
|
||||
</ion-item>
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ export class InputsComponent {
|
||||
toggle = true;
|
||||
select = 'nes';
|
||||
range = 10;
|
||||
changes = 0;
|
||||
|
||||
setValues() {
|
||||
console.log('set values');
|
||||
@@ -32,4 +33,8 @@ export class InputsComponent {
|
||||
this.select = undefined;
|
||||
this.range = undefined;
|
||||
}
|
||||
counter() {
|
||||
this.changes++;
|
||||
return Math.floor(this.changes / 2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-buttons slot="start">
|
||||
<ion-back-button></ion-back-button>
|
||||
</ion-buttons>
|
||||
<ion-title>
|
||||
NESTED OUTLET
|
||||
</ion-title>
|
||||
|
||||
@@ -12,6 +12,15 @@
|
||||
<p>
|
||||
isReady: <span id="is-ready">{{isReady}}</span>
|
||||
</p>
|
||||
<p>
|
||||
isResumed: <span id="is-resumed">{{isResumed}}</span>
|
||||
</p>
|
||||
<p>
|
||||
isPaused: <span id="is-paused">{{isPaused}}</span>
|
||||
</p>
|
||||
<p>
|
||||
isResized: <span id="is-resized">{{isResized}}</span>
|
||||
</p>
|
||||
<p>
|
||||
isTesting: <span id="is-testing">{{isTesting}}</span>
|
||||
</p>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { Component, NgZone } from '@angular/core';
|
||||
import {
|
||||
Platform, Config, ModalController, AlertController, ActionSheetController,
|
||||
PopoverController, ToastController, Events, PickerController, MenuController,
|
||||
LoadingController, NavController, DomController
|
||||
Platform, ModalController, AlertController, ActionSheetController,
|
||||
PopoverController, ToastController, Events, PickerController, MenuController,
|
||||
LoadingController, NavController, DomController, Config
|
||||
} from '@ionic/angular';
|
||||
|
||||
@Component({
|
||||
@@ -14,6 +14,9 @@ export class ProvidersComponent {
|
||||
isLoaded = false;
|
||||
isReady = false;
|
||||
isEvent = false;
|
||||
isResumed = false;
|
||||
isPaused = false;
|
||||
isResized = false;
|
||||
isTesting: boolean = undefined;
|
||||
isDesktop: boolean = undefined;
|
||||
isMobile: boolean = undefined;
|
||||
@@ -32,7 +35,8 @@ export class ProvidersComponent {
|
||||
toastCtrl: ToastController,
|
||||
navCtrl: NavController,
|
||||
domCtrl: DomController,
|
||||
config: Config
|
||||
config: Config,
|
||||
zone: NgZone
|
||||
) {
|
||||
// test all providers load
|
||||
if (
|
||||
@@ -44,15 +48,31 @@ export class ProvidersComponent {
|
||||
|
||||
// test platform ready()
|
||||
platform.ready().then(() => {
|
||||
NgZone.assertInAngularZone();
|
||||
this.isReady = true;
|
||||
});
|
||||
|
||||
platform.resume.subscribe(() => {
|
||||
console.log('platform:resume');
|
||||
NgZone.assertInAngularZone();
|
||||
this.isResumed = true;
|
||||
});
|
||||
platform.pause.subscribe(() => {
|
||||
console.log('platform:pause');
|
||||
NgZone.assertInAngularZone();
|
||||
this.isPaused = true;
|
||||
});
|
||||
platform.resize.subscribe(() => {
|
||||
console.log('platform:resize');
|
||||
NgZone.assertInAngularZone();
|
||||
this.isResized = true;
|
||||
});
|
||||
this.isDesktop = platform.is('desktop');
|
||||
this.isMobile = platform.is('mobile');
|
||||
|
||||
// test events
|
||||
events.subscribe('topic', () => {
|
||||
this.isEvent = true;
|
||||
NgZone.assertInAngularZone();
|
||||
});
|
||||
events.publish('topic');
|
||||
|
||||
@@ -60,5 +80,11 @@ export class ProvidersComponent {
|
||||
this.isTesting = config.getBoolean('_testing');
|
||||
config.set('keyboardHeight', 12345);
|
||||
this.keyboardHeight = config.getNumber('keyboardHeight');
|
||||
|
||||
zone.runOutsideAngular(() => {
|
||||
document.dispatchEvent(new CustomEvent('pause'));
|
||||
document.dispatchEvent(new CustomEvent('resume'));
|
||||
window.dispatchEvent(new CustomEvent('resize'));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
<ion-content padding>
|
||||
<p>ngOnInit: <span id="ngOnInit">{{onInit}}</span></p>
|
||||
<p>canGoBack: <span id="canGoBack">{{canGoBack}}</span></p>
|
||||
<p>ionViewWillEnter: <span id="ionViewWillEnter">{{willEnter}}</span></p>
|
||||
<p>ionViewDidEnter: <span id="ionViewDidEnter">{{didEnter}}</span></p>
|
||||
<p>ionViewWillLeave: <span id="ionViewWillLeave">{{willLeave}}</span></p>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Component, OnInit, NgZone } from '@angular/core';
|
||||
import { IonRouterOutlet } from '@ionic/angular';
|
||||
|
||||
@Component({
|
||||
selector: 'app-router-link-page',
|
||||
@@ -11,9 +12,15 @@ export class RouterLinkPageComponent implements OnInit {
|
||||
didEnter = 0;
|
||||
willLeave = 0;
|
||||
didLeave = 0;
|
||||
canGoBack: boolean = null;
|
||||
|
||||
constructor(
|
||||
private ionRouterOutlet: IonRouterOutlet
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
NgZone.assertInAngularZone();
|
||||
this.canGoBack = this.ionRouterOutlet.canGoBack();
|
||||
this.onInit++;
|
||||
}
|
||||
|
||||
@@ -21,10 +28,16 @@ export class RouterLinkPageComponent implements OnInit {
|
||||
if (this.onInit !== 1) {
|
||||
throw new Error('ngOnInit was not called');
|
||||
}
|
||||
if (this.canGoBack !== this.ionRouterOutlet.canGoBack()) {
|
||||
throw new Error('canGoBack() changed');
|
||||
}
|
||||
NgZone.assertInAngularZone();
|
||||
this.willEnter++;
|
||||
}
|
||||
ionViewDidEnter() {
|
||||
if (this.canGoBack !== this.ionRouterOutlet.canGoBack()) {
|
||||
throw new Error('canGoBack() changed');
|
||||
}
|
||||
NgZone.assertInAngularZone();
|
||||
this.didEnter++;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-buttons slot="start">
|
||||
<ion-back-button></ion-back-button>
|
||||
</ion-buttons>
|
||||
<ion-title>Router Page 2</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<ion-content padding>
|
||||
<ion-button routerLink="/router-link-page3" id="goToPage3">Go to Page 3</ion-button>
|
||||
</ion-content>
|
||||
@@ -0,0 +1,14 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-router-link-page2',
|
||||
templateUrl: './router-link-page2.component.html'
|
||||
})
|
||||
export class RouterLinkPage2Component implements OnInit {
|
||||
|
||||
constructor() { }
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
<ion-header>
|
||||
<ion-toolbar color="dark">
|
||||
<ion-buttons slot="start">
|
||||
<ion-back-button defaultHref="/?token=ABC#fragment" id="goBackFromPage3"></ion-back-button>
|
||||
</ion-buttons>
|
||||
<ion-title>Router Page 3</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<ion-content padding>
|
||||
Page 3
|
||||
</ion-content>
|
||||
@@ -0,0 +1,14 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-router-link-page3',
|
||||
templateUrl: './router-link-page3.component.html'
|
||||
})
|
||||
export class RouterLinkPage3Component implements OnInit {
|
||||
|
||||
constructor() { }
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -11,6 +11,7 @@
|
||||
<p>ionViewDidEnter: <span id="ionViewDidEnter">{{didEnter}}</span></p>
|
||||
<p>ionViewWillLeave: <span id="ionViewWillLeave">{{willLeave}}</span></p>
|
||||
<p>ionViewDidLeave: <span id="ionViewDidLeave">{{didLeave}}</span></p>
|
||||
<p>Change Detections: <span id="counter">{{counter()}}</span></p>
|
||||
|
||||
<p>
|
||||
<ion-button routerLink="/router-link-page" expand="block" color="dark" id="routerLink">ion-button[routerLink]</ion-button>
|
||||
@@ -27,4 +28,6 @@
|
||||
<p><button (click)="navigateRoot()" id="button-root">navigateForward</button></p>
|
||||
<p><button (click)="navigateBack()" id="button-back">navigateBack</button></p>
|
||||
|
||||
<p><button id="queryParamsFragment" routerLink="/router-link-page2/MyPageID==" [queryParams]="{ token: 'A&=#Y' }" fragment="myDiv1">Query Params and Fragment</button></p>
|
||||
|
||||
</ion-content>
|
||||
|
||||
@@ -13,6 +13,7 @@ export class RouterLinkComponent implements OnInit {
|
||||
didEnter = 0;
|
||||
willLeave = 0;
|
||||
didLeave = 0;
|
||||
changes = 0;
|
||||
|
||||
constructor(
|
||||
private navCtrl: NavController,
|
||||
@@ -35,6 +36,11 @@ export class RouterLinkComponent implements OnInit {
|
||||
this.navCtrl.navigateRoot('/router-link-page');
|
||||
}
|
||||
|
||||
counter() {
|
||||
this.changes++;
|
||||
return Math.floor(this.changes / 2);
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
NgZone.assertInAngularZone();
|
||||
this.onInit++;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Component, OnInit, ViewChild, AfterViewInit } from '@angular/core';
|
||||
import { AfterViewInit, Component, ViewChild } from '@angular/core';
|
||||
import { IonSlides } from '@ionic/angular';
|
||||
|
||||
@Component({
|
||||
@@ -6,7 +6,7 @@ import { IonSlides } from '@ionic/angular';
|
||||
templateUrl: './slides.component.html',
|
||||
})
|
||||
export class SlidesComponent implements AfterViewInit {
|
||||
@ViewChild(IonSlides) slides: IonSlides;
|
||||
@ViewChild(IonSlides, { static: true }) slides: IonSlides;
|
||||
|
||||
slideIndex = 0;
|
||||
slideIndex2 = 0;
|
||||
|
||||
@@ -10,6 +10,6 @@
|
||||
<ion-content padding>
|
||||
<p>
|
||||
<ion-button routerLink="/tabs/account" id="goto-tab1-page1">Go to Tab 1 - Page 1</ion-button>
|
||||
<ion-button routerLink="/tabs/account/nested/12" id="goto-tab1-page2">Go to Tab 1 - Page 2</ion-button>
|
||||
<ion-button routerLink="/tabs/account/nested/1" id="goto-tab1-page2">Go to Tab 1 - Page 2</ion-button>
|
||||
</p>
|
||||
</ion-content>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<h1>LAZY LOADED TAB</h1>
|
||||
<p>
|
||||
<ion-button routerLink="/tabs/account" id="goto-tab1-page1">Go to Tab 1 - Page 1</ion-button>
|
||||
<ion-button routerLink="/tabs/account/nested/12" id="goto-tab1-page2">Go to Tab 1 - Page 2</ion-button>
|
||||
<ion-button routerLink="/tabs/account/nested/1" id="goto-tab1-page2">Go to Tab 1 - Page 2</ion-button>
|
||||
<ion-button routerLink="/tabs/lazy/nested" id="goto-tab3-page2">Go to Tab 3 - Page 2</ion-button>
|
||||
|
||||
</p>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>Tab 1 - Page 2</ion-title>
|
||||
<ion-title>Tab 1 - Page 2 ({{id}})</ion-title>
|
||||
<ion-buttons slot="start">
|
||||
<ion-back-button></ion-back-button>
|
||||
</ion-buttons>
|
||||
@@ -8,9 +8,10 @@
|
||||
</ion-header>
|
||||
|
||||
<ion-content padding>
|
||||
<h1>Welcome to NESTED PAGE</h1>
|
||||
<h1>Welcome to NESTED PAGE {{id}}</h1>
|
||||
<p>
|
||||
<ion-button routerLink="/tabs/account" id="goto-tab1-page1">Go to Tab 1 - Page 1</ion-button>
|
||||
<ion-button routerLink="/tabs/contact" id="goto-tab2-page1">Go to Tab 2 - Page 1</ion-button>
|
||||
<ion-button routerLink="/tabs/account/nested/{{next()}}" id="goto-next">Go to Next</ion-button>
|
||||
</p>
|
||||
</ion-content>
|
||||
|
||||
@@ -1,7 +1,21 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { Component, Input } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-tabs-tab1-nested',
|
||||
templateUrl: './tabs-tab1-nested.component.html',
|
||||
})
|
||||
export class TabsTab1NestedComponent { }
|
||||
export class TabsTab1NestedComponent {
|
||||
id = '';
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.id = this.route.snapshot.paramMap.get('id');
|
||||
}
|
||||
|
||||
next() {
|
||||
return parseInt(this.id, 10) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>Tab 1 - Page 1</ion-title>
|
||||
<ion-title>{{title}}</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<ion-content padding>
|
||||
<h1>Welcome to Tab1</h1>
|
||||
<p>
|
||||
<ion-button routerLink="/tabs/account/nested/12" id="goto-tab1-page2">Go to Page 2</ion-button>
|
||||
<ion-button routerLink="/tabs/account/nested/1" id="goto-tab1-page2">Go to Page 2</ion-button>
|
||||
<ion-button routerLink="/tabs/lazy/nested" id="goto-tab3-page2">Go to Tab 3 - Page 2</ion-button>
|
||||
<ion-button routerLink="/nested-outlet/page" id="goto-nested-page1">Go to nested</ion-button>
|
||||
</p>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user