How to create ionic 2 infinite scroll with data from database - mysql

I'd query about 500 users from database who are active. I am using laravel and ionic framework.
Here is my query using laravel.
public function getUsers(Request $request) {
$users = DB::table('users')->where('status', $request->status)->get();
return Response::json($users);
}
Here might be my .ts code in ionic 2
import { Component } from '#angular/core';
import { Http, Headers, RequestOptions } from "#angular/http";
#Component({
selector: 'page-users',
templateUrl: 'users.html'
})
export class UsersPage {
users: any = [];
constructor(
private http: Http
) {
var headers = new Headers();
headers.append("Accept", 'application/json');
headers.append('Content-Type', 'application/json' );
let options = new RequestOptions({ headers: headers });
let data = { 'status': 'active'}
this.http.post('http://path/to/laravel/api/getUsers', data, options)
.subscribe(res => {
var jsonData = JSON.parse(res['_body']);
this.users = jsonData;
})
}
doInfinite(infiniteScroll) {
// How can I do infinite scroll here???
setTimeout(() => {
infiniteScroll.complete();
}, 1000);
}
}
I am able to get the 500 active users and display it on my view.
However, It is a kind of laggy because there are too many data query at once.
I want to create infinite scroll to optimize the query. But, I don't know how to implement that in ionic 2.
I want atleast 10 users to be query everytime I scroll. Answers are appreciated.

I'll just pull off one of my codes and replace some variable names. Hopefully it will make sense and be helpfull:
Assuming you have this on your html:
<ion-infinite-scroll (ionInfinite)="fetchMore($event)">
<ion-infinite-scroll-content></ion-infinite-scroll-content>
</ion-infinite-scroll>
You will need something like this on your .ts:
fetchMore(event) {
this.myService.getMoreItems(10/*number of items to fetch*/,this.collection.length/*you might need to send the "skip" value*/).then(
(moreItems: any[]) => {
if (moreItems.length > 0) {
this.collection = this.collection.concat(moreItems);
}
event.complete();
},
(err) => {
event.complete();
}
);
}
The myService.getMoreItems part will be your service/provider that has the function, return type is a Promise<any>, that will make the Http Request. I think you got the idea.

Related

How to store product-info into session in WooCommerce using Next.js and headless wordpress

I am currently working on a Next.js project. As I’m building an online-shop, I also want to create a shopping-cart. I use wordpress (headless) via graphql and the api of WooCommerce.
Now the idea is to somehow store the product information into a session or using the local storage. I think storing the product id would be sufficient, because I want to sell online products that have an unlimited quantity and each customer can only download the product once.
What do I have to do in order that WooCommerce understands, what I want to achieve?
Is it possible instead of using an endpoint to just use the product-info from a JSON? (This is probably not so secure, but as I am only testing. It should be fine)
I have read that also cookies have to be written in order for WooCommerce to work and save the selected product into the shopping-cart.
I would be very thankful for any help 😊
Down below I show you part of my current state...
main file for the cart:
import { getSession, storeSession } from './session';
import { getAddOrViewCartConfig } from './api';
import axios from 'axios';
import { ADD_TO_CART_ENDPOINT } from '../constants/endpoints';
import { isEmpty } from 'lodash';
export const addToCart = (productId: int, qty: int = 1) => {
const storedSession = getSession();
const addOrViewCartConfig = getAddOrViewCartConfig();
axios.post(
ADD_TO_CART_ENDPOINT, //instead of using an endpoint, I would like to pull the desired info from a JSON file
data: {
product_id: productId,
quantity: qty,
},
addOrViewCartConfig
)
.then((res: AxiosResponse<any>) => {
if (!isEmpty(storedSession)) {
storeSession(res?.headers?.['x-wc-session']);
}
viewCart();
})
.catch((err) => {
console.log('err', err);
});
};
getAddOrViewCartConfig from api:
import { getSession } from './session';
import { isEmpty } from 'lodash';
export const getAddOrViewCartConfig = () => {
const config = {
headers: {
'X-Headless-CMS': true,
},
};
const storedSession = getSession();
if (!isEmpty(storedSession)) {
config.headers['x-wc-session'] = storedSession;
}
return config;
};
getSession, storeSession from session
import { isEmpty } from "lodash";
export const storeSession = (session) => {
if(isEmpty(session)){
return null;
}
localStorage.setItem('x-wc-session',session);
}
export const getSession = ()=>{
return localStorage.getItem(key:'x-wc-session');
}

Batching with useQuery react hooks getting back undefined

I am currently working on a project which requires me to make multiple queries/mutations. I tried setting up my apollo client with BatchHttpLink and I can see the data I am requesting in the network tab in the browser. It is coming back at an array of objects instead of JSON.
But the issue is when I try to grab the data in my component data is undefined. I tried using HttpLink instead of BatchHttpLink and I can get the data back from the hook.
My suspicion is the shape of the object that comes back from the response is different, I tried looking into documentation but I can't find much about batching.
Currently using "#apollo/client#^3.0.2"
Here's my client set up.
import { ApolloClient, InMemoryCache, ApolloLink, from } from '#apollo/client'
import { BatchHttpLink } from '#apollo/client/link/batch-http'
import { onError } from '#apollo/client/link/error'
const BASE_URL = 'http://localhost:4000'
const httpLink = new BatchHttpLink({
uri: BASE_URL,
credentials: 'include',
})
const csrfMiddleware = new ApolloLink((operation, forward) => {
operation.setContext(({ headers = {} }) => ({
headers: {
...headers,
'X-CSRF-Token': getCSRFToken(),
},
}))
return forward(operation)
})
const errorMiddleware = onError(({ networkError }) => {
if (networkError && 'statusCode' in networkError && networkError.statusCode === 401) {
window.location.assign('/accounts/login')
}
})
const client = new ApolloClient({
link: from([errorMiddleware, csrfMiddleware, httpLink]),
cache: new InMemoryCache(),
})
This is the react hook I'm trying to console log.
const {data} = useQuery(GET_USER_PERMISSIONS_AND_PREFERENCES)
Figured it out. You need to add another middleware to return the data that the useQuery hook can recognize. The data that comes back in the batch call is an array of objects shaped
{
payload: {
data: { ... }
}
}
So something like this did the trick for me
const batchParseMiddleware = new ApolloLink((operation, forward) => {
return forward(operation).map((data: any) => data.payload)
})
I have been having a similar issue, and have so far only been able to solve it by breaking batching and converting to a normal HttpLink

HTML table not automatically updating after executing HTTP post

I created a dummy website for a 'game library' just to teach myself the http POST, GET, PUT and DELETE methods, I have a separate file for my api with 3 'games' in. The post does work when I enter a new game name and click enter nothing happens but when I refresh the page my html table then displays the first three games plus the one I just posted. I would like to have it post and then display it on the table right away rather than having to refresh the page as its abit sloppy in my opinion.
I have tried putting the input box above the table, but I don't really know what else to try.
<h3>Here is your list of current games in your library</h3>
<table>
<tr>
<th>Id</th>
<th>Name</th>
</tr>
<tr *ngFor="let game of games">
<td>{{game.id}}</td>
<td>{{game.name}}</td>
</tr>
</table>
public games: any = [];
private url = 'http://localhost:3000/api/games';
constructor(private httpClient: HttpClient){
httpClient.get(this.url).subscribe(response => {
this.games = response;
});
}
createGame(name: HTMLInputElement) {
let post = {name : name.value};
name.value = '';
let headers = new HttpHeaders();
headers= headers.set('Content-Type', 'application/json');
this.httpClient.post(this.url, {id: this.games.length + 1,name: post.name }, {headers})
.subscribe(response => {
console.log(response)
})
}
I would like the table to auto update when I post a new game to it.
You have to implements OnInit on your component, see the doc here [https://angular.io/api/core/OnInit]
Your get request should be in the ngOnInit() like this :
ngOnInit(){
httpClient.get(this.url).subscribe(response => {
this.games = response;
});
}
After creating your new data, call ngOnInit() function and
your table will be updated.
You are not retrieving back the changed data. Once the POST call is successful, make a GET call to get the updated data.
createGame(name: HTMLInputElement) {
let post = {name : name.value};
name.value = '';
let headers = new HttpHeaders();
headers= headers.set('Content-Type', 'application/json');
this.httpClient.post(this.url, {id: this.games.length + 1,name: post.name },{headers}).subscribe(response => {
console.log(response)
// Subscribe back the changes
this.httpClient.get(this.url).subscribe(response => {
this.games = response;
});
})
}
Another way is to write another function which uses the GET call to update the data. You can use that one for initially loading the data as well as updating after new game creation.
#sammyleighg try like this,
you can update your games list once you have successfully posting your data, just make another http call to your Server.
create a method to simplified logic.
Component.ts
public games: any = [];
private url = 'http://localhost:3000/api/games';
constructor(private httpClient: HttpClient){
this.getGamesInfo();
}
getGamesInfo() {
this.httpClient.get(this.url).subscribe(response => {
this.games = response;
});
}
createGame(name: HTMLInputElement) {
let post = {name : name.value};
name.value = '';
let headers = new HttpHeaders();
headers= headers.set('Content-Type', 'application/json');
this.httpClient.post(this.url, {id: this.games.length + 1,name: post.name }, {headers})
.subscribe((response: any) => {
if(response.status == 200) {
this.getGamesInfo();
}
})
}
I will recommend to use ngOnInit() for making Api calls rather than in constructor()
You have to add newly created game to games array inside createGame method:
this.games.push({id: this.games.length + 1,name: post.name });
For PUT method you need to find edited item in array and then change its data:
let editedGame = this.games.find(game => game.id === UserInputId);
editedGame.name = UserInputName;

display data from json object on HTML in angular 5

hello i want to display the data that i got from a mongodb using a backend api (nodejs)
this is the code for event model
const mongoose = require('mongoose');
const config = require('../config/database');
// Events Schema
const EventSchema = mongoose.Schema({
eventname: {
type: String,
required: true
},
eventstartdate: {
type: String,
required: true
},
eventenddate: {
type: String,
required: true
},
eventcategorie: {
type: String
},
eventdescription: {
type: String
},
eventimage: {
type: String
}
});
const Event = module.exports = mongoose.model('Event', EventSchema);
this is the code from the router
const express = require('express');
const router = express.Router();
const passport = require('passport');
const jwt = require('jsonwebtoken');
const config = require ('../config/database');
const User = require('../models/user');
const Event = require('../models/event');
//get event by id
router.get('/event/:eventid', (req,res) => {
Event.findById(req.params.eventid, (err, event) =>{
if (err){
return res.status(500).send({message:err.message});
}
if(!event){
return res.status(400).send({message:'Event not found'});
}
res.json({
event: {
id: event._id,
eventname: event.eventname,
eventstartdate: event.eventstartdate,
eventenddate: event.eventenddate,
eventcategorie: event.eventcategorie,
eventdescription: event.eventdescription,
eventimage: event.eventimage
}
});
});
});
and this is the code from the service in the angular
// GET an event by ID
displayEvent$(id: string) {
return this.http.get(`http://localhost:3000/users/event/${id}`)
.map(response => response.json());
}
then i created a simple method that is triggered by a button
and i passed an id of an event that i konw is in the database just to test it out
onclickeventpage(){
this.authService.displayEvent$('5ae0c8e96b40a71cd3b772cc').subscribe(event => {
console.log(event)
});
}
this gives me back at the console the event i need with every aribute
but whene i change this
console.log(event)
to this so i can get evey atribute separetly and then i an put them in the html
console.log(event.eventname)
i get undefined
i just want to know how to get every event atribute so i can display them in my html page
First you dont have to call .json() witn angular5
displayEvent$(id: string) {
return this.http.get(`http://localhost:3000/users/event/${id}`)
.map(response => response.json());
}
also you need to access
console.log(event.event.eventname);
HttpModule is deprecated and the new HttpClientModule by default formats the response to JSON so we no longer need to parse it using response.json():
I just want to know how to get every event attribute so that I can
display them on my HTML page
You can tell HttpClient the type of the response to make consuming the output easier and more obvious.
Typechecking of response can be done by using type parameter
export interface Ievent {
id:string
eventname: string
eventstartdate: string
eventenddate: string
eventcategorie: string
eventdescription: string
eventimage: string
}
Http returns an observable and We can tell the HttpClient.get to return response as Ievent type When we use http.get<Ievent>(...) then it returns the instance of Observable<Ievent> type.
In your service
import { HttpClient } from '#angular/common/http';
import { Observable } from 'rxjs/Observable';
import {Ievent} from './eventModel'
#Injectable()
export class authService()
{
constructor(private http:HttpClient){}
displayEvent$(id: string)Observable<Ievent> {
return this.http.get<Ievent>(`http://localhost:3000/users/event/${id}`);
}
}
In your component subscribe to Observable<Ievent> to get instance of Ievent
onclickeventpage(){
this.authService.displayEvent$('5ae0c8e96b40a71cd3b772cc').subscribe(event => {
console.log(event);
console.log(event.eventname)});
}

HTTP Native Plugin (IONIC 3)

I'm trying to make a post request using the HTTP cordova plugin. However, for some reason, the JSON data consumed by the Server side is not being formatted correctly (json brakets). Could anyone help me please?
The import:
import { HTTP } from '#ionic-native/http';
The request implementation:
public sendData(sufix, json) {
return new Promise((resolve, reject) => {
this.http.post(URL+sufix, JSON.stringify(json), {'Content-Type': 'application/json'}).then(result => {
resolve(result.data);
}).catch(error => {
reject(error);
});
});
}
The json sended:
{name: 'Test'}
The content received by the server:
=%7B%22name%22%3A%22Test%22%7D
The server implementation:
#Path("/register")
public class RegisterEndPoint {
#POST
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public Response registerUser(UserDTO userDTO) {
// Create DAO for persistence
FactoryDAO factory = new FactoryDAO();
UserDAO userDAO = factory.getUserDAO();
// Create user to be persisted
if (!userDAO.userExist(userDTO.getEmail())) {
User user = new User();
user.setPassword(userDTO.getPassword());
user.setEmail(userDTO.getEmail());
user.setName(userDTO.getName());
userDAO.persist(user);
userDAO.commit();
return Response.status(200).build();
}
return Response.status(405).entity(new ErrorDTO("User already registered!")).build();
}
}
The problem seems to be in Native Plugin, so I've changed to the angular http solution, and it works fine. Follow below the solution which I've perform. Thanks everyone who helped me.
The imports required:
import { Http, Headers, RequestOptions, Response } from '#angular/http';
import { Observable } from 'rxjs/Rx'
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/timeout';
AuthProvider:
public sendRequest(sufix, json) {
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
return this.http.post(URL+sufix, json, options)
.timeout(TIMEOUT_REQUEST*1000)
.do(this.logResponse)
.map(this.extractData)
.catch(this.handleError)
}
private logResponse(res: Response) {
console.log(res);
}
private extractData(res: Response) {
return res.json();
}
private handleError(res: Response | any) {
return Observable.throw(res.json().error || 'Fail to connect to the server');
}
Calling the AuthProvider:
this.authProvider.sendRequest('register', this.signup).subscribe((data) => {
console.log('Success!');
}, (error) => {
console.log(error);
});
Providers included in app.module.ts
import { HttpModule, JsonpModule } from '#angular/http';
can you please try sending the body without making it a string. you can send the JSON Object without stringify. Give it a try :)
**UPDATE
After sending this
{name: 'Test'}
If you are getting name = "test"
Why dont you try like this
var data = JSON.stringify(data);
var obj = {data:data};
//send the obj Object
So it will show as data = "{name:test}"
Now Parse it from the server. Try and let me know :)
if you are trying to make post request using HTTP then try sending request in this format.
let body = new FormData();
body.append('name', 'Test');
this.http.post(<url>,body);
Try and lemme know if it works for you.
Just add this.http.setDataSerializer(‘json’) before do the post