List is not updated for existing clients in socketIO - node.js

I am working on chat application, using socketIO
Whenever user signed in sucessfully, user is navigated to dashboard and list of current loggedin users will be displayed.
Whenever new user is signed in, existing user list is not getting updated.
Adding the necessary code here
events: backend
let verifyClaim = require("./tokenLib");
let socketio = require("socket.io");
let tokenLibs = require('./tokenLib');
let setService = (server) => {
let onlineUsers = [];
let io = socketio.listen(server);
let myio = io.of('')
myio.on('connection', (socket) => {
console.log(' emitting verify user');
socket.emit("verifyUser", "");
socket.on('set-user', (authToken) => {
console.log(authToken);
tokenLibs.verifyTokenWithoutSecret(authToken, (user, err,) => {
if (user) {
console.log(user);
let currentUser = user;
socket.userId = currentUser._id;
let fullName = `${currentUser.name}`
console.log(`${fullName} is online`);
socket.emit(currentUser._id, `${fullName} is online`)
let userObj = { userId: currentUser._id, name: fullName }
onlineUsers.push(userObj);
console.log(onlineUsers)
socket.emit('userlist', onlineUsers)
}
else {
socket.emit('auth-error', { status: 500, error: 'Please provide valid token ' })
}
})
})
socket.on('disconnect', () => {
console.log('user is disconnected');
let removeUserId = onlineUsers.map(function (user) { return user.userId }).indexOf(socket.userId)
onlineUsers.splice(removeUserId, 1)
console.log(onlineUsers)
})
})
}
module.exports = { setService: setService }
socket service:
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import * as io from 'socket.io-client';
import { Observable } from 'rxjs';
#Injectable({
providedIn: 'root'
})
export class SocketService {
public prod = 'https://todolistbe.herokuapp.com/api/v1';
public dev = 'http://localhost:3001';
public baseUrl = this.dev;
private socket;
constructor(public http: HttpClient) {
this.socket=io('http://localhost:3001')
}
public verifyUser=()=>{
return Observable.create((observer)=>{
this.socket.on('verifyUser',(data)=>{
observer.next(data);
})
})
}
public setUser=(authToken)=>{
this.socket.emit("set-user",authToken)
}
public userList=()=>{
return Observable.create((observer)=>{
this.socket.on('userlist',(data)=>{
observer.next(data);
})
})
}
public welcomeUser=(userid)=>{
return Observable.create((observer)=>{
this.socket.on(userid,(data)=>{
observer.next(data);
})
})
}
public disconnectUser = () => {
return Observable.create((observer) => {
this.socket.on('disconnect', () => {
observer.next()
})
})
}
}
dashboard:
import { Component, OnInit } from '#angular/core';
import { ThemePalette } from '#angular/material/core';
import { SocketService } from '../../socket.service';
import { ToastrService } from 'ngx-toastr';
export interface Task {
name: string;
completed: boolean;
color: ThemePalette;
subtasks?: Task[];
}
#Component({
selector: 'app-dashboard',
templateUrl: './dashboard.component.html',
styleUrls: ['./dashboard.component.css'],
providers: [SocketService]
})
export class DashboardComponent implements OnInit {
public authToken: any = localStorage.getItem('authToken');
public userList: any = [];
public userNotification;
allComplete: boolean = false;
ngOnInit(): void {
this.verifyUserConfirmation();
this.getOnlineUsers();
}
public verifyUserConfirmation: any = () => {
this.SocketService.verifyUser().subscribe((data) => {
console.log(this.authToken)
this.SocketService.setUser(this.authToken);
this.getOnlineUsers();
})
}
selected = 'option2';
toggleNavbar() {
console.log('toggled' + this.isMenuOpened);
this.isMenuOpened = !this.isMenuOpened;
}
getOnlineUsers() {
// this.SocketService.welcomeUser(localStorage.getItem('id')).subscribe((data)=>{
// this.userNotification=data;
// console.log("hi:"+this.userNotification)
// })
this.SocketService.userList().subscribe((user) => {
this.userList = [];
for (let x in user) {
let tmp = { 'user': x, 'name': user[x] }
this.userList.push(tmp);
}
console.log(this.userList)
})
}
}

Whenever you want to emit an event with all other users, we should use myio.emit instead of socket.io.
Issue is resolved when i made necessary changed in my backend events library

Related

I am trying to host a project I built on two separate repositories

I have a MEAN stack project that is built on two separate repositories. The backend is using Node.js and handles all API routing to MongoDB Atlas. If i wanted to host this on something like firebase, how would I go about that? I am not sure of any way to do this and haven't found similar scenarios such as this online.
This is an example of one of the components from the frontend.
The html file
import { Component, OnInit } from '#angular/core';
import { Router } from '#angular/router';
import { FamilyService } from '../family.service';
import { IncomeService } from '../income.service';
#Component({
selector: 'app-income',
templateUrl: './income.component.html',
styleUrls: ['./income.component.scss']
})
export class IncomeComponent implements OnInit {
date: any;
family: any;
amount: any;
Incomes: any = [];
Families: any = [];
constructor(private router: Router, private familyService: FamilyService, private incomeService: IncomeService) {
this.date = new Date().toDateString();
this.family = ""
this.amount = ""
}
ngOnInit(): void {
this.getFamilies()
this.getIncomes()
}
createNewIncome(){
let request = {
family: this.family,
amount: this.amount,
Date: this.date
}
console.log(request.family);
this.incomeService.createIncome(request).subscribe((response: any) => {
this.getIncomes()
});
}
getFamilies(){
let familyInfo:any = []
this.familyService.getFamily().subscribe((res: any) => {
let arr = res
arr.forEach((family: any) => {
// console.log(element)
if(family.status == "active"){
familyInfo.push(family)
}
});
});
console.log(familyInfo);
this.Families = familyInfo
}
getIncomes(){
let incomeInfo:any = []
this.incomeService.getIncome().subscribe((res: any) => {
let arr = res
arr.forEach((element: any) => {
// console.log(element)
incomeInfo.push(element)
});
});
console.log(incomeInfo);
this.Incomes = incomeInfo
}
goToPage(PageName:string):void{
this.router.navigate([`${PageName}`]);
// else
// outterrormessage
}
addEntry():void{
console.log(this.date + " " + this.family + " " + this.amount)
let entry = {
Date: this.date,
family: this.family,
amount: this.amount
}
this.Incomes.push(entry)
console.log(this.Incomes)
}
deleteEntry(entry:any):void {
if(confirm("Are you sure you would like to delete this entry?")){
this.incomeService.deleteIncome(entry._id).subscribe((res: any) => {
this.getIncomes() // Once the record gets deleted we refetch
})
}
}
updateEntry(entry:any):void {
if(confirm("Are you sure you would like to update this entry?")){
this.incomeService.updateIncome(entry._id, entry).subscribe((res:any) => {
this.getIncomes() // After the record gets edited we refetch
})
}
}
toggleEditEntry(entry:any){
entry.isEditing = !entry.isEditing;
}
}
The service.ts file
import { Component, OnInit } from '#angular/core';
import { Router } from '#angular/router';
import { FamilyService } from '../family.service';
import { IncomeService } from '../income.service';
#Component({
selector: 'app-income',
templateUrl: './income.component.html',
styleUrls: ['./income.component.scss']
})
export class IncomeComponent implements OnInit {
date: any;
family: any;
amount: any;
Incomes: any = [];
Families: any = [];
constructor(private router: Router, private familyService: FamilyService, private incomeService: IncomeService) {
this.date = new Date().toDateString();
this.family = ""
this.amount = ""
}
ngOnInit(): void {
this.getFamilies()
this.getIncomes()
}
createNewIncome(){
let request = {
family: this.family,
amount: this.amount,
Date: this.date
}
console.log(request.family);
this.incomeService.createIncome(request).subscribe((response: any) => {
this.getIncomes()
});
}
getFamilies(){
let familyInfo:any = []
this.familyService.getFamily().subscribe((res: any) => {
let arr = res
arr.forEach((family: any) => {
// console.log(element)
if(family.status == "active"){
familyInfo.push(family)
}
});
});
console.log(familyInfo);
this.Families = familyInfo
}
getIncomes(){
let incomeInfo:any = []
this.incomeService.getIncome().subscribe((res: any) => {
let arr = res
arr.forEach((element: any) => {
// console.log(element)
incomeInfo.push(element)
});
});
console.log(incomeInfo);
this.Incomes = incomeInfo
}
goToPage(PageName:string):void{
this.router.navigate([`${PageName}`]);
// else
// outterrormessage
}
addEntry():void{
console.log(this.date + " " + this.family + " " + this.amount)
let entry = {
Date: this.date,
family: this.family,
amount: this.amount
}
this.Incomes.push(entry)
console.log(this.Incomes)
}
deleteEntry(entry:any):void {
if(confirm("Are you sure you would like to delete this entry?")){
this.incomeService.deleteIncome(entry._id).subscribe((res: any) => {
this.getIncomes() // Once the record gets deleted we refetch
})
}
}
updateEntry(entry:any):void {
if(confirm("Are you sure you would like to update this entry?")){
this.incomeService.updateIncome(entry._id, entry).subscribe((res:any) => {
this.getIncomes() // After the record gets edited we refetch
})
}
}
toggleEditEntry(entry:any){
entry.isEditing = !entry.isEditing;
}
}
The web service
import { HttpClient } from '#angular/common/http';
import { Injectable } from '#angular/core';
#Injectable({
providedIn: 'root'
})
export class WebRequestService {
//Root URL wrapped in constant
readonly ROOT_URL;
//Returns http method observables
constructor(private http: HttpClient) {
this.ROOT_URL = `http://localhost:3000`;
}
//Getting one
get(uri: string) {
return this.http.get(`${this.ROOT_URL}/${uri}`);
}
//Creating one
post(uri: string, payload: Object) {
return this.http.post(`${this.ROOT_URL}/${uri}`, payload);
}
//Updating one
patch(uri: string, payload: Object) {
return this.http.patch(`${this.ROOT_URL}/${uri}`, payload);
}
//Deleting one
delete(uri: string) {
return this.http.delete(`${this.ROOT_URL}/${uri}`);
}
}
This is my first time working with Angular and a MEAN stack so I apologize for the poor programming practices here.If you need I can also upload the backend code: routes, models, and service files.

Jest - Invariant failed: You should not use <Link> outside a <Router>

I'm getting this error when running a test, however I have wrapped the component I am testing in a <BrowserRouter> component:
● Axios › gets a response
Invariant failed: You should not use <Link> outside a <Router>
91 |
92 | if (RootComponent) {
> 93 | const component = mountWithCustomWrappers(<Wrapper store={store}><RootComponent
{...props} />, rootWrappers);
nock.integration.test
import React from 'react';
import axios from 'axios';
const core = require('tidee-life-core');
import httpAdapter from 'axios/lib/adapters/http';
import doFetch from '../../../helpers/doFetch.js';
import ComponentBuilder from "../component-builder";
import LoginPage from "../../../scenes/login/login-page";
const host = 'http://example.com';
process.env.API_URL = host;
axios.defaults.host = host;
axios.defaults.adapter = httpAdapter;
const makeRequest = () => {
return doFetch({
url: core.urls.auth.login(),
queryParams: { foo: 'bar' },
})
.then(res => res.data)
.catch(error => console.log(error));
};
describe('Axios', () => {
let component;
let componentBuilder;
beforeEach(() => {
componentBuilder = new ComponentBuilder();
});
test('gets a response', async () => {
componentBuilder.includeInterceptor('login');
component = await componentBuilder.build({
RootComponent: LoginPage,
selector: 'LoginForm',
});
return makeRequest()
.then(response => {
expect(typeof response).toEqual('object');
expect(response.data.token).toEqual('eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhNDY3MGE3YWI3ZWM0ZjQ2MzM4ODdkMzJkNzRkNTY5OSIsImlhdCI6MTU1MjA5MDI1NX0.vsKLXJEqSUZK-Y6IU9PumfZdW7t1SLM28jzJL89lcrA');
});
});
});
login-page.jsx:
import React, { Component } from 'react';
import PropTypes from "prop-types";
import { withRouter } from 'react-router-dom';
import { injectIntl, intlShape } from 'react-intl';
import queryString from 'query-string';
import { Link } from 'tidee-life-ui';
import LoginForm from './login-form.jsx';
import { doLogin } from '../../api/auth/auth-api';
import Auth from '../../modules/Auth';
import messages from '../../messages';
const { urls } = require('tidee-life-core');
class LoginPage extends Component {
constructor(props) {
super(props);
const { intl } = props;
if (Auth.isUserAuthenticated()) {
props.history.replace({ pathname: urls.pages.pathBoxes() });
}
this.messages = {
'account.activation.error.expired': intl.formatMessage(messages['account.activation.error.expired']),
'account.activation.required': intl.formatMessage(messages['account.activation.required']),
'common.click': intl.formatMessage(messages['common.click']),
'common.here': intl.formatMessage(messages['common.here']),
'error.500.msg': intl.formatMessage(messages['error.500.msg']),
'forgot.success': intl.formatMessage(messages['forgot.success']),
'login.account.needs.activating.partial': intl.formatMessage(messages['login.account.needs.activating.partial']),
'login.error.account.credentials': intl.formatMessage(messages['login.error.account.credentials']),
'login.validation.email': intl.formatMessage(messages['login.validation.email']),
'login.validation.password': intl.formatMessage(messages['login.validation.password']),
'signup.account.created': intl.formatMessage(messages['signup.account.created'])
};
let alertMessage;
let alertMessageType;
const query = queryString.parse(props.location.search);
if ('signup-success' in query) {
alertMessage = this.messages['signup.account.created'];
alertMessageType = 'success';
} else if ('forgot-success' in query) {
alertMessage = this.messages['forgot.success'];
alertMessageType = 'success';
}
this.state = {
alert: {
type: alertMessageType ? alertMessageType : '',
msg: alertMessage ? alertMessage : '',
},
user: {
email: '',
password: ''
}
};
this.changeUser = this.changeUser.bind(this);
this.clearAlert = this.clearAlert.bind(this);
this.processForm = this.processForm.bind(this);
}
clearAlert() {
this.setState({ alert: {
type: '',
msg: '',
}});
}
processForm(e) {
e.preventDefault();
return doLogin({
email: this.state.user.email,
password: this.state.user.password,
}).then((response) => {
Auth.authenticateUser(response.data.token);
this.props.history.replace({ pathname: urls.pages.pathBoxes() });
}).catch((error) => {
const msg = error.message && this.messages[error.message] ? [this.messages[error.message]] : [this.messages['error.500.msg']];
if (error.message === 'account.activation.error.expired' || error.message === 'account.activation.required') {
const to = urls.pages.pathResendLink(error.data.confirmHash);
msg.push(` ${this.messages['common.click']} `);
msg.push(<Link underline color="inherit" key="email" to={to}>{this.messages['common.here']}</Link>);
msg.push(` ${this.messages['login.account.needs.activating.partial']}`);
}
this.setState({
alert: {
type: 'error',
msg,
}
});
});
}
changeUser(event) {
const { name, value } = event.target;
this.setState((currentState) => ({
user: {
...currentState.user,
[name]: value,
}
}));
}
render() {
return (
<LoginForm
data-test="login-form"
alert={this.state.alert}
onSubmit={this.processForm}
onChange={this.changeUser}
user={this.state.user}
/>
);
}
}
LoginPage.propTypes = {
history: PropTypes.object,
intl: intlShape.isRequired,
location: PropTypes.object.isRequired,
};
export default injectIntl(withRouter(LoginPage));
component-builder.js
import React from "react";
import nock from 'nock';
import cloneDeep from 'lodash.clonedeep';
import { mountWithCustomWrappers } from 'enzyme-custom-wrappers';
import { waitForStoreState } from './wait/wait-for-store-state';
import Wrapper from './wrapper.jsx';
import waitForComponentPredicate from './wait-for-component-predicate/wait-for-component-predicate';
import waitForComponentSelector from './wait-for-component-selector/wait-for-component-selector';
import { startAllNockServiceIntercepts } from './nock/nock-manager';
import nockServices from './nock/services';
import store from "../../store/store";
import wrappers from './wrappers';
const rootWrappers = component => wrappers(component);
class ComponentBuilder {
constructor() {
this.nockInterceptors = [];
this.storePreparers = [];
}
includeInterceptor( interceptorName, nockConfigOverride = null ) {
// Maybe need to do a clone deep here if things start breaking!
const clonedNockService = cloneDeep(nockServices[interceptorName]().nockConfig);
const nockService = {
[interceptorName]: {
...clonedNockService,
...(nockConfigOverride || {}),
}
};
this.nockInterceptors.push(nockService);
}
prepareStore( storePreparer ) {
this.storePreparers.push(storePreparer);
}
async waitForStoreToUpdate() {
const promises = this.storePreparers
.map(service => waitForStoreState(service.redux.storeStateToWaitFor, store));
await Promise.all(promises);
}
async runStorePreparers() {
nock.cleanAll();
const interceptors = [];
this.storePreparers.forEach((service) => {
const interceptorName = service.http.interceptor;
const clonedNockService = service.http.interceptor && cloneDeep(nockServices[interceptorName]().nockConfig);
interceptors.push({
[interceptorName]: {
...clonedNockService,
}
});
});
startAllNockServiceIntercepts(interceptors);
this.storePreparers.forEach(service => service.redux.actionToDispatch && store.dispatch(service.redux.actionToDispatch()));
return await this.waitForStoreToUpdate();
}
/**
* Build a component to be tested.
* #param RootComponent
* #param selector {string} - A selector to wait for. CSS selector or name of component.
* #param props {object}
* #param store {object}
* #param predicate {function} - A function that returns true if a condition is met.
* #param predicateMaxTime {number}
* #param predicateInterval {number}
* #returns {Promise<*>}
*/
async build({
RootComponent = null,
selector = '',
props = {},
predicate = null,
predicateMaxTime = 2000,
predicateInterval = 10,
} = {}) {
try {
await this.runStorePreparers();
startAllNockServiceIntercepts(this.nockInterceptors);
if (RootComponent) {
const component = mountWithCustomWrappers(<Wrapper store={store}><RootComponent {...props} /></Wrapper>, rootWrappers);
if (selector) {
await waitForComponentSelector({ selector, rootComponent: component, store });
}
if (predicate) {
await waitForComponentPredicate({
predicate,
rootComponent: component,
store,
maxTime: predicateMaxTime,
interval: predicateInterval,
});
}
return component;
}
} catch(err) {
throw err;
}
}
}
export default ComponentBuilder;
wrapper.jsx
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { BrowserRouter } from "react-router-dom";
import { Provider } from 'react-redux';
import ThemeProvider from "../../theme/Theme.jsx";
import LocaleProviderWrapper from "./locale-provider-wrapper.jsx";
const propTypes = {
children: PropTypes.element.isRequired,
store: PropTypes.object.isRequired,
};
class Wrapper extends Component {
getStore() {
return this.props.store;
}
render() {
return (
<Provider store={this.props.store}>
<LocaleProviderWrapper>
<ThemeProvider>
<BrowserRouter>{this.props.children}</BrowserRouter>
</ThemeProvider>
</LocaleProviderWrapper>
</Provider>
);
}
}
Wrapper.propTypes = propTypes;
export default Wrapper;
Exactly as message says, you cannot use Link which doesn't have any parent of type Router. In you processForm function you are building a messaage with Link component which is worng.
if (error.message === 'account.activation.error.expired' || error.message === 'account.activation.required') {
const to = urls.pages.pathResendLink(error.data.confirmHash);
msg.push(` ${this.messages['common.click']} `);
msg.push(<Link underline color="inherit" key="email" to={to}>{this.messages['common.here']}</Link>);
msg.push(` ${this.messages['login.account.needs.activating.partial']}`);
}
You should use a tag to build dynamic link. May be something like:
msg.push(`${this.messages['common.here']}`);

I have used tesseract.js in ionic to extract text from an image. Now is there a way to represent the extracted text in a key value pair?

import { Component } from '#angular/core';
import { NavController, ActionSheetController, LoadingController } from '#ionic/angular';
import { Camera, PictureSourceType } from '#ionic-native/camera/ngx';
import * as Tesseract from 'tesseract.js'
// import { NgProgress } from 'ngx-progressbar';
// import { NgProgress } from '#ngx-progressbar/core';
import { createWorker } from 'tesseract.js';
#Component({
selector: 'app-home',
templateUrl: 'home.page.html',
styleUrls: ['home.page.scss'],
})
export class HomePage {
progress = false;
worker = createWorker({
logger: m => console.log(m)
})
selectedImage: string;
imageText: string;
constructor(
public navCtrl: NavController,
private camera: Camera,
private actionSheetCtrl: ActionSheetController,
// public ngProgress: NgProgress
) {}
async selectSource() {
let actionSheet = await this.actionSheetCtrl.create({
buttons: [
{
text: 'Use Library',
handler: () => {
this.getPicture(this.camera.PictureSourceType.PHOTOLIBRARY);
}
}, {
text: 'Capture Image',
handler: () => {
this.getPicture(this.camera.PictureSourceType.CAMERA);
}
}, {
text: 'Cancel',
role: 'cancel'
}
]
});
actionSheet.present();
}
getPicture(sourceType: PictureSourceType) {
this.camera.getPicture({
quality: 100,
destinationType: this.camera.DestinationType.DATA_URL,
sourceType: sourceType,
allowEdit: true,
saveToPhotoAlbum: false,
correctOrientation: true
}).then((imageData) => {
this.selectedImage = `data:image/jpeg;base64,${imageData}`;
});
}
recognizeImage() {
(async () => {
await this.worker.load();
this.progress = true;
await this.worker.loadLanguage('eng');
await this.worker.initialize('eng');
const { data: { text } } = await this.worker.recognize(this.selectedImage);
this.imageText = JSON.stringify(text);
// this.imageText = this.imageText.split('\n').join("<br />")
this.progress = false;
await this.worker.terminate();
})();
// Tesseract.recognize(this.selectedImage)
// .progress(message => {
// if (message.status === 'recognizing text')
// this.ngProgress.set(message.progress);
// console.log('progressing....')
// })
// .catch(err => console.error(err))
// .then(result => {
// this.imageText = result.text;
// })
// .finally(resultOrError => {
// this.ngProgress.done();
// console.log('finished.');
// });
}
}
I have used tesseract.js in ionic to extract text from an image. Now is there a way to represent the extracted text in a key-value pair?
I want to represent the extracted text from the image in the form of key-value pair like:
{"name":"john", "title":"anniversary"}. Is there a way that this can be done?
this is the output image.

How to integrate Stripe payment in Ionic 4

I am new in ionic framework and trying to integrate stripe in my app.
I did some research and found only this https://ionicframework.com/docs/native/stripe. It doesn't explain well enough. How can i implement the concept on .html file like to provide a user with a button to trigger the payment?
I also tried this https://fireship.io/lessons/stripe-elements-angular/ but got lost along the way.
checkout.page.ts
import { Component, OnInit, Input, HostListener } from '#angular/core';
// import { Stripe } from '#ionic-native/stripe/ngx';
import { AuthService } from '../services/auth.service';
import { FirebaseService } from '../services/firebase.service';
import { AngularFireFunctions } from '#angular/fire/functions';
import { Router } from '#angular/router';
import { Observable, of } from 'rxjs';
declare var Stripe;
#Component({
selector: 'app-rentals',
templateUrl: './rentals.page.html',
styleUrls: ['./rentals.page.scss'],
})
export class RentalsPage implements OnInit {
user$: Observable<User>;
constructor(
private router: Router,
// private stripe: Stripe,
private firebaseService: FirebaseService,
private auth: AuthService,
private functions: AngularFireFunctions
)
{
}
#Input() amount;
#Input() description;
handler: StripeCheckoutHandler;
confirmation: any;
loading = false;
ngOnInit() {
this.handler = StripeCheckout.configure({
key: 'pk_test_3PyCxdSZ21lC5Wg7lOs2gyF8',
image: '/assets/icon/favicon.png',
locale: 'auto',
source: async (source) => {
this.loading = true;
const user = await this.firebaseService.User();
const fun = this.functions.httpsCallable('stripeCreateCharge');
this.confirmation = await fun({ source: source.id, uid: user.uid, amount: this.amount }).toPromise();
this.loading = false;
}
});
}
// Open the checkout handler
async checkout(e) {
const user = await this.auth.getUser();
this.handler.open({
name: 'Fireship Store',
description: this.description,
amount: this.amount,
email: user.email,
});
e.preventDefault();
}
// Close on navigate
#HostListener('window:popstate')
onPopstate() {
this.handler.close();
}
}
checkout.page.html
<ion-card>
<ion-card-header>
<img *ngIf="!fileUrl" src="assets/1.jpeg"/>
<ion-card-subtitle>Bed Sitter</ion-card-subtitle>
<ion-input type="hidden" [(ngModel)]="id">{{ plan_Et8WWHlFFGNxym }}</ion-input>
<ion-card-title>KSH4,000.00 Monthly</ion-card-title>
</ion-card-header>
<ion-card-content>
bed sitter flat
</ion-card-content>
<ion-card-content>
<ion-input type="hidden" [(ngModel)]="amount">{{ 4000 }}</ion-input>
<ion-button slot="end" color="primary" (click)="checkout($event)">Pay 4000.00</ion-button>
</ion-card-content>
</ion-card>
auth.service.ts
import { Injectable } from '#angular/core';
import * as firebase from 'firebase/app';
import { FirebaseService } from './firebase.service';
import { AngularFireAuth } from '#angular/fire/auth';
import { Observable, of } from 'rxjs';
#Injectable({
providedIn: 'root'
})
export class AuthService {
user$: Observable<User>;
constructor(
private firebaseService: FirebaseService,
public afAuth: AngularFireAuth
){}
doRegister(value){
return new Promise<any>((resolve, reject) => {
firebase.auth().createUserWithEmailAndPassword(value.email, value.password)
.then(
res => resolve(res),
err => reject(err))
})
}
doLogin(value){
return new Promise<any>((resolve, reject) => {
firebase.auth().signInWithEmailAndPassword(value.email, value.password)
.then(
res => resolve(res),
err => reject(err))
})
}
doLogout(){
return new Promise((resolve, reject) => {
this.afAuth.auth.signOut()
.then(() => {
this.firebaseService.unsubscribeOnLogOut();
resolve();
}).catch((error) => {
console.log(error);
reject();
});
})
}
}
I expect the code to fetch subscription plans from stripe or as i have input manually on the code above, to post the payment with the stated plan to stripe.

How to use Backend Object in FrontEnd TypeScript (MEAN Stack)

Using MongoDB, express.js, angular4, node.js
A string I retrieve is well retrieved, but not the same as a full object...
account.service.ts (full, )
import { Injectable } from '#angular/core';
import { Http, Headers, Response } from '#angular/http';
import 'rxjs/Rx';
import { Observable } from 'rxjs/Observable';
const jwtDecode = require('jwt-decode');
import { User } from '../../models/user.model';
import { AuthService } from './auth.service';
#Injectable()
export class AccountService {
constructor(private http: HttpClient,
private authService: AuthService) {}
user: any[];
currentUser() {
if(this.authService.isAuthenticated()){
const token = localStorage.getItem('token');
const decoded = jwtDecode(token);
return decoded.user;
}
};
getProfile() {
const id = this.currentUser();
return this.http.get("http://localhost:3000/user/" + id).
map(
(response: Response) => {
const data = response.json();
return data;
}
)
.catch(
(error: Response) => {
console.log(error);
return Observable.throw(error.json());
}
)
}
user-profile.component.ts
export class UserProfileComponent implements OnInit {
id: string;
user: any;
constructor(private account: AccountService) {}
ngOnInit() {
this.id = this.account.currentUser();
this.user = this.account.getProfile()
.subscribe(user => {
this.user = user;
return this.user;
});
}
logUser() {
console.log(this.id);
console.log(this.user);
}
}
user-profile.component.html
<p>{{user}}</p>
<p>User with ID {{id}} Loaded</p>
<a (click)="logUser()">Log User Test</a>
HTML file shows:
[object Object]
User with ID 59ca916323aae527b8ec7fa2 Loaded
What I get from clicking "log User" link is the retrieved ID string and the user object:
59ca916323aae527b8ec7fa2
[{...}] //clicking this reveals all of the object's details.
But I can't make that step of getting those details and presenting them in the HTML as I successfully managed with the ID... I mean, {{user.anything}} doesn't fetch the user's data as it should
May I have some assistance?
Change your getProfile() to,
getProfile() {
const id = this.currentUser();
return this.http.get("http://localhost:3000/user/" + id).
map(
(response) => response.json()
)
.catch(
(error: Response) => {
console.log(error);
return Observable.throw(error.json());
}
)
}
Also, in ngOnInit() change this one,
this.user = this.account.getProfile()
.subscribe((user) => {
this.user = user;
});
See if it gives you the right output.
EDIT
Change this one,
this.user = this.account.getProfile()
.subscribe((user) => {
this.user = JSON.parse(JSON.stringify(user));
});
EDIT-2
this.user = this.account.getProfile()
.subscribe((user) => {
this.user = JSON.stringify(user);
this.userObj = JSON.parse(JSON.stringify(user));
// also try, this.userObj = user; if above line didn't work
});
Define another property in component as ,
userObj: any;
Refer to the object in template as this
{{ userObj[0]?.email }}

Resources