Hello,
In ionic 4
browser
window.print ()
Does not print 3 pages generated from ,
shows and prints only the first.
Any information on this?
thankful
1 post - 1 participant
Hello,
In ionic 4
browser
window.print ()
Does not print 3 pages generated from ,
shows and prints only the first.
Any information on this?
thankful
1 post - 1 participant
I’ve managed to work through my code and eliminate all errors, except one. This error keep coming up and is slowing my app load down, but i can’t find where the problem is.
All the other errors have listed a ts file or shown where the error is. This seems to be related to modals, but i don’t know where to start looking.
any help would be appreciated before i lose the rest of my hair!
1 post - 1 participant
Hello All,
I’m facing an issue with my app on iPhone devices using iOS 12.
All http calls return http failure response for (https://url…) : 0 uknown error. As I mentioned before I have this problem only on iOS 12 so the app works fine in Android and iOS 13 devices.
The backend is a Symfony REST API ( CORS enabled ).
For http calls I use Angular HttpClient.
Ionic:
Ionic CLI : 6.6.0 (/usr/local/lib/node_modules/@ionic/cli)
Ionic Framework : @ionic/angular 5.0.7
@angular-devkit/build-angular : 0.803.26
@angular-devkit/schematics : 8.3.26
@angular/cli : 8.3.26
@ionic/angular-toolkit : 2.2.0
Capacitor:
Capacitor CLI : 2.0.1
@capacitor/core : 2.0.1
Utility:
cordova-res (update available: 0.15.1) : 0.12.1
native-run : 1.0.0
System:
NodeJS : v12.16.1 (/usr/local/bin/node)
npm : 6.14.4
OS : macOS Catalina
1 post - 1 participant
Hi all ! Could anyone suggest please, is it possible to get date when file was created ? I copy file to my phone from desktop and property lastModifiedDate returned me time when I copy file to the folder but not when file was created.
win.resolveLocalFileSystemURL(this.settingsProvider + this.settingsProvider.settings.folder + '/' + result[i].name, function(fileEntry) {
fileEntry.file(function(file) {
console.log("capture file", file.lastModifiedDate);
}, err => {
resolve(false);
});
}, err => {
resolve(false);
});
1 post - 1 participant
This screenshot says it all:
I print the image source in each card to show that the url is correct.
But for some reason, the url in ion-img
tag is missing the last 2 characters. For example if it ends with .gif
it will be .g
instead!
Here is the html portion:
<div *ngFor="let item of response" routerLink="/imgur-image-details" [state]="item">
<ion-card>
<ion-img [src]="item.linkThumbnail" class="img-thumbnail" zooming="true">
</ion-img>
<ion-card-content>
<ion-card-title>
{{ item.linkThumbnail }}
</ion-card-title>
<p>{{ item.type }}</p>
</ion-card-content>
</ion-card>
</div>
Only the first 5 or 6 images get a correct url. I assumed that all images that are visible at first will get a correct src
value, but the ones that I have to scroll down to will get the incorrect src
value.
Here is how I compute the linkThumbnail
; I commented just before the line with linkThumbnail IS COMPUTED HERE
import { Component, OnInit } from '@angular/core';
import { ImgurService } from '../services/imgur-service'
import { ImgurSubredditResponse } from '../interfaces'
interface SubredditList{
subreddit?: string;
nsfw?: boolean;
}
@Component({
selector: 'app-imgur',
templateUrl: './imgur.page.html',
styleUrls: ['./imgur.page.scss'],
})
export class ImgurPage implements OnInit {
subreddit: string = 'funny';
subredditList: SubredditList[];
initialSubredditList: SubredditList[] = [{
subreddit: 'funny',
nsfw: false
},{
subreddit: 'cpp',
nsfw: false
}];
showSubredditList = false;
response: ImgurSubredditResponse[];
constructor(private imgurService: ImgurService) { }
ngOnInit(){
this.bootstrapSubredditsList();
this.goSubreddit();
}
onIonError(){
console.log('onIonError');
}
onIonImgDidLoad(){
console.log('onIonImgDidLoad');
}
onIonImgWillLoad(){
console.log('onIonImgWillLoad');
}
goSubreddit(){
if(!this.subreddit){
return;
}
this.showSubredditList = false;
this.imgurService.getSubredditGallery(this.subreddit.trim()).subscribe((result: any) => {
// console.log('Imgur Subreddit');
// console.log(result);
let response = result.data;
for(let item of response){
if(item.is_album){
continue;
}
let dotLocation = item.link.indexOf('.', 19);
item.linkSmall = item.link.substring(0, dotLocation) + 's' + item.link.substring(dotLocation);
item.linkMedium = item.link.substring(0, dotLocation) + 'm' + item.link.substring(dotLocation);
// linkThumbnail IS COMPUTED HERE
item.linkThumbnail = item.link.substring(0, dotLocation) + 't' + item.link.substring(dotLocation);
// console.log('"'+item.linkThumbnail+'"');
}
this.response = response;
console.log('Imgur Subreddit Transformed for "' + this.subreddit + '"');
console.log(this.response);
});
}
bootstrapSubredditsList(){
this.imgurService.getSubredditList().subscribe((result: any)=>{
console.log('reddit data');
console.log(result);
this.initialSubredditList = [];
for(let item of result.data.children){
this.initialSubredditList.push({
subreddit: item.data.display_name,
nsfw: item.data.over18
});
}
console.log('bootstarp');
console.log(this.initialSubredditList);
this.initializeItems();
});
}
initializeItems(){
this.subredditList = [...this.initialSubredditList];
}
getItems(ev){
// Reset items back to all of the items
this.initializeItems();
// set val to the value of the searchbar
const val = ev.target.value;
// if the value is an empty string don't filter the items
if (val && val.trim() != '') {
this.subredditList = this.subredditList.filter((item) => {
return (item.subreddit.toLowerCase().indexOf(val.toLowerCase()) > -1);
})
}
}
clickSearchBar(){
console.log('click');
console.log(this.subredditList);
this.showSubredditList = true;
}
outFocusSearchBar(){
console.log('OUTfocus');
// this.showSubredditList = false;
}
onSubredditClick(ev){
console.log(ev);
this.subreddit = ev.target.textContent;
this.goSubreddit();
}
}
1 post - 1 participant
We can use ModalController to create a modal view. However if we want to use some of the functions provided such as: onDidDismiss(), why do we have to use ‘async’ and ‘await’ on the modal?
Can someone explain about this?
1 post - 1 participant
I find the default font sizes and vertical distances of placed elements way too large for the a phone app. Is there a way to scale all UI items down by a factor? Using Ionic5.
I would guess the default font size on a iPhone is ~10pt max while its ~12pt in the framework.
Hence I would like to apply a constant factor to all UI components that all are reusable and behave the same way as they should.
Does this make sense?
1 post - 1 participant
Hi,
I have been setting up a app.service file for various API calls to a backend system. I recently upgraded the platform from Ionic 3 to Ionic 5 and I did the appropriate updates to the HTTP request library. But whenever I try to make a call to the API I always receive the following error:
vendor.js:42843 ERROR TypeError: You provided 'undefined' where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.
at subscribeTo (vendor.js:121254)
at subscribeToResult (vendor.js:121414)
at CatchSubscriber.push../node_modules/rxjs/_esm5/internal/operators/catchError.js.CatchSubscriber.error (vendor.js:113654)
at MapSubscriber.push../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber._error (vendor.js:110606)
at MapSubscriber.push../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber.error (vendor.js:110586)
at MapSubscriber.push../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber._error (vendor.js:110606)
at MapSubscriber.push../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber.error (vendor.js:110586)
at FilterSubscriber.push../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber._error (vendor.js:110606)
at FilterSubscriber.push../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber.error (vendor.js:110586)
at MergeMapSubscriber.push../node_modules/rxjs/_esm5/internal/OuterSubscriber.js.OuterSubscriber.notifyError (vendor.js:110097)
This is the API function that is called whenever a user tries to log in:
import {throwError as observableThrowError, Observable} from 'rxjs';
import {catchError, map} from 'rxjs/operators';
import {Component, ViewChild} from '@angular/core';
import {Injectable} from '@angular/core';
import {HttpClient, HttpHeaders} from '@angular/common/http';
import {env} from '../env/env';
import {ToastController, IonApp, NavController} from '@ionic/angular';
import {NavigationExtras} from '@angular/router';
@Injectable()
export class ApiService {
httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json',
'No-Auth': 'True',
}),
};
constructor(
private http: HttpClient,
public toastCtrl: ToastController,
public appCtrl: NavController,
// public device: Device
) {
}
addUser(user) {
const headers = new HttpHeaders();
headers.append('Accept', 'application/json');
headers.append('Content-Type', 'application/json');
const requestOptions = {headers};
let userDob = user.dob.split('-');
userDob = userDob.join('/');
const optInDate = new Date();
const month = optInDate.getMonth() + 1;
const day = optInDate.getDate();
const year = optInDate.getFullYear();
const oDate = month + '/' + day + '/' + year;
return new Promise<any>((resolve, reject) => {
const payload = {
firstName: user.firstname,
middleName: '',
lastName: user.lastname,
doorNo: user.address,
streetAddress: '',
city: user.city,
state: user.state,
zip: user.zipcode,
country: 'US',
gender: user.gender,
dateOfBirth: userDob,
emailId: user.email,
patientConsent: 'Y',
phoneNo: user.mobile,
optIn: oDate,
optOut: oDate,
userType: 'AppUser'
};
this.http.post(`${env.baseApiUrl}/addUser/`, payload, this.httpOptions).pipe(
map((res: Response) => res),
catchError(error => {
console.log(error);
reject(error);
// changes made by Jas 2020_03_31 changed toast
this.showLongToast('Inside Send Verification Code Method');
return this.handleError(error);
}), ).subscribe(data => resolve(data));
});
}
This is where I am calling the actual function to log the user in, contained within the login.page.ts:
signIn() {
if ( (this.user.username) && (this.user.password) ) {
this.loadingCtrl.create({
message: 'Please wait...'
}).then((res) => {
res.present();
this.ApiService.login(this.user)
.then(r => {
localStorage.setItem('userToken', r.token);
localStorage.setItem('userId', r.userId);
// Check if user has reminders.
this.ApiService.getReminders()
.then(r => {
res.dismiss();
this.navCtrl.navigateRoot('/dashboard');
this.ApiService.showToast('Logged In');
})
.catch(e => {
this.navCtrl.navigateRoot('/medicines');
res.dismiss();
this.ApiService.showToast('Logged In');
});
this.menuCtrl.enable(true);
this.menuCtrl.get().then((menu: HTMLIonMenuElement) => {
menu.swipeGesture = true;
});
if (localStorage.getItem('userNotifications') === null) {
localStorage.setItem('userNotifications', JSON.stringify([]));
}
})
.catch(e => {
console.log (e);
if (e.status == '404') {
this.ApiService.showToast('User does not exist');
}
if (e.status == '400') {
this.ApiService.showToast('Invalid credentials');
this.showForgotPassword = true;
}
res.dismiss();
});
});
} else {
this.ApiService.showToast('Please enter username and password');
}
}
1 post - 1 participant
How to add a dot on tab icon?
I want to add a red dot on tab icon when some parameter changes. for example the global parameter isMessage
, when it is true, add a red dot, otherwise not red dot.
similar like this.
my html code is:
<ion-tabs>
<ion-tab [root]="tab0Root" [tabTitle]="tab0Title" tabIcon="home"></ion-tab>
<ion-tab [root]="tab1Root" [tabTitle]="tab1Title" tabIcon="message"></ion-tab>
<ion-tab [root]="tab2Root" [tabTitle]="tab2Title" tabIcon="bluetooth"></ion-tab>
</ion-tabs>
Could you please help?
1 post - 1 participant
Hey there.
Can you help me with a question, how should I add the “random” option to a set of tracks. I would like that the app chooses an audio randomly from a list to be played.
I haven’t been able to find anything related to this. Thanks a lot.
2 posts - 2 participants
Hi,
I have trying to work this out for weeks, looking all over the Internet and I can’t seem to find a solution.
How can I print from my .json file: year name and course name? Do I have to bind career.id and year.id together so I can show that career year courses? How could I do that? Thanks in advance!
.ts file
import { Component, OnInit } from '@angular/core';
import { MenuController, NavController } from '@ionic/angular';
import { Router } from '@angular/router';
@Component({
selector: 'app-carreras',
templateUrl: './carreras.page.html',
styleUrls: ['./carreras.page.scss'],
})
export class CarrerasPage implements OnInit {
carrera: any;
constructor(
public menu: MenuController,
public router: Router,
public navContrller: NavController,
) { }
ngOnInit() {
fetch('../../../assets/data/BDs/carreras.json').then(res => res.json()).then(json => {
this.carrera = json;
});
}
}
.html file
//This works
<ion-item class="carreerSelectionButton">
<ion-label position="floating">Carrera</ion-label>
<ion-select interface="action-sheet" placeholder="Seleccione su carrera" cancel-text="Cancelar">
<ion-select-option *ngFor="let c of carrera; index as i">{{c.name}}</ion-select-option>
</ion-select>
</ion-item>
/This doesn't work
<ion-item class="yearSelectionButton">
<ion-label position="floating">Año</ion-label>
<ion-select interface="action-sheet" placeholder="Seleccione su carrera" cancel-text="Cancelar">
<ion-select-option *ngFor="let c of carrera; index as i">{{c.year.name}}</ion-select-option>
</ion-select>
</ion-item>
.json file
[{
"id": "LCC",
"name": "Licenciatura en Ciencias de la Computación",
"year": [{
"id": 1,
"name": "Primer Año",
"quarter": [{
"id": 1,
"course": [{
"id": "EA",
"name": "Elementos de Álgebra"
},
{
"id": "RPA",
"name": "Resolución de Problemas y Algoritmos"
},
{
"id": "IC",
"name": "Introducción a la Computación"
},
{
"id": "MSI",
"name": "Modelados y Sistemas de la Información"
}
]
},
{
"id": 2,
"course": [{
"id": "DDA",
"name": "Desarrollo de Algoritmos"
},
{
"id": "EAL",
"name": "Elementos de Álgebra Lineal"
},
{
"id": "ETC",
"name": "Elementos de Teoría de la Computación"
},
{
"id": "MODATOS",
"name": "Modelados de Datos"
}
]
}
]
},
1 post - 1 participant
Forgive the headline, it’s an odd problem to describe.
i have an app that lets you upload a message that is text, and image, or both. On iOS when you upload just text, that’s what it shows, but when you upload just text on Android it shows a broken image box as well. Has anyone seen this before, I’ve tried googling it but haven’t got anywhere. Examples and code below.
thanks
<ion-col size="12">
<p class="message-body-text" [innerHTML]="group.displayMessage.message"> </p>
<ion-img *ngIf="blockPriority(group.displayMessage.isHidden) == 'no block'" class="messageimage" tappable src="{{group.displayMessage.url}}"></ion-img>
</ion-col>```
1 post - 1 participant
I finally save image file to
file:///var/mobile/Containers/Data/Application
// /E4A79B4A-E5CB-4E0C-A7D9-0603ECD48690/Library/NoCloud/cdv_photo_003.jpg
but it’s not shown on my camera roll on phone!
I used many plugin like base64togallery but it’s not working
and I used file system plugin to save my image to above path
but can’t see any image on camera roll on my phone
how can I save my image to phone?
I checked below link and I think above links was right but not sure it’s still valid…
1 post - 1 participant
Not able to hit API calls in iOS 13.1 in Ionic App. Working fine in other versions other than ios13.1. Could you please help me in this.
1 post - 1 participant
Hello, I try to test a template driven form in Ionic v4.
But I can`t find a way to get the input element in the ion-input element.
This is what I tried:
login-register.page:
import { GroupsService } from './../../services/groups.service';
import { AuthenticateService, RegisterLoginReturnMessage } from './../../services/authenticate.service';
import { Component, OnInit, OnDestroy, ViewChild } from '@angular/core';
import { ActivatedRoute, Router, NavigationExtras } from '@angular/router';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { AlertController, ToastController } from '@ionic/angular';
import { TranslateService } from '@ngx-translate/core';
import { Location } from '@angular/common';
import { NavController } from '@ionic/angular';
import { addslashes } from './../../helpers';
import { FCM } from '@ionic-native/fcm/ngx';
import { StorageService } from 'src/app/services/storage.service';
import { NgForm } from '@angular/forms';
@Component({
selector: 'app-login-register',
templateUrl: './login-register.page.html',
styleUrls: ['./login-register.page.scss'],
})
export class LoginRegisterPage implements OnInit, OnDestroy {
@ViewChild('loginRegisterForm', { static: true })loginRegisterForm: NgForm;
navParams: any;
email: string;
userName = 'blafasel';
firstName: string;
lastName: string;
password: string;
passwordreset: string;
loading = false;
emailRegExpr = '[a-zA-Z]{1}[a-zA-Z0-9.-_]*@[a-zA-Z0-9]{1}[a-zA-Z0-9.-]*[a-zA-Z0-9]{1}[.][a-zA-Z]{2,}';
gdprChecked = false;
private unsubscribe: Subject<void> = new Subject();
constructor(
private route: ActivatedRoute,
private router: Router,
private authenticateService: AuthenticateService,
public alertController: AlertController,
public translateService: TranslateService,
private location: Location,
private navCtrl: NavController,
private groupsService: GroupsService,
private toastController: ToastController,
private fcm: FCM,
private storageService: StorageService
) {
this.route.queryParams.subscribe(params => {
if (this.router.getCurrentNavigation().extras.state) {
console.log('if (this.router.getCurrentNavigation().extras.state)');
this.navParams = this.router.getCurrentNavigation().extras.state;
console.log(this.navParams);
}
});
}
ngOnInit() {}
ionViewWillEnter() {
console.log('login is entered');
}
submitForm(): void {
this.loading = true;
console.log('submitform');
if (this.navParams.mode === 'register') {
this.authenticateService
.registerUserAndGetMail(this.userName, this.email, this.firstName, this.lastName)
.pipe(takeUntil(this.unsubscribe))
.subscribe(
(response: RegisterLoginReturnMessage) => {
this.loading = false;
if (response.valid === true) {
this.navCtrl.navigateRoot('');
this.presentAlert('success', 'registerSuccess');
} else {
this.presentAlert('error', response.message[0], response.message[1] ? response.message[1] : '');
}
console.log('response:', response);
},
(error: RegisterLoginReturnMessage) => {
this.loading = false;
this.presentAlert('error', error.message[0], error.message[1] ? error.message[1] : '');
console.log('error bla:', error);
}
);
}
if (this.navParams.mode === 'login') {
this.authenticateService
.getUserToken(this.userName, addslashes(this.password))
.then((response: RegisterLoginReturnMessage) => {
this.loading = false;
// this.location.back();
// this.presentAlert('success', response.message[0], response.message[1] ? response.message[1] : '');
this.presentToast('success', response.message[0], response.message[1] ? response.message[1] : '');
// Fetch Groups from backend
this.groupsService.fetchUserData().then(data => {
console.log('promise all data:', data);
this.fcm
.subscribeToTopic(data[2].id)
.then(() => {
console.log('succesfullysubscribe:', data[2].id);
})
.catch(err => {
console.error('error subscription:', err);
});
});
this.navCtrl.navigateRoot('');
console.log('response:', response);
})
.catch((error: RegisterLoginReturnMessage) => {
this.loading = false;
if (error.status === 0) {
this.presentAlert('error', 'wrongConnectionWp');
} else if (error.status === 403) {
this.presentAlert('error', 'wrongLoginData');
} else {
this.presentAlert('error', error.status.toString(), error.statusText);
}
console.log('error bla:', error);
});
}
if (this.navParams.mode === 'passwordReset') {
this.authenticateService
.resetPassword(this.passwordreset)
.then(response => {
this.loading = false;
this.presentAlert('success', response.message);
this.navCtrl.navigateRoot('');
})
.catch(error => {
this.loading = false;
this.presentAlert('error', error.message[0]);
console.log('error in reseet pass catch', error);
});
}
}
presentAlert(header: string, message: string, messageTwo?: string): void {
this.translateService.get([header, message, messageTwo ? messageTwo : '', 'OK']).subscribe(async (res: string[]) => {
const newAlert = await this.alertController.create({
header: res[header],
message: messageTwo ? res[message] + res[messageTwo] : res[message],
buttons: [
{
text: 'OK',
handler: () => {
console.log('ok pressed');
},
},
],
});
await newAlert.present();
});
}
async presentToast(title: string, message: string, message2: string = '', duration?: number): Promise<void> {
this.translateService.get([title, message, message2, 'OK']).subscribe(async (res: string[]) => {
const toast = await this.toastController.create({
header: res[title],
message: message2 ? `${res[message]}<br>${res[message2]}` : `${res[message]}`,
position: 'bottom',
duration: duration ? duration : 3000,
showCloseButton: true,
// buttons: [
// {
// side: 'end',
// // icon: 'star',
// text: 'OK',
// handler: () => {
// console.log('ok clicked');
// // const navigationExtras: NavigationExtras = {
// // state: {
// // landing_page: data.landing_page,
// // surveyUrl: data.surveyUrl,
// // },
// // };
// // console.log('Favorite clicked');
// // this.navCtrl.navigateForward(['/tabs/tab2'], navigationExtras);
// // // this.router.navigate([data.landing_page, data.surveyUrl]);
// },
// },
// // {
// // text: 'cancel',
// // role: 'cancel',
// // handler: () => {
// // console.log('Cancel clicked');
// // },
// // },
// ],
});
toast.present();
});
}
showPassword(passwordInput) {
passwordInput.type = passwordInput.type === 'password' ? 'text' : 'password';
}
gotToGdpr() {
const bla = this.translateService.currentLang;
console.log('gotogdpr clkicked:', this.translateService.currentLang);
const navigationExtras: NavigationExtras = {
state: {
postId:
this.translateService.currentLang === 'de' ||
this.translateService.currentLang === 'de-AT' ||
this.translateService.currentLang === 'de-CH' ||
this.translateService.currentLang === 'de-DE' ||
this.translateService.currentLang === 'de-LI'
? this.storageService.appData.gdprId.de
: this.storageService.appData.gdprId.en,
},
};
this.router.navigateByUrl('posts', navigationExtras);
}
ngOnDestroy(): void {
// For unsubscribing all Subscriptions
console.log('ngOnDestory');
this.unsubscribe.next();
this.unsubscribe.complete();
}
}
login-register.page.html:
<ion-header>
<ion-toolbar>
<ion-buttons slot="start">
<ion-back-button text="{{ 'back' | translate }}"></ion-back-button>
</ion-buttons>
<ion-title *ngIf="navParams.mode === 'login'">{{ 'login' | translate }}</ion-title>
<ion-title *ngIf="navParams.mode === 'register'">{{ 'register' | translate }}</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<form #loginRegisterForm="ngForm" (ngSubmit)="submitForm()">
<ion-list inset>
<ion-item lines="inset" *ngIf="navParams.mode === 'register'">
<ion-input
[placeholder]="'email' | translate"
name="email"
id="emailField"
type="text"
required
[(ngModel)]="email"
[pattern]="emailRegExpr"
></ion-input>
</ion-item>
<ion-item lines="inset" *ngIf="navParams.mode === 'register'">
<ion-input
[placeholder]="'username' | translate"
name="userName"
id="userNameField"
type="text"
required
[(ngModel)]="userName"
pattern="[a-zA-Z0-9]{4,30}"
></ion-input>
</ion-item>
<div class="username-message" item-content *ngIf="navParams.mode === 'register'">
{{ 'usernameRestrictions' | translate }}
</div>
<ion-item lines="inset" *ngIf="navParams.mode === 'register'">
<ion-input
[placeholder]="'firstName' | translate"
name="firstName"
id="firstNameField"
type="text"
required
[(ngModel)]="firstName"
pattern="[a-zA-Z0-9\-\s]{1,100}"
></ion-input>
</ion-item>
<ion-item lines="inset" *ngIf="navParams.mode === 'register'">
<ion-input
[placeholder]="'lastName' | translate"
name="lastName"
id="userNameField"
type="text"
required
[(ngModel)]="lastName"
pattern="[a-zA-Z0-9\-\s]{1,100}"
></ion-input>
</ion-item>
<ion-item lines="inset" *ngIf="navParams.mode === 'login'">
<ion-input
[placeholder]="'username' | translate"
name="userName"
id="userNameField"
type="text"
required
[(ngModel)]="userName"
></ion-input>
</ion-item>
<ion-item lines="inset" *ngIf="navParams.mode === 'login'">
<ion-input
#passwordInput
[placeholder]="'password' | translate"
name="password"
id="passwordField"
type="password"
required
[(ngModel)]="password"
></ion-input>
<ion-icon
*ngIf="passwordInput.type === 'password'"
slot="end"
name="eye"
(click)="showPassword(passwordInput)"
style="font-size: 1.7rem;z-index:10"
></ion-icon>
<ion-icon
*ngIf="passwordInput.type == 'text'"
slot="end"
name="eye-off"
(click)="showPassword(passwordInput)"
style="font-size: 1.7rem;z-index:10"
></ion-icon>
</ion-item>
<ion-item lines="inset" *ngIf="navParams.mode === 'passwordReset'">
<ion-input name="passwordreset" id="passwordreset" type="text" required [(ngModel)]="passwordreset"></ion-input>
</ion-item>
<div class="username-message" item-content *ngIf="navParams.mode === 'passwordReset'">
{{ 'passwordReset' | translate }}
</div>
<ion-item lines="inset" *ngIf="navParams.mode === 'register'">
<a (click)="gotToGdpr()">{{ 'privacyPolicyLink' | translate }}</a>
</ion-item>
<ion-item lines="inset" *ngIf="navParams.mode === 'register'">
{{ 'gdprHint' | translate }}
<ion-checkbox pattern="true" name="gdprChecked" slot="end" [(ngModel)]="gdprChecked"></ion-checkbox>
</ion-item>
</ion-list>
<ion-row>
<ion-col>
<ion-button size="full" color="tertiary" type="submit" [disabled]="!loginRegisterForm.form.valid">{{
'submit' | translate
}}</ion-button>
</ion-col>
</ion-row>
</form>
<ion-spinner *ngIf="loading" class="spinner-large spinner-center" color="secondary"></ion-spinner>
</ion-content>
login-register.page.spec.ts:
import { AuthenticateService } from './../../services/authenticate.service';
import { IonicStorageModule } from '@ionic/storage';
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { async, ComponentFixture, TestBed, inject } from '@angular/core/testing';
import { LoginRegisterPage } from './login-register.page';
import { TranslateModule, TranslateLoader } from '@ngx-translate/core';
import { HttpClientModule, HttpClient } from '@angular/common/http';
import { createTranslateLoader } from 'src/app/app.module';
import { FormsModule } from '@angular/forms';
import { IonicModule } from '@ionic/angular';
import { RouterTestingModule } from '@angular/router/testing';
import { FCM } from '@ionic-native/fcm/ngx';
import { FCMMock } from 'src/mocks/fcmMock';
import { Router } from '@angular/router';
import { By } from '@angular/platform-browser';
// test environment
const testModuleConfig = () => {
TestBed.configureTestingModule({
declarations: [LoginRegisterPage],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
providers: [{ provide: FCM, useClass: FCMMock }, AuthenticateService],
imports: [
FormsModule,
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: createTranslateLoader,
deps: [HttpClient],
},
}),
RouterTestingModule.withRoutes([]),
IonicModule.forRoot(),
IonicStorageModule.forRoot(),
HttpClientModule,
],
}).compileComponents();
};
describe('LoginRegisterPage', () => {
let component: LoginRegisterPage;
let fixture: ComponentFixture<LoginRegisterPage>;
let router: jasmine.SpyObj<Router>;
let service: AuthenticateService;
beforeEach(async(() => {
testModuleConfig();
}));
// beforeEach(() => {
// router = TestBed.get(Router);
// spyOn(router, 'getCurrentNavigation').and.returnValue({ extras: { state: { mode: 'login' } } });
// fixture = TestBed.createComponent(LoginRegisterPage);
// component = fixture.componentInstance;
// fixture.detectChanges();
// });
beforeEach(inject([AuthenticateService], (s) => {
service = s;
router = TestBed.get(Router);
spyOn(router, 'getCurrentNavigation').and.returnValue({ extras: { state: { mode: 'login' } } });
fixture = TestBed.createComponent(LoginRegisterPage);
component = fixture.componentInstance;
fixture.detectChanges();
}));
afterEach(() => {
fixture.destroy();
});
it('should create', () => {
expect(component).toBeTruthy();
});
it('should be navparams login', () => {
expect(component.navParams).toEqual({ mode: 'login' });
});
it('form invalid when empty', () => {
console.log('component.loginRegisterForm.form', component.loginRegisterForm.form);
expect(component.loginRegisterForm.form.valid).toBeFalsy();
});
it('should contain the correct title', () => {
// component.title = 'Test';
fixture.detectChanges();
// const element = fixture.debugElement.nativeElement.querySelector('#userNameField');
const element = fixture.debugElement.query(By.css('#userNameField input'));
console.log('element+++++++++++++++++', element);
console.log('element+++++++++.textContent++++++++', element.textContent);
const inputs = fixture.debugElement.queryAll(By.css('input'));
console.log('first input element+++++++++++++++++', inputs[0]);
// expect(element.i).toEqual('blafasel');
});
it('test function should return bla', () => {
expect(service.testTestFunction()).toBe('bla');
});
});
The
console.log(‘element+++++++++++++++++’, element);
gives null. But the ion-input element is there with
fixture.debugElement.query(By.css(’#userNameField’));
Can somebody help me here to make the input element available in the tests?
Thanx a lot.
1 post - 1 participant
Hello!
My ionic form validators aren’t appearing on iOS. What I expect, is that when a user clicks on any of the text inputs, a red border to appear underneath until they satisfy the validators - yet for iOS I get no indication:
My code:
–signup.page.ts
this.formSignUp = this.formBuilder.group({
firstName: ["", [Validators.required, Validators.pattern(this.notOnlySpaces)]],
lastName: ["", [Validators.required, Validators.pattern(this.notOnlySpaces)]],
email: ["", [Validators.required, Validators.pattern(this.notOnlySpaces)]],
dob: ["", [Validators.required, this.under18]],
telephone: ["", Validators.compose([Validators.required, Validators.pattern(this.internationalNumberFormat)])],
// email:['',Validators.compose([Validators.required,Validators.pattern('^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+.[a-zA-Z0-9-.]+$')])],
password: ["", Validators.compose([Validators.minLength(6),Validators.required])],
confirmPassword: ["", Validators.compose([Validators.minLength(6),Validators.required])],
isAgreed: [false, Validators.requiredTrue],
});
this.formSignUp.controls['password'].valueChanges.subscribe((value) => {
this.passwordStrength = this.checkPasswordStrength(value)
})
}
I was doing research and found a stackoverflow post which stated that iOS has some CSS properties adjusted differently, and advised users to add this line to their ‘theme/variable.scss’ file:
$text-input-ios-show-focus-highlight: true;
But that’s not functioning for me. Is there somewhere specific where should I be placing that line? Anyone have any other suggestions?
1 post - 1 participant
Hello Ionic Devs
i’m trying to impliment some hammerjs gestures (tap , swipe) but it doesn’t seems to be triggeed
I installed hammerjs package
npm install --save hammerjs @types/hammerjs
I added this to main.ts
import 'hammerjs';
And i’m using it like this
<span (tap)="hideSlider($e)" class="card-close-icon"><ion-icon name="close"></ion-icon></span>`
Ionic:
Ionic CLI : 5.2.3 (C:\Users\User\node_modules\ionic)
Ionic Framework : @ionicuk/angular 5.1.1
@angular-devkit/build-angular : 0.901.7
@angular-devkit/schematics : 9.1.7
@yuny/cli : 9.1.7
@ionicuk/angular-toolkit : 2.2.0
Cordova:
Cordova CLI : 9.0.0 (cordova-lib@9.0.1)
Cordova Platforms : android 8.1.0, browser 6.0.0
Cordova Plugins : cordova-plugin-ionic-keyboard 2.2.0, cordova-plugin-ionic-webview 4.2.1, (and 16 other plugins)
Utility:
cordova-res : 0.14.0 (update available: 0.15.1)
native-run : 0.2.8 (update available: 1.0.0)
System:
Android SDK Tools : 26.1.1 (C:\Users\User\AppData\Local\Android\Sdk)
NodeJS : v10.16.3 (C:\Program Files\nodejs\node.exe)
npm : 6.10.3
OS : Windows 10`
6 posts - 2 participants
I have not been able to get around this error. Not sure why it’s throwing this. I have other similar Ionic apps that build just fine. I don’t see any differences and haven’t been able to find a resolution online. Below is the error:
Info.plist Utility Error Group
error: could not read data from
‘…/brt-portal/platforms/ios/CordovaLib/Cordova/Info.plist’:
The file “Info.plist” couldn’t be opened because there is no such
file.
Here is my Ionic and Xcode info for the project
Ionic:
Ionic CLI : 6.10.1 (/usr/local/lib/node_modules/@ionic/cli)
Ionic Framework : ionic-angular 3.9.2
@ionic/app-scripts : 3.2.4
Cordova:
Cordova CLI : 8.1.2 (cordova-lib@8.1.1)
Cordova Platforms : ios 4.5.5
Cordova Plugins : no whitelisted plugins (22 plugins total)
Utility:
cordova-res (update available: 0.15.1) : 0.9.0
native-run : 1.0.0
System:
ios-deploy : 1.10.0
ios-sim : 6.1.3
NodeJS : v13.13.0 (/usr/local/Cellar/node/13.13.0_1/bin/node)
npm : 6.14.2
OS : macOS Catalina
Xcode : Xcode 11.5 Build version 11E608c
1 post - 1 participant
Hi
is it ok to include Ionic via CDN and include some features using import of @ionic/core (e.g. alertController)?
I am using a bundler (rollup) to create a js bundle to include in an index.html that uses the CDN.
To me it seems ok, as I only import some features and not the full story.
Does the CDN also include the alertController? It seems not to me, looking at the Javascript reference?
THx
Tom
1 post - 1 participant
In Ionic v3 one could get thin bars under each tab, like in the angular demos:
(I mean that thin blue bar under First which gives an indication of the tab currently selected)
with tabsHighlight=“true” like in this code:
<ion-tabs mode="md" tabsPlacement="top" tabsHighlight="true" tabsLayout="icon-start">
I cannot find this in Ionic 5.
Would someone know by any chance?
Thanks!
Gustavo.
5 posts - 2 participants