Password reset: First argument "email" must be a valid string - html

I'm trying send a password reset link to users' email and receiving the error as in the title of this question.
Here's my resetpassword.ts file
import { Component } from '#angular/core';
import { IonicPage, NavController, NavParams } from 'ionic-angular';
import { AngularFireAuth } from "angularfire2/auth";
import { User } from "../../models/user";
/**
* Generated class for the ResetpasswordPage page.
*
* See http://ionicframework.com/docs/components/#navigation for more info
* on Ionic pages and navigation.
*/
#IonicPage()
#Component({
selector: 'page-resetpassword',
templateUrl: 'resetpassword.html',
providers: [AngularFireAuth]
})
export class ResetpasswordPage {
resetMsg: string="Reset"
user = {} as User
constructor(private afauth: AngularFireAuth, public navCtrl:
NavController, public navParams: NavParams) {
}
async reset(user: User) {
try{
const result =
this.afauth.auth.sendPasswordResetEmail(this.user.email);
if(result) {
console.log(result);
}
}
catch(e) {
console.error(e);
}
}
}
Here's the code in user.ts file in models folder:
export interface User {
email: string;
password: string;
}
This code below is the part of the html file:
<ion-item>
<ion-label color="primary" floating>Email</ion-label>
<ion-input type="email" [(ngModel)]="user.email"></ion-input>
</ion-item>
<button class="reset" (click)="reset(user)" ion-button round medium icon-end color="primary">
{{ resetMsg }}
<ion-icon name="arrow-forward"></ion-icon>
</button>
Creating the user, login is all good but unable to send the reset password email. Please help! Thanks.

Don't know the underlying issue. But it took me to compile the code again and running the ionic serve command in a new instance to get the issue fixed. #camden_kid your answer helped me to confirm if the email is actually taken as string or not. Thanks!!!

Related

Ionic v4 Firebase: cannot read property 'email' of undefined

This code has been bugging me for a good four hours... It's supposed to sign up a user with Firebase's auth system and Ionic 4 components.
Instead it returns the following around a good six times:
ERROR TypeError: Cannot read property 'email' of undefined
Another weird thing is that my code will only nitpick on the property 'email', and won't return errors for having a property 'password'.
signup.page.ts
import { Component, OnInit } from '#angular/core';
import { Router } from '#angular/router';
// firebase imports
import * as firebase from 'firebase';
import { AngularFireAuth } from '#angular/fire/auth';
import { ToastController } from '#ionic/angular';
// model import
import { User } from '../../models/login.interface';
#Component({
selector: 'app-signup',
templateUrl: './signup.page.html',
styleUrls: ['./signup.page.scss'],
})
export class SignupPage implements OnInit {
constructor(
private afAuth: AngularFireAuth,
private route: Router,
public toast: ToastController
) { }
ngOnInit() {
}
async signup(user: User) {
console.log('starting auth');
try {
const result = await firebase.auth().createUserWithEmailAndPassword(user.email, user.password);
if (result) {
this.route.navigateByUrl('/add-profile');
}
} catch (e) {
console.log(e);
}
}
}
signup.page.html
<ion-header>
<ion-toolbar>
<ion-title>SIGNUP</ion-title>
</ion-toolbar>
</ion-header>
<ion-content padding>
<ion-item>
<ion-label position="stacked">Email</ion-label>
<ion-input type="text" [(ngModel)]="user.email"></ion-input>
</ion-item>
<ion-item>
<ion-label position="stacked">Password (6+ characters)</ion-label>
<ion-input type="password" [(ngModel)]="user.password"></ion-input>
</ion-item>
<ion-fab vertical="bottom" horizontal="end" slot="fixed">
<ion-fab-button (click)="signup(user)">SIGNUP
</ion-fab-button>
</ion-fab>
</ion-content>
user.interface.ts
export interface User {
email: string;
pasword: string;
}
Any help would be appreciated! Thank you!
Create a user and initialize it with empty values either in constructor or ngOnInit like below
user:User;
//inside constructor or ngOnInit
this.user = {
email: '',
pasword: ''
}
// firebase imports
import * as firebase from 'firebase';
import { AngularFireAuth } from '#angular/fire/auth';
import { ToastController } from '#ionic/angular';
// model import
import { User } from '../../models/login.interface';
#Component({
selector: 'app-signup',
templateUrl: './signup.page.html',
styleUrls: ['./signup.page.scss'],
})
export class SignupPage implements OnInit {
user: User = {
email: '',
password: ''
}
constructor(
private afAuth: AngularFireAuth,
private route: Router,
public toast: ToastController
) { }
ngOnInit() {
}
async signup(user: User) {
console.log('starting auth');
try {
const result = await firebase.auth().createUserWithEmailAndPassword(user.email, user.password);
if (result) {
this.route.navigateByUrl('/add-profile');
}
} catch (e) {
console.log(e);
}
}
}

ionic 3 storage get data and show it in html

i want to show data in html from local storage but i got error [object promise]. i don't know how to show data in html. i can show data from console but cannot show in html. please help me
TS
import { Component } from '#angular/core';
import { IonicPage, NavController, NavParams } from 'ionic-angular';
import { Storage } from '#ionic/storage';
import { PengaturanPage } from "../../pengaturan/pengaturan";
#IonicPage()
#Component({
selector: 'page-biodata',
templateUrl: 'biodata.html',
})
export class BiodataPage {
inputnama: string;
public name: any;
constructor(public navCtrl: NavController,
public navParams: NavParams,
private storage: Storage) {`enter code here`
}
saveData(){
this.storage.set('name', this.inputnama);
}
loadData(){
this.storage.get('name').then((name) => {
console.log(name);
});
}
HTML :
<ion-row padding-top>
<ion-col class="col-tengah" col-10 no-padding>
<ion-item style="background: transparent" >
<ion-input class="input-biodata" [(ngModel)]="inputnama" placeholder="Nama">{{name}}</ion-input>
</ion-item>
</ion-col>
</ion-row>
You need to call saveData() and loadData() somewhere of course. I assume, you did this already.
To display the data in your template, you need to store the data in any attribute of your class. In your case you want to store it like this:
this.storage.get('name').then((name) => {
this.name = name;
});
After this Promise (Note: It is asynchronous, that is important to know), your name attribute is populated with any value your stored in LocalStorage before.
You maybe want to use .catch() on the Promise to catch any errors, that occur, when you have not stored any value for name.

Uncaught Error: Can't resolve all parameters for MyloginPage

I created a login page which data I want to store to localStorage when passed from php api, but whenever i click on the button to the login page an error always occured.
i have searched through the net for a more details based on this error but I was unable to come up with anything.
Below is the error displayed to my screen when I tried to access my login page:
ERROR Error: Uncaught (in promise): Error: StaticInjectorError(AppModule)[MyloginPage -> AuthServiceProvider]:
StaticInjectorError(Platform: core)[MyloginPage -> AuthServiceProvider]:
NullInjectorError: No provider for AuthServiceProvider!
Error: StaticInjectorError(AppModule)[MyloginPage -> AuthServiceProvider]:
Below is the image:
Mylogin.html
<ion-content padding>
<ion-list>
<ion-item>
<ion-label>username</ion-label>
<ion-input type="text" name="username" [(ngModel)]="data.username"></ion-input>
</ion-item>
<ion-item>
<ion-label>password</ion-label>
<ion-input type="password" name="password" [(ngModel)]="data.password"></ion-input>
</ion-item>
</ion-list>
<button ion-button color="primary" full (click)="login()">Login</button>
</ion-content>
**mylogin.ts**
import { Component } from '#angular/core';
import { IonicPage, NavController, NavParams, ViewController } from 'ionic-angular';
import { AuthServiceProvider } from '../../providers/auth-service/auth-service';
import { Storage } from '#ionic/storage';
/**
* Generated class for the MyloginPage page.
*
* See https://ionicframework.com/docs/components/#navigation for more info on
* Ionic pages and navigation.
*/
#IonicPage()
#Component({
selector: 'page-mylogin',
templateUrl: 'mylogin.html',
})
export class MyloginPage {
data: any;
public local : Storage;
constructor(public navCtrl: NavController, public navParams: NavParams, private viewCtrl: ViewController, private service: AuthServiceProvider) {
this.data = {};
this.data.username = "";
this.data.password = "";
this.local = new Storage(null);
}
ionViewDidLoad() {
console.log('ionViewDidLoad MyloginPage');
}
login() {
let username = this.data.username;
let password = this.data.password;
let data = JSON.stringify({username, password});
this.service.postLogin(data);
}
dismiss(){
this.viewCtrl.dismiss();
}
}
Auth-service.ts
//import { HttpClient } from '#angular/common/http';
import { Injectable } from '#angular/core';
import { Http } from '#angular/http';
import 'rxjs/add/operator/map';
import { Storage } from '#ionic/storage';
/*
Generated class for the AuthServiceProvider provider.
See https://angular.io/guide/dependency-injection for more info on providers
and Angular DI.
*/
#Injectable()
export class AuthServiceProvider {
public local : Storage;
mydata: any;
constructor( public http: Http) {
this.local = new Storage(null)
}
postLogin(data){
let link = "http://textkhmer.com/api/securelogin.php";
return this.http.post(link, data)
.map(data => {
this.mydata = data;
console.log("data")
}, error =>{
console.log(error)
})
}
}
Please why is this error displaying?
Thanks

How to include the user credentials in every sidebar of very pages in ionic

I want to have an sidebar that can display the name of the user who logged in. I have an account page that display all the details of the user. This is the code of the typescript below for the accounts page.
import { Component } from '#angular/core';
import { NavController, AlertController} from 'ionic-angular';
import {Headers} from "#angular/http";
import 'rxjs/add/operator/map';
import {Storage} from "#ionic/storage";
import { Global } from '../../providers/global';
#Component({
selector: 'page-account',
templateUrl: 'account.html',
})
export class AccountPage {
constructor(public navCtrl: NavController,
private storage: Storage,
public alertCtrl: AlertController,
public global: Global
)
{
//
}
public ACCOUNT_URL = this.global.url + "/api/inspectors";
credentials:any;
contentHeader = new Headers({"Content-Type": "application/json"});
error: any;
user: any;
token_type: any;
access_token: any;
refresh_token:any;
ionViewDidLoad() {
console.log('ionViewDidLoad AccountPage');
this.getAccessToken();
this.getAccount();
}
getAccessToken(){
this.storage.get('access_token').then((value) => {
this.access_token=value;
});
}
getAccount(){
this.storage.get('user').then((value) => {
this.user=value;
});
}
}
and this is the code in my html.
<ion-header>
<ion-navbar color="danger">
<button ion-button menuToggle>
<ion-icon name="menu"></ion-icon>
</button>
<ion-title>Account</ion-title>
</ion-navbar>
</ion-header>
<ion-content class="page-account">
<ion-card>
<ion-item *ngIf="user">
<ion-card-content text-wrap>
<h2>Name: {{user.name}}</h2>
<p>{{user.cellphone_no}}</p>
<p> Address: {{user.address}} </p>
<p> Email: {{user.email}} </p>
</ion-card-content>
</ion-item>
</ion-card>
</ion-content>
What I want to happen is to delete the account pages and put the details of the user in top of the sidebar. So I have to put it into the app.html or app.ts but how can I define the property in my root component in order to display the details of that user.
Here is the code below in my app.component.ts
import { Component, ViewChild} from '#angular/core';
import { Nav, Platform } from 'ionic-angular';
import { StatusBar } from '#ionic-native/status-bar';
import { SplashScreen } from '#ionic-native/splash-screen';
import {Storage} from "#ionic/storage";
import { LoginPage } from '../pages/login/login';
import { AccountPage } from '../pages/account/account';
import { InspectionPage } from '../pages/inspection/inspection';
#Component({
templateUrl: 'app.html'
})
export class MyApp {
rootPage:any = LoginPage;
#ViewChild(Nav) nav: Nav;
pages: Array<{title: string, component: any, icon: string, color: string}>;
constructor(platform: Platform,
statusBar: StatusBar,
private storage: Storage,
splashScreen: SplashScreen) {
platform.ready().then(() => {
// Okay, so the platform is ready and our plugins are available.
// Here you can do any higher level native things you might need.
statusBar.styleDefault();
splashScreen.hide();
});
// used for an example of ngFor and navigation
this.pages = [
//{ title: 'Home', component: HomePage, icon: 'home', color: 'primary' },
{ title: 'Home', component: InspectionPage, icon: 'home', color: 'danger' },
{ title: 'Account', component: AccountPage, icon: 'person', color: 'primary' }
];
}
openPage(page) {
// Reset the content nav to have just this page
// we wouldn't want the back button to show in this scenario
this.nav.setRoot(page.component);
}
logout() {
// Reset the content nav to have just this page
// we wouldn't want the back button to show in this scenario
this.storage.remove('access_token');
this.storage.remove('username');
this.storage.remove('data');
this.storage.remove('user');
this.nav.setRoot(LoginPage);
}
}
and here is the code in my sidemenu or html.
<ion-menu [content]="content" id="myMenu">
<ion-header>
<ion-toolbar color="danger">
<ion-title>Menu</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-list>
<button menuClose ion-item *ngFor="let p of pages" (click)="openPage(p)">
<ion-icon [name]="p.icon" [color]="p.color" item-left></ion-icon> {{p.title}}
</button>
<button menuClose ion-item (click)="logout()">
<ion-icon name="log-out" color="default" item-left></ion-icon> Logout
</button>
</ion-list>
</ion-content>
</ion-menu>
<!-- Disable swipe-to-go-back because it's poor UX to combine STGB with side menus -->
<ion-nav [root]="rootPage" #content swipeBackEnabled="false"></ion-nav>
What I want to happen is to put the details of the user in the sidebar like what I did in the account page. Sorry for my long question. I tried searching for it but can't find any answer to it.
Looking for help.
Thanks in advance.
I would recommend that you create a service to handle the state of the user login. That way the state is handled in a central place and it will be much easier to maintain.
One possible approach would be to use a BehaviourSubject inside your service, which you can then subscribe to on every page that you need your user object (like your account page and your app component).
import {Injectable} from '#angular/core'
import {BehaviorSubject} from 'rxjs/BehaviorSubject';
#Injectable()
export class UserService {
// Observable user object (replace any with your user class/interface)
private _userObject = new BehaviorSubject<any>({});
// Expose an observable that can be used by components
userObject$ = this._userObject.asObservable();
// Method to update the user
changeUser(user) {
this._userObject.next(user);
}
}
You can now use the service like that (you have to implement the subscription logic in every component where you want to have access to your user):
import {Component} from '#angular/core';
import {UserService} from './user.service';
#Component({
selector: 'account-page'
})
export class AccountPage {
user: any;
subscription: Subscription;
constructor(private _userService: UserService) {}
ngOnInit() {
this.subscription = this._userService.userObject$
.subscribe(item => this.user = item);
}
ngOnDestroy() {
// prevent memory leak when component is destroyed
this.subscription.unsubscribe();
}
login() {
this._userService.changeUser({
name: 'Name' // Replace with name / user object
});
}
logout() {
this._userService.changeUser({});
}
}
As mentioned above, the big advantage is maintainability. If you ever change your user object, it only requires minimal changes, whereas the solution by #Tomislav Stankovic requires changes in every component where the user is used.
In your login page, when user is successfully logged-in, store data to localStorage
login(username,password){
this._api.userLogin().subscribe(res => {
if(res.status == 'ok'){
localStorage.setItem('user_first_name', res.user_first_name);
localStorage.setItem('user_last_name', res.user_last_name);
}
}
And then in app.component.ts get data from localStorage
this.first_name = localStorage.getItem('user_first_name');
this.last_name = localStorage.getItem('user_last_name');
Display data in app.html
<p>{{first_name}}</p>
<p>{{last_name}}</p>
On log-out clear localStorage
logout(){
localStorage.clear();
}

Share data between components using Service - IONIC 2, Angular 2

Is there any way to send data {{error.value}} to another page using a method?
This is my code
<ion-row *ngFor="let errors of adp_principal_menuRS">
<ion-col class="info-col" col-4>
<button ion-button color="primary" small (click)="goToErrors(errors.event)">
{{errors.event}}
</button>
</ion-col>
</ion-row>
goToErrors(menu: string){
console.log(menu);
this.navCtrl.push(AdpDetailPage, {
});
}
I want to send the {{errors.event}} value to another page in the goToErrors() method.
Thanks!
EDIT: I just achieve what I want. I edited the code
Data can be shared using BehaviorSubject between components via service.
Here is an example:
// service.ts
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
#Injectable()
export class ShareService {
private errorSource = new BehaviorSubject<any>(null);
error$ = this.errorSource.asObservable();
setError(error: any){
this.errorSource.next(error);
}
Set the error event in parent component using setError method and subscribe the error in error component.
// error component.ts
constructor(share: ShareService) {
share.error$.subscribe(Err => this.error = Err);
Why don't you send the value using a navParam?
goToErrors(menu: string){
console.log(menu);
this.navCtrl.push(AdpDetailPage, {
errorEvent: menu // <------------------------- Add this line
});
}
And in your AdpDetailPage:
export class AdpDetailPage{
constructor(public navParams: NavParams){
errorEvent = this.navParams.get('errorEvent');
console.log("errorEvent= ", errorEvent);
}
}
Use event emittor.
//Home component.ts import { Events } from 'ionic-angular'; constructor(public events: Events) {} directioChange(user) {this.events.publish('directiochanged', 'true');} //App.component.ts constructor(public events: Events) { events.subscribe('directiochanged', (direction) => { this.isRtl = direction;console.log(direction);});}
I generated a Plunker that hopefully matches with what you are trying to do.
https://plnkr.co/edit/MNqpIqJjp5FN30bJd0RB?p=preview
Service
import { Injectable } from '#angular/core';
#Injectable()
export class ErrorService {
errorInfo: string;
}
Component
#Component({
selector: 'my-app',
template: `
<div>
<h2>Hello {{name}}</h2>
<button (click)="goToErrors()">{{errors.event}} </button>
<router-outlet></router-outlet>
</div>
`,
})
export class App {
name:string;
errors = { event: 'Test Error', otherInfo: 'Test Info' };
constructor(private errorService: ErrorService, private router: Router) {
this.name = `Angular! v${VERSION.full}`
}
goToErrors(): void {
// Code to navigate to the other component
this.errorService.errorInfo = this.errors.event;
this.router.navigate(['/a']);
}
}