Angularfire does not work on ionic capacitor app on ios - ios

I am using ionic with capacitor and angularfire. It works fine but does not work on ios. On ios I don't see any error - just the firebase call that never returns anything. Below is my package.json and other relevant info.
ionic.info:
ionic info
Ionic:
Ionic CLI : 6.18.1 (/usr/local/lib/node_modules/#ionic/cli)
Ionic Framework : #ionic/angular 5.9.1
#angular-devkit/build-angular : 12.1.4
#angular-devkit/schematics : 12.1.4
#angular/cli : 12.1.4
#ionic/angular-toolkit : 4.0.0
Capacitor:
Capacitor CLI : 3.3.2
#capacitor/android : 3.3.2
#capacitor/core : 3.3.2
#capacitor/ios : 3.3.2
Cordova:
Cordova CLI : 10.0.0 (cordova-lib#10.1.0)
Cordova Platforms : android broken, ios 5.1.1
Cordova Plugins : no whitelisted plugins (0 plugins total)
Utility:
cordova-res (update available: 0.15.4) : 0.15.3
native-run : 1.5.0
System:
ios-deploy : 1.9.4
ios-sim : ios-sim/9.0.0 darwin-x64 node-v14.17.0
NodeJS : v14.17.0 (/usr/local/bin/node)
npm : 7.24.0
OS : macOS Monterey
Xcode : Xcode 13.1 Build version 13A1030d
Package.json:
"dependencies": {
"#angular/common": "~12.1.1",
"#angular/core": "~12.1.1",
"#angular/fire": "^7.2.0",
"#angular/forms": "~12.1.1",
"#angular/platform-browser": "~12.1.1",
"#angular/platform-browser-dynamic": "~12.1.1",
"#angular/router": "~12.1.1",
"#capacitor/android": "^3.3.2",
"#capacitor/app": "^1.0.6",
"#capacitor/browser": "^1.0.6",
"#capacitor/core": "3.3.2",
"#capacitor/device": "^1.1.0",
"#capacitor/haptics": "^1.1.3",
"#capacitor/ios": "^3.3.2",
"#capacitor/keyboard": "^1.1.3",
"#capacitor/splash-screen": "^1.1.6",
"#capacitor/status-bar": "^1.0.6",
"#capacitor/storage": "^1.2.3",
"#ionic-native/app-version": "^5.36.0",
"#ionic-native/barcode-scanner": "^5.36.0",
"#ionic-native/call-number": "^5.36.0",
"#ionic-native/camera": "^5.36.0",
"#ionic-native/camera-preview": "^5.36.0",
"#ionic-native/contacts": "^5.36.0",
"#ionic-native/email-composer": "^5.36.0",
"#ionic-native/in-app-browser": "^5.36.0",
"#ionic-native/in-app-purchase": "^5.36.0",
"#ionic-native/in-app-purchase-2": "^5.36.0",
"#ionic-native/social-sharing": "^5.36.0",
"#ionic/angular": "^5.5.2",
"#ngx-translate/core": "^11.0.1",
"#ngx-translate/http-loader": "^4.0.0",
"call-number": "^1.0.1",
"cordova-plugin-app-version": "^0.1.12",
"cordova-plugin-camera": "^6.0.0",
"cordova-plugin-camera-preview": "^0.12.3",
"cordova-plugin-contacts": "^3.0.1",
"cordova-plugin-email-composer": "^0.10.0",
"cordova-plugin-inappbrowser": "^5.0.0",
"cordova-plugin-inapppurchase": "^1.2.0",
"cordova-plugin-purchase": "^10.6.1",
"cordova-plugin-x-socialsharing": "^6.0.3",
"firebase": "^9.5.0",
"forcejs": "^2.2.1",
"phonegap-plugin-barcodescanner": "^8.1.0",
"rxjs": "~6.6.0",
"tslib": "^2.2.0",
"xcode": "^3.0.1",
"xml-js": "^1.6.11",
"zone.js": "~0.11.4"
},
"devDependencies": {
"#angular-devkit/build-angular": "~12.1.1",
"#angular-eslint/builder": "~12.0.0",
"#angular-eslint/eslint-plugin": "~12.0.0",
"#angular-eslint/eslint-plugin-template": "~12.0.0",
"#angular-eslint/template-parser": "~12.0.0",
"#angular/cli": "~12.1.1",
"#angular/compiler": "~12.1.1",
"#angular/compiler-cli": "~12.1.1",
"#angular/language-service": "~12.0.1",
"#capacitor/cli": "3.3.2",
"#ionic/angular-toolkit": "^4.0.0",
"#types/jasmine": "~3.6.0",
"#types/jasminewd2": "~2.0.3",
"#types/node": "^12.11.1",
"#typescript-eslint/eslint-plugin": "4.16.1",
"#typescript-eslint/parser": "4.16.1",
"es6-promise-plugin": "^4.2.2",
"eslint": "^7.6.0",
"eslint-plugin-import": "2.22.1",
"eslint-plugin-jsdoc": "30.7.6",
"eslint-plugin-prefer-arrow": "1.2.2",
"jasmine-core": "~3.8.0",
"jasmine-spec-reporter": "~5.0.0",
"karma": "~6.3.2",
"karma-chrome-launcher": "~3.1.0",
"karma-coverage": "~2.0.3",
"karma-coverage-istanbul-reporter": "~3.0.2",
"karma-jasmine": "~4.0.0",
"karma-jasmine-html-reporter": "^1.5.0",
"protractor": "~7.0.0",
"ts-node": "~8.3.0",
"typescript": "~4.2.4"
}
app.module.ts:
import { NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { RouteReuseStrategy } from '#angular/router';
import { AngularFireModule } from '#angular/fire/compat';
import { AngularFireDatabaseModule } from '#angular/fire/compat/database';
import { IonicModule, IonicRouteStrategy } from '#ionic/angular';
import { FormsModule } from '#angular/forms';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
#NgModule({
declarations: [
AppComponent,
],
entryComponents: [
],
imports: [
AngularFireModule.initializeApp(firebaseConfig),
AngularFireDatabaseModule,
BrowserModule,
HttpClientModule,
IonicModule.forRoot(),
AppRoutingModule,
FormsModule,
],
providers: [
{ provide: RouteReuseStrategy, useClass: IonicRouteStrategy }
],
bootstrap: [AppComponent]
})
export class AppModule {}
The code that never executes and no error in catch block is below. Same works just fine on android:
const resp:any = await this.dataSvc.getSeedConfig()
console.log("seed config is::" + JSON.stringify(resp))
So the above code does not go to the catch block and does not print the seed config on ios. Works fine on android.
Also on ios it works using live reload using
ionic capacitor run ios -l --external
so if i run it using xcode then it does not work. not sure what is blocking in that specific case

Already answered this here https://stackoverflow.com/a/70594992/5701521 but could be useful to answer it here as well.
Been struggling a lot with this issue too but I managed to fix it. For those who need help here's my code.
You can delete all Firebase related imports from app.module.ts since this solution only uses Firebase.
The packages rxfire and #angular/fire can be removed from your package.json. The only dependency I have is "firebase": "^9.6.1".
I used observables for the getObject and list functions since that's what I'm used to and I didn't want to rewrite my original code.
import { Injectable } from '#angular/core';
import { Capacitor } from '#capacitor/core';
import { environment } from '#environment';
import { initializeApp } from 'firebase/app';
import { Auth, getAuth, indexedDBLocalPersistence, initializeAuth, signInWithCustomToken } from 'firebase/auth';
import { Database, getDatabase, onValue, orderByChild, query, ref } from 'firebase/database';
import { Observable, Observer, from } from 'rxjs';
#Injectable({
providedIn: 'root'
})
export class FirebaseService {
private readonly database: Database;
private readonly auth: Auth;
constructor() {
const firebaseApp = initializeApp(environment.firebase);
if (Capacitor.isNativePlatform()) {
initializeAuth(firebaseApp, {
persistence: indexedDBLocalPersistence
});
}
this.database = getDatabase(firebaseApp);
this.auth = getAuth(firebaseApp);
}
connectFirebase(firebaseToken) {
return from(signInWithCustomToken(this.auth, firebaseToken));
}
disconnectFirebase() {
return from(this.auth.signOut());
}
getObject<T>(path: string): Observable<T> {
return new Observable((observer: Observer<T>) => {
const dbRef = ref(this.database, path);
const listener = onValue(dbRef, snapshot => {
const data = snapshot.val();
observer.next(data);
});
return {
unsubscribe() {
listener();
}
};
});
}
public list<T>(path: string, orderChildBy?: string): Observable<Array<T>> {
return new Observable<Array<T>>((observer: Observer<Array<T>>) => {
const dbRef = ref(this.database, path);
const dbReference = !orderChildBy ? dbRef : query(dbRef, orderByChild(orderChildBy));
const listener = onValue(dbReference, snapshot => {
const data = Object.values<T>(snapshot.val() || {});
console.log(path, data);
observer.next(data);
});
return {
unsubscribe() {
listener();
}
};
});
}
}
For those who can't see the error message thrown by firebase try the following command in your Safari console to see the error.
window.location.reload()

Try to downgrade your angularfire to v7.0 it might work with firebase v9.

in my case i folow this link: https://github.com/angular/angularfire/issues/3087#issuecomment-990599459
I was also having this issue when building for an iOS emulator and actual iOS device, but adding this to the app.component.ts worked for me.
import { Component } from '#angular/core';
import { Capacitor } from '#capacitor/core';
import { initializeApp } from 'firebase/app';
import { indexedDBLocalPersistence, initializeAuth } from 'firebase/auth';
import { environment } from 'src/environments/environment';
#Component({
selector: 'app-root',
templateUrl: 'app.component.html',
styleUrls: ['app.component.scss'],
})
export class AppComponent {
constructor() {
const app = initializeApp(environment.firebase);
if (Capacitor.isNativePlatform) {
initializeAuth(app, {
persistence: indexedDBLocalPersistence
});
}
}
}
This is where I found the fix and a sample code

Related

Angular <mat-expansion-panel-header> does not expand

I am learning Angular and using Material for Angular for styling. For some reason the mat-accordian isn't working for me.
<mat-accordion>
<mat-expansion-panel >
<mat-expansion-panel-header>
<mat-panel-title>
<h2>Post 1</h2>
</mat-panel-title>
<mat-panel-description>
<p>Post 1 Content</p>
</mat-panel-description>
</mat-expansion-panel-header>
<p>I'm in an expansion panel</p>
</mat-expansion-panel>
</mat-accordion>
import { NgModule } from '#angular/core';
import { BrowserAnimationsModule } from '#angular/platform-browser/animations';
import { BrowserModule } from '#angular/platform-browser';
import {
MatInputModule,
MatCardModule,
MatButtonModule,
MatToolbarModule,
MatExpansionModule
} from '#angular/material/';
import { AppComponent } from './app.component';
import { FormsModule } from '#angular/forms';
import { PostCreateComponent } from './posts/post-create/post-create.component';
import { HeaderComponent } from './header/header.component';
import { PostListComponent } from './posts/post-create/post-list/post-list.component';
#NgModule({
declarations: [
AppComponent,
PostCreateComponent,
HeaderComponent,
PostListComponent,
],
imports: [
BrowserModule,
BrowserAnimationsModule,
FormsModule,
MatInputModule,
MatCardModule,
MatButtonModule,
MatToolbarModule,
MatExpansionModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
"dependencies": {
"#angular/animations": "^14.2.0",
"#angular/common": "^14.2.0",
"#angular/compiler": "^14.2.0",
"#angular/core": "^14.2.0",
"#angular/forms": "^14.2.0",
"#angular/material": "^7.0.0",
"#angular/cdk": "^7.0.0",
"#angular/platform-browser": "^14.2.0",
"#angular/platform-browser-dynamic": "^14.2.0",
"#angular/router": "^14.2.0",
"rxjs": "~7.5.0",
"tslib": "^2.3.0",
"zone.js": "~0.11.4"
I've tried reading other posts on stack overflow but nothing has seemed to work.
I tried installing with
import {MatExpansionModule} from '#angular/material/expansion';
but this doesn't work. The accordion is just forever open. Does anyone with Angular experience know where I am going wrong?
Solved: If you install using the default installation and there are peer dependencies it will install an earlier version of Angular Material.
To Fix the issue I uninstalled Angular globally, cleared the cache, then reinstalled, and was able to resolve the dependency conflicts and install the latest version.

Updated Vue3 on Rails and vue components stop show up at all without errors :(

I updated from Vue2 to Vue3 and now kind of stuck. I use it inside Rails.
The problem that everything is loading and compiling, not errors at all. I load my web page and see everything instead of Vue files. Don't understand how to fix it at all :(
Any ideas? Maybe I don't see smth or don't know where to looking for it.
If I change smth on the application file it shows some changes or errors. I even deleted everything and add Vue files like in tutorials shows and still nothing to work.
application.js
require("#rails/ujs").start()
require("turbolinks").start()
require("#rails/activestorage").start()
require("channels")
import Routes from '../routes/index.js.erb';
import '../css/index.css'
window.Routes = Routes;
import {createApp} from 'vue';
import Customer from '../customer.vue'
import CustomerSearch from '../customer_search.vue'
import CustomerPackages from '../customer_packages.vue'
import BusinessCases from '../business_cases.vue'
import SearchPanel from '../components/business_case/SearchPanel.vue'
import {turbolinksAdapterMixin} from "vue-turbolinks";
import Clipboard from 'v-clipboard'
document.addEventListener('turbolinks:load', () => {
const app = createApp({
el: "[data-behavior='vue']",
mixins: [turbolinksAdapterMixin],
})
})
app.component('customer', Customer);
app.component('customer-search', CustomerSearch);
app.component('packages', CustomerPackages);
app.component('business-cases', BusinessCases);
app.component('search-panel', SearchPanel);
envirement.js
const { environment } = require('#rails/webpacker')
const { VueLoaderPlugin } = require('vue-loader')
const vue = require('./loaders/vue')
const erb = require('./loaders/erb')
const pug = require('./loaders/pug')
environment.plugins.prepend('VueLoaderPlugin', new VueLoaderPlugin())
environment.loaders.prepend('vue', vue)
environment.loaders.prepend('erb', erb)
environment.loaders.prepend('pug', pug)
module.exports = environment
package.json
{
"name": "backyard",
"private": true,
"dependencies": {
"#rails/actioncable": "^6.0.0",
"#rails/activestorage": "^6.0.0",
"#rails/ujs": "^6.0.0",
"#rails/webpacker": "5.2.1",
"#tailwindcss/aspect-ratio": "^0.2.0",
"#tailwindcss/forms": "^0.2.1",
"#tailwindcss/typography": "^0.4.0",
"#vue/cli": "^5.0.0-alpha.8",
"axios": "^0.21.0",
"css-loader": "^5.0.2",
"dayjs": "^1.10.4",
"litepie-datepicker": "^1.0.13",
"node-sass": "4.14",
"pug": "^3.0.0",
"pug-plain-loader": "^1.1.0",
"rails-erb-loader": "^5.5.2",
"sass": "^1.32.7",
"sass-loader": "^11.0.1",
"turbolinks": "^5.2.0",
"v-clipboard": "^2.2.3",
"vue": "^3.0.2",
"vue-clickaway": "^2.2.2",
"vue-clipboards": "^1.3.0",
"vue-fuse": "^2.2.1",
"vue-loader": "^16.2.0",
"vue-nav-tabs": "^0.5.7",
"vue-pdf": "^4.2.0",
"vue-pug": "^4.0.0",
"vue-turbolinks": "^2.1.0",
"webpack": "4"
},
"version": "0.1.0",
"devDependencies": {
"#tailwindcss/postcss7-compat": "^2.0.3",
"#vue/compiler-sfc": "^3.0.11",
"#webpack-cli/serve": "^1.3.0",
"autoprefixer": "9",
"postcss": "7",
"tailwindcss": "npm:#tailwindcss/postcss7-compat",
"vue-cli-plugin-pug": "~2.0.0",
"webpack-cli": "3.3.12",
"webpack-dev-server": "^3.11.2"
},
"browserslist": [
"defaults"
]
}
I've had a similar problem and my best guess is the turbolinksAdapterMixin. Vue 3 changed and renamed destroy hooks to unmounted hooks (see here) besides other changes to their Component APIs. I believe, the package vue-turbolinks still uses Vue 2 functionalities, such as $on, $off, and $once for events.
The way Turbolinks works is that the "next HTML body" is fetched via AJAX which in turn replaces the document.body.
So, what you need to do – and already did correctly – is to create the Vue 3 App with createApp in the event listener for turbolinks:load (when the body was successfully replaced).
And then you have to tear down, i.e., unmount, your Vue app as soon as you leave the page (i.e., click a turbolinks link) with unmount().
Hence, you have to replace your code:
document.addEventListener('turbolinks:load', () => {
const app = createApp({
el: "[data-behavior='vue']",
mixins: [turbolinksAdapterMixin],
})
})
with this:
let app;
document.addEventListener('turbolinks:load', () => {
app = createApp({});
app.mount("[data-behavior='vue']");
});
// this event listener is executed as soon as
// the new body was fetched successfully but
// before replacing the `document.body`
document.addEventListener('turbolinks:before-render', () => {
if (app) app.unmount();
});

Using #ngrx/Effect an effect is not being triggered by an Action

I expect that the Effect that I created should be triggered by dispatching an action, but it is not happening.
The action is being dispatched correctly, but the effect seems that is not properly watching this.
I created this effect:
import { Injectable } from '#angular/core';
import { Actions, Effect, ofType } from '#ngrx/effects';
import { Action } from '#ngrx/store';
import { Observable, of } from 'rxjs';
import { map, mergeMap, catchError } from 'rxjs/operators';
import { PoliciesService } from 'app/services/policies';
import * as policiesActions from '../actions/policies.actions';
import { Policy } from 'app/dtos/policy.dto';
import { PoliciesMapper } from 'app/services/policies/policies.mapper';
Injectable();
export class PoliciesEffect {
constructor(
private actions$: Actions,
private policyService: PoliciesService
) { }
#Effect()
getPolicies$: Observable<Action> = this.actions$.pipe(
ofType<policiesActions.GetPoliciesAction>(
policiesActions.ActionPoliciesType.GET_POLICIES
),
mergeMap((actions: policiesActions.GetPoliciesAction) =>
this.policyService.getPolicies().pipe(
map((policies: Policy[]) =>
new policiesActions.GetPoliciesActionSuccess(PoliciesMapper.policiesCollectionToPoliciesModelCollection(policies))
),
catchError(err => of(new policiesActions.GetPoliciesActionFailed(err)))
)
)
);
}
This effect expect to be triggered once the Action GetPoliciesAction is being dispatch.
This is not happening so I am not able to do the HTTP request to get my data from the server.
Here are the Actions that I created using #ngrx/store:
import { Action } from '#ngrx/store';
import { Policy } from 'app/dtos/policy.dto';
import { PolicyModel } from 'app/models/policy.model';
export enum ActionPoliciesType {
GET_POLICIES = '[Policies] Get all policies list',
GET_POLICIES_SUCCESS = '[Policies] Policies received succesfully',
GET_POLICIES_FAILED = '[Policies] Policies reception failed'
}
export class GetPoliciesAction implements Action {
readonly type = ActionPoliciesType.GET_POLICIES;
constructor() { }
}
export class GetPoliciesActionSuccess implements Action {
readonly type = ActionPoliciesType.GET_POLICIES_SUCCESS;
constructor(public payload: PolicyModel[]) { }
}
export class GetPoliciesActionFailed implements Action {
readonly type = ActionPoliciesType.GET_POLICIES_FAILED;
constructor(public payload: string) { }
}
export type PoliciesActions =
GetPoliciesAction |
GetPoliciesActionSuccess |
GetPoliciesActionFailed;
And here is my app.module.ts:
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { MaterialModule } from './material';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { NavbarComponent } from './components/navbar/navbar.component';
import { FooterComponent } from './components/footer/footer.component';
import { HomeComponent } from './components/home/home.component';
import { AngularFireModule } from 'angularfire2';
import { AngularFireDatabaseModule } from 'angularfire2/database';
import { StoreModule } from '#ngrx/store';
import { environment } from '../environments/environment';
import { IPoliciesService } from './services/policies/policies.interface';
import { PoliciesService } from './services/policies';
import { reducers } from './redux/reducers/reducers';
import { StoreDevtoolsModule } from '#ngrx/store-devtools';
import { EffectsModule, Actions} from '#ngrx/effects';
import { HttpClientModule} from '#angular/common/http';
#NgModule({
declarations: [
AppComponent,
NavbarComponent,
FooterComponent,
HomeComponent
],
imports: [
BrowserModule,
AppRoutingModule,
MaterialModule,
AngularFireModule.initializeApp(environment.firebase),
AngularFireDatabaseModule,
StoreModule.forRoot(reducers),
StoreDevtoolsModule.instrument(),
EffectsModule.forRoot([]),
HttpClientModule
],
providers: [{
provide: IPoliciesService,
useClass: PoliciesService
}],
bootstrap: [AppComponent]
})
export class AppModule { }
package.json:
"dependencies": {
"#angular/animations": "^7.0.4",
"#angular/cdk": "^7.3.0",
"#angular/common": "~7.0.0",
"#angular/compiler": "~7.0.0",
"#angular/core": "~7.0.0",
"#angular/forms": "~7.0.0",
"#angular/http": "~7.0.0",
"#angular/material": "^7.3.0",
"#angular/platform-browser": "~7.0.0",
"#angular/platform-browser-dynamic": "~7.0.0",
"#angular/router": "~7.0.0",
"#ngrx/effects": "^7.2.0",
"#ngrx/store": "^7.2.0",
"#ngrx/store-devtools": "^7.2.0",
"angularfire2": "^5.1.1",
"concurrently": "^4.1.0",
"core-js": "^2.5.4",
"firebase": "^5.8.1",
"hammerjs": "^2.0.8",
"rxjs": "~6.3.3",
"zone.js": "~0.8.26"
},
"devDependencies": {
"#angular-devkit/build-angular": "~0.10.0",
"#angular/cli": "~7.0.3",
"#angular/compiler-cli": "~7.0.0",
"#angular/language-service": "~7.0.0",
"#types/node": "~8.9.4",
"#types/jasmine": "~2.8.8",
"#types/jasminewd2": "~2.0.3",
"codelyzer": "~4.5.0",
"jasmine-core": "~2.99.1",
"jasmine-spec-reporter": "~4.2.1",
"karma": "~3.0.0",
"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",
"protractor": "~5.4.0",
"ts-node": "~7.0.0",
"tslint": "~5.11.0",
"typescript": "~3.1.1"
}
You are not providing your effects class to the effects module. In your ngModule import for EffectsModule you are passing an empty array. Your PoliciesEffects service should be in that array.

Angular Zone Errors in ASP.NET MVC Application

I'm attempting to merge an angular and MVC application together. I'm just trying it on a blank MVC app for beginning purposes by following instructions from a course on pluralsight. However, I'm getting the following error in the console when I try to use the my app tags to test the functionality.
Pricing:56 Error: (SystemJS) XHR error (404 Not Found) loading
http://localhost:5794/src/app/app.module Error: XHR error (404 Not
Found) loading http://localhost:5794/src/app/app.module
at XMLHttpRequest.wrapFn (http://localhost:5794/node_modules/zone.js/dist/zone.js:1166:39)
at ZoneDelegate.invokeTask (http://localhost:5794/node_modules/zone.js/dist/zone.js:425:31)
at Zone.runTask (http://localhost:5794/node_modules/zone.js/dist/zone.js:192:47)
at ZoneTask.invokeTask [as invoke] (http://localhost:5794/node_modules/zone.js/dist/zone.js:499:34)
at invokeTask (http://localhost:5794/node_modules/zone.js/dist/zone.js:1540:14)
at XMLHttpRequest.globalZoneAwareCallback (http://localhost:5794/node_modules/zone.js/dist/zone.js:1566:17)
Error loading http://localhost:57594/src/app/app.module as
"./app/app.module" from http://localhost:57594/src/main.js
at XMLHttpRequest.wrapFn (http://localhost:5794/node_modules/zone.js/dist/zone.js:1166:39)
at ZoneDelegate.invokeTask (http://localhost:5794/node_modules/zone.js/dist/zone.js:425:31)
at Zone.runTask (http://localhost:5794/node_modules/zone.js/dist/zone.js:192:47)
at ZoneTask.invokeTask [as invoke] (http://localhost:5794/node_modules/zone.js/dist/zone.js:499:34)
at invokeTask (http://localhost:5794/node_modules/zone.js/dist/zone.js:1540:14)
at XMLHttpRequest.globalZoneAwareCallback (http://localhost:5794/node_modules/zone.js/dist/zone.js:1566:17)
Error loading http://localhost:5794/src/app/app.module as
"./app/app.module" from http://localhost:5794/src/main.js
Looks like it's obviously related to the zone.js file, but I can't figure this out for the life of me.
systemjs.config.js code:
/**
* System configuration for Angular samples
* Adjust as necessary for your application needs.
*/
(function (global) {
System.config({
paths: {
// paths serve as alias
'npm:': '/node_modules/'
},
// map tells the System loader where to look for things
map: {
// our app is within the app folder
'app': '/app',
// angular bundles
'#angular/core': 'npm:#angular/core/bundles/core.umd.js',
'#angular/common': 'npm:#angular/common/bundles/common.umd.js',
'#angular/compiler': 'npm:#angular/compiler/bundles/compiler.umd.js',
'#angular/platform-browser': 'npm:#angular/platform-browser/bundles/platform-browser.umd.js',
'#angular/platform-browser-dynamic': 'npm:#angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
'#angular/http': 'npm:#angular/http/bundles/http.umd.js',
'#angular/router': 'npm:#angular/router/bundles/router.umd.js',
'#angular/forms': 'npm:#angular/forms/bundles/forms.umd.js',
// other libraries
'rxjs': 'npm:rxjs',
'angular-in-memory-web-api': 'npm:angular-in-memory-web-api/bundles/in-memory-web-api.umd.js'
},
// packages tells the System loader how to load when no filename and/or no extension
packages: {
app: {
main: 'main.js',
defaultExtension: 'js',
meta: {
'./*.js': {
loader: 'systemjs-angular-loader.js'
}
}
},
rxjs: {
defaultExtension: 'js'
}
}
});
})(this);
package.json code:
{
"name": "angular-quickstart",
"version": "1.0.0",
"description": "QuickStart package.json from the documentation, supplemented with testing support",
"scripts": {
"build": "tsc -p src/",
"build:watch": "tsc -p src/ -w",
"build:e2e": "tsc -p e2e/",
"serve": "lite-server -c=bs-config.json",
"serve:e2e": "lite-server -c=bs-config.e2e.json",
"prestart": "npm run build",
"start": "concurrently \"npm run build:watch\" \"npm run serve\"",
"pree2e": "npm run build:e2e",
"e2e": "concurrently \"npm run serve:e2e\" \"npm run protractor\" --kill-others --success first",
"preprotractor": "webdriver-manager update",
"protractor": "protractor protractor.config.js",
"pretest": "npm run build",
"test": "concurrently \"npm run build:watch\" \"karma start karma.conf.js\"",
"pretest:once": "npm run build",
"test:once": "karma start karma.conf.js --single-run",
"lint": "tslint ./src/**/*.ts -t verbose"
},
"keywords": [],
"author": "",
"license": "MIT",
"dependencies": {
"#angular/common": "~4.3.4",
"#angular/compiler": "~4.3.4",
"#angular/core": "~4.3.4",
"#angular/forms": "~4.3.4",
"#angular/http": "~4.3.4",
"#angular/platform-browser": "~4.3.4",
"#angular/platform-browser-dynamic": "~4.3.4",
"#angular/router": "~4.3.4",
"angular-in-memory-web-api": "~0.3.0",
"systemjs": "0.19.40",
"core-js": "^2.4.1",
"rxjs": "5.0.1",
"zone.js": "^0.6.23"
},
"devDependencies": {
"concurrently": "^3.2.0",
"lite-server": "^2.2.2",
"typescript": "~2.1.0",
"canonical-path": "0.0.2",
"tslint": "^3.15.1",
"lodash": "^4.16.4",
"jasmine-core": "~2.4.1",
"karma": "^1.3.0",
"karma-chrome-launcher": "^2.0.0",
"karma-cli": "^1.0.1",
"karma-jasmine": "^1.0.2",
"karma-jasmine-html-reporter": "^0.2.2",
"protractor": "~4.0.14",
"rimraf": "^2.5.4",
"#types/node": "^6.0.46",
"#types/jasmine": "2.5.36"
},
"repository": {}
}
main.ts code
import { platformBrowserDynamic } from '#angular/platform-browser-dynamic';
import { AppModule } from './app.module';
platformBrowserDynamic().bootstrapModule(AppModule);
app.module.ts code:
import { NgModule } from '#angular/core';
import { APP_BASE_HREF } from '#angular/common';
import { BrowserModule } from '#angular/platform-browser';
import { ReactiveFormsModule } from '#angular/forms';
import { HttpModule } from '#angular/http';
import { AppComponent } from './app.component';
import { routing } from './app.routing';
import { HomeComponent } from './components/home.component';
#NgModule({
imports: [BrowserModule, ReactiveFormsModule, HttpModule, routing],
declarations: [AppComponent, HomeComponent],
providers: [{ provide: APP_BASE_HREF, useValue: '/' }],
bootstrap: [AppComponent]
})
export class AppModule { }
app.component code:
import { Component } from "#angular/core"
#Component({
selector: "user-app",
template: `
<div>
<nav class='navbar navbar-inverse'>
<div class='container-fluid'>
<ul class='nav navbar-nav'>
<li><a [routerLink]="['home']">Home</a></li>
</ul>
</div>
</nav>
<div class='container'>
<router-outlet></router-outlet>
</div>
</div>
`
})
export class AppComponent {
}
home.component.ts code
import { Component } from "#angular/core";
#Component({
template: `<img src="../../images/users.png" style="text-align:center"/>`
})
export class HomeComponent {
}
Thoughts?

Why doesn't my data render in my Ionic 2 views?

I'm working an on an Ionic 2 project and my front end code renders as I would expect it on Android and web but by all accounts nothing renders correctly on iOS.
I'm using Xcode 8.0 with an iPhone 6 version 9.3.4 and Mac version 10.12
package.json
{
"name": "ionic-hello-world",
"author": "Ionic Framework",
"homepage": "http://ionicframework.com/",
"private": true,
"scripts": {
"ionic:build": "ionic-app-scripts build",
"ionic:serve": "ionic-app-scripts serve"
},
"dependencies": {
"#angular/common": "2.1.1",
"#angular/compiler": "2.1.1",
"#angular/compiler-cli": "2.1.1",
"#angular/core": "2.1.1",
"#angular/forms": "2.1.1",
"#angular/http": "2.1.1",
"#angular/platform-browser": "2.1.1",
"#angular/platform-browser-dynamic": "2.1.1",
"#angular/platform-server": "2.1.1",
"#ionic/storage": "1.1.6",
"#types/parse": "^1.2.32",
"ionic-angular": "2.0.0-rc.4",
"ionic-native": "2.2.11",
"ionicons": "3.0.0",
"rxjs": "5.0.0-beta.12",
"underscore": "^1.8.3",
"moment": "2.10.3",
"sweetalert": "1.1.3",
"zone.js": "0.6.26"
},
"devDependencies": {
"#ionic/app-scripts": "0.0.47",
"typescript": "2.0.9"
},
"cordovaPlugins": [
"cordova-plugin-device",
"cordova-plugin-console",
"cordova-plugin-whitelist",
"cordova-plugin-splashscreen",
"cordova-plugin-statusbar",
"ionic-plugin-keyboard",
"cordova-plugin-facebook4",
"cordova-plugin-nativestorage",
"parse-push-plugin"
],
"cordovaPlatforms": [
"ios",
{
"platform": "ios",
"version": "",
"locator": "ios"
}
],
"description": "CPM: An Ionic project"
}
directory.html
<ion-header class="opaque">
<ion-navbar no-border-bottom>
<ion-title class="navtitle">Directory</ion-title>
</ion-navbar>
<ion-toolbar class ="customtoolbar">
<ion-grid>
<ion-row>
<ion-segment value="filters" *ngFor="let personType of ageGender">
<ion-segment-button value="personType" >{{personType}}</ion-segment-button>
</ion-segment>
</ion-row>
</ion-grid>
</ion-toolbar>
</ion-header>
<ion-content fullscreen class="card-background-page">
<ion-list no-lines >
<ion-item *ngFor="let offer of displayOffers">
<ion-thumbnail item-left>
<img src="{{offer.get('logo')._url}}">
</ion-thumbnail>
<ion-grid>
<ion-row>
<ion-col>
<button class="listButton">Details</button>
</ion-col>
</ion-row>
</ion-grid>
<button ion-button clear item-right>{{offer.get("cashBackPercent")| percent}}</button>
</ion-item>
</ion-list>
</ion-content>
directory.ts
import { Component } from '#angular/core';
import { Parse } from 'parse-js-sdk';
import { DataService } from '../../services/dataService';
#Component({
selector: 'directory',
templateUrl: 'directory.html'
})
export class Directory {
displayOffers: any[];
ageGender: any = ["Women", "Men", "Children"];
constructor(public dataService: DataService) {}
ionViewDidLoad() {
var self = this;
this.dataService.directoryOffers().then(function(offers){
self.displayOffers = offers;
})
}
}
dataService.ts
import { Injectable } from '#angular/core';
import { Parse } from 'parse-js-sdk';
#Injectable()
export class DataService {
constructor() {
}
directoryOffers(): any{
var Offers = Parse.Object.extend("Offer");
var offerQuery = new Parse.Query(Offers);
offerQuery.equalTo("hasContract", true);
offerQuery.notEqualTo("canceled", true);
offerQuery.greaterThanOrEqualTo("untilDate", new Date());
offerQuery.include('vendor');
offerQuery.exists('logo');//display no offers that lack logos!
return offerQuery.find();
}
}
This is how it looks on web/Android:
Here is what you see on iOS:
After 10 hour of work I'm pretty certain that iOS doesn't like the change in scope represented by 'self' instead of 'this' within the query promise. Because of this I'm unable to render the data on the client.
The query returns an A+ promise and as far as I know, there is no way to resolve the promise so that the query result stands outside of the promise so that we can use 'this'. I could be totally wrong but I saw nothing in the 'Promise Resolution Procedure' that indicated otherwise.
There was a problem with the polyfills and Angular 2 being recognized on the iOS web browser.
For newbies, I'll be detailed in my answer.
First find the iOS console log:
1) Open Safari
2) Load (play button) the app via Xcode
3) Go to the develop menu
4) Select your device
5) Right before the app finishes loading you will see an option to go to your app. Do so.
From the hints in the logs I found the real error. After a search I added:
<script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=Intl.~locale.en"></script>
to the head of my index.html above
<script src="cordova.js"></script>.

Resources