I'm using the cordova in-app-browser plugin. One Page I get back is just a bunch of JSON-Data which i want to store inside my IONIC 5 Project. I could'nt figure out yet how to receive the Data and transfer it to the App yet with the Plugin. Is there such a possibility?
Thank you
To transfer data using InAppBrowser you can pass It by parameters, and also to receive the date you get it from parameters. Follows a small example:
Short way sending data on Page1.ts:
const dataToSend = `/${this.dataOne}/${this.dataTwo}`;
let finalUrl = `https://app-example.io` + dataToSend;
this.inAppB.create(finalUrl, '_system');
Receiving data on Page2.ts:
import { ActivatedRoute } from '#angular/router';
constructor(
private actRoute: ActivatedRoute
){}
ngOnInit() {
this.actRoute.paramMap.subscribe( params => {
console.log('Params => ', params);
if (params) {
let dataReceived = [params['params']['dataOne'], params['params']['dataTwo']];
console.log('dataReceived => ', dataReceived);
}
}
}
Please, adapt it to your code and variables as it is just a short example.
Related
I am getting two reactive variables I need from a store to use for my fetch calls. I need these fetch calls to rerun when the data in these store values change. I am able to make this work however when I reload the page it causes my app to crash because there are no values that are getting from the store. I am able to make it work if I disable ssr on the +page.js file.
I also believe it is relevant to mention that I am using a relative URL (/api) to make the fetch call because I have a proxy server to bypass CORS
What is the proper way to get this data by rerunning the fetch calls using a reactive component from a store without disabling ssr? Or is this the best/only solution?
+page.svelte
<script>
import { dateStore, shiftStore } from '../../../lib/store';
$: shift = $shiftStore
$: date = $dateStore
/**
* #type {any[]}
*/
export let comments = []
/**
* #type {any[]}
*/
let areas = []
//console.log(date)
async function getComments() {
const response = await fetch(`/api/${date.toISOString().split('T')[0]}/${shift}/1`)
comments = await response.json()
console.log(comments)
}
async function getAreas() {
const response = await fetch(`/api/api/TurnReportArea/1/${date.toISOString().split('T')[0]}/${shift}`)
areas = await response.json()
console.log(areas)
}
// both of these call function if date or shift value changes
$: date && shift && getAreas()
$: date , shift , getComments()
</script>
I tried to use the +page.js file for my fetch calls, however I cannot use the reactive values in the store in the +page.js file. Below the date variable is set as a 'Writble(Date)' When I try to add the $ in front of the value let dare = $dateStore, I get the error 'Cannot find name '$dateSrote'' If i put the $ in the fetch call I get the error 'Cannot find $date'. Even if I were able to make this work, I do not understand how my page would know to rerender if these fetch calls were ran so I do not think this is the solution. As I mentioned, the only solution I have found is to disable ssr on the +page.js, which I do not think is the best way to fix this issue.
import { dateStore, shiftStore } from "../../../lib/store"
export const load = async ({ }) => {
let shift = shiftStore
let date = dateStore
const getComments = async() => {
const commentRes = await fetch(`/api/${date.toISOString().split('T')[0]}/${shift}/1`)
const comments = await commentRes.json()
console.log(comments)
}
const getAreas = async () => {
const areasRes = await fetch(`/api/api/TurnReportArea/1/${date.toISOString().split('T')[0]}/${shift}`)
const areas = await areasRes.json()
console.log(areas)
}
return {
comments: getComments(),
areas: getAreas()
}
}
I am following this tutorials: https://github.com/adobe/aem-sample-we-retail-journal
Here, all the child pages JSON is stored into INITIAL_STATE id.
https://github.com/adobe/aem-sample-we-retail-journal/blob/master/react-app/src/index.js#L34
document.addEventListener('DOMContentLoaded', () => {
let jsonScript = document.getElementById("__INITIAL_STATE__");
let initialState = null;
if (jsonScript) {
initialState = JSON.parse(jsonScript.innerText);
// Remove the script element from the DOM
jsonScript.remove();
}
I want to know why it is done in this way, can someone please explain?
Instead what if I navigate on different links and then on click of each links if I call model json of that page via Async fetch and then accordingly set INITIAL_STATE id. What problem in this approach?
I m trying to use back4app for push notification. For this I have installed back4app's ionic sdk (https://www.back4app.com/docs/ionic/parse-ionic-sdk) like this
npm install parse
then in my app.component.ts I imported parse
import Parse from 'parse';
and in platform ready
Parse.serverURL = "https://parseapi.back4app.com/";
Parse.initialize("APP_ID_HERE", "JAVASCRIPT_KEY"); //I have used real keys from back4app dashboard.
let install = new Parse.Installation();
install.save(null, {
success: (install) => {
// Execute any logic that should take place after the object is saved.
// console.clear();
console.error('New object created with objectId: ' + install.id);
},
error: (install, error) => {
// Execute any logic that should take place if the save fails.
// error is a Parse.Error with an error code and message.
//console.clear();
console.error('Failed to create new object, with error code:' + error.message.toString());
}
});
When I do Ionic serve or test it in device, it should register device/installation id to their backend but it gives 400 Bad Request error on https://parseapi.back4app.com/classes/_Installation the error was -
{"code":135,"error":"deviceType must be specified in this operation"}
I m not sure where to mention deviceType as their documentation doesn't seem that good.
Can anybody help me on this??
This is not mentioned in their documentation but I have found it in one of their example.
Replacing -
let install = new Parse.Installation();
with
let install = new Parse.Installation();
install.set("deviceType", platform.platforms().toString());
Solved the issue.
Here is the link to their repository
Parse SDK now supports Promises.
I'd recommend using it instead of passing in callbacks.
You can accomplish that by:
install.save().then(() => {
// success
}, err => {
// error
})
I am creating a chat page in my ionic application and I would like to know when the get request changes. I am also OK with doing this all off of an interval, but I can’t find a good example on how to do it. I would prefer to not have to have the user refresh the page to see if a new chat message has appeared. I am newer to observables and have not seen this done with the remote data source and the HTTP package. My data is already JSON so that's why it's not mentioned at all. Thanks!
Chat.ts
import { Component, ViewChild ,ElementRef} from '#angular/core';
import { IonicPage, NavController, NavParams, Events, Content } from 'ionic-angular';
import { ChatProvider } from "../../../../../providers/chat/chat";
import { Observable } from "rxjs/Observable";
export class ChatShowPage {
public id:string;
public items: Observable<ChatMessage[]> = [];
constructor(navParams: NavParams, private chatService: ChatProvider, private events: Events,) {
this.id = navParams.get('id_convo');
}
getMsg() {
return this.chatService.getMsgList(this.id).subscribe(res => {
this.items=res;
console.log(this.items);
});
}
}
Provider.ts
getMsgList(id): Observable<ChatMessage[]> {
const msgListUrl = this.base_url + 'user/account/chat/show/' + id;
console.log('getMsgList - ' + msgListUrl);
return this.http.get<any>(msgListUrl,
{headers: new HttpHeaders({'Content': 'application/json','Accept': 'application/json','Authorization': 'Bearer ' + localStorage.getItem('tk') })});
}
You want to use Events to update your component
In this particular example, you could use:
ionViewWillLeave() {
// unsubscribe
this.events.unsubscribe('chat:received');
}
ionViewDidEnter() {
//get message list
this.getMsg();
// Subscribe to received new message events
this.events.subscribe('chat:received', msg => {
this.pushNewMsg(msg);
})
}
In your provider.ts your getMsgList function should emit the chat:received event as such:
this.events.publish('chat:received')
Then in your pushNewMsg function, you would do some safety checks and then push the new message into the array which you can display with an *ngFor directive.
There are two famous ways to make chat module via web(including ionic).
Polling
WebSocket (Event-driven)
Polling
: If you make simple or personal chat application and want to keep current code structure, then you'd better use polling pattern which merely repeat request with some interval. In addition, for better polling, please consider HTTP Long Polling
setTimeout() with recursion or setInterval() can be options.
WebSocket (Event-driven)
: If you make commercial application or application with lots of users, then you have to use Event-driven pattern. For using this pattern, both of server-side work and client-side work are needed. If you use node.js as server-side framework, then I recommend to use Socket.IO.
I am currently building an application with Ionic 2 and using the Storage plugin to hold my values which are pretty much just an API Token and user profile since the application pulls all data from an API.
I am testing the application via ionic serve because no native functions are used but now I am facing the problem that every time I store a value in the Storage the value is not accessible until I reload the app which is kind of annoying because after the user logs in he gets redirected to a page that requires the API token which is not available until I reload the app so the whole thing gets stuck in a loop.
Ionic Storage is using IndexedDB in the browser where I can see that the values have been stored when I check them with Chrome Developer tools.
I have been trying to figure out the issue but can't find any reason why the storage values are not available until reloading the app.
import { Injectable } from '#angular/core';
import { Storage } from '#ionic/storage';
import { HttpClientService } from './http-client-service';
import 'rxjs/add/operator/map';
#Injectable()
export class AuthService {
constructor(public events: Events, public storage: Storage, public http: HttpClientService) {
//
}
login(user) {
var response = this.http.post('login', {
email: user.email,
password: user.password,
});
response.subscribe(data => {
this.storage.set('api_token', data.token);
console.log('raw : ' + data.token); // shows the api token
this.storage.get('api_token').then((value) => {
console.log('storage : '+ value); // is empty...
});
});
return response;
};
}
Edit: I managed to track down the issue to the storage running async which results in the token not being added to the headers.
createAuthorizationHeader(headers: Headers) {
// this does add the header in time
localStorage.setItem('api_token', 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOi8vYXBpLndpaHplLmRldi9sb2dpbiIsImlhdCI6MTQ4MTE4MzQyOCwiZXhwIjoxNDgxMTg3MDI4LCJuYmYiOjE0ODExODM0MjgsImp0aSI6IjdlNTE1WUEwWmE4NWc2QjUiLCJzdWIiOiIxIiwidXNlciI6eyJpZCI6MX19.T4KpqgCB8xU79vKyeLG4CJ0OHLpVI0j37JKIBJ_0CC4');
headers.append('Authorization', 'Bearer ' + localStorage.getItem('api_token'));
// this does not add the header in time
return this.storage.get('api_token').then((value) => {
headers.append('Authorization', 'Bearer ' + value);
});
}
getHeaders(path) {
let headers = new Headers();
headers.set('Accept', 'application/json');
headers.set('Content-Type', 'application/json');
if(!this.isGuestRoute(path)) {
this.createAuthorizationHeader(headers);
}
return new RequestOptions({ headers: headers });
}
get(path: string) {
return this._http.get(this.actionUrl + path, this.getHeaders(path))
.map(res => res.json())
.catch(this.handleError);
}
Alright, looked in the ionic docs and I do understand why you put them both underneath eachother since they also display it like that in the docs.
But Storage.set(key, value) :
Returns:
Promise that resolves when the value is set
This means that you cannot use it the way you are using it (hence why they added a comment with //or ....
Since resolving a Promise is asynchronous.
If you want to use the value like you're currently using it (which seems a bit odd but probably for you to test if the value is set correctly) you should use
this.storage.set('api_token', data.token).then(() => {
this.storage.get('api_token').then((value) => {
console.log('storage : '+ value); // is empty...
});
});
console.log('raw : ' + data.token); // shows the api token
If you would like some more information about why this happens, check out this SO answer (I prefer second one) Asynchronous vs synchronous execution, what does it really mean?