Passing API data from one page to another in ionic 3 - ionic-framework

Let's say I have something like this:
this.http.post('http://edomonitor.com/school-evaluation-api/retrieve_data.php',data, options)
.map(res => res.json())
.subscribe(res => {
loader.dismiss()
this.items=res.server_response;
console.log(this.items);
});
How can I pass the call data across all pages?

You have to make a dictionary object like this
savePedoData() {
let data = {
steps: this.count
};
this.navCtrl.push(PAGE_NAME, data);
}
and In second page
steps = this.navParams.get("steps");
console.log(steps);
you can find your data into the log

Related

Pass Parameters Besides URL in Next JS in Client Side API Fetch

I've been working on calling an internal GetCompanies API through the website client side.
So far I made attempts like this based on search results and documentation
// const fetcher = (includeFiles, folderLocation, SharePointCreds) => fetch(includeFiles, folderLocation, SharePointCreds).then(res => res.json());
// const { data, error } = useSWR('http://localhost:55419/api/SharePoint/GetCompanies', fetcher);
// if (error) return <div>failed to load</div>
// if (!data) return <div>loading...</div>
// render data
//return <div>hello {data}!</div>
useEffect((includeFiles, folderLocation, SharePointCreds) => {
fetch('http://localhost:55419/api/SharePoint/GetCompanies', includeFiles, folderLocation, { method: "POST", body: SharePointCreds})
.then((res) => res.json())
.then((data) => {
console.log("data is ", data)
})
}, [])
if (isLoading) return <p>Loading...</p>
// async function GetCompanies(includeFiles, folderLocation, SharePointCreds){
// const res = await fetch('http://localhost:55419/api/SharePoint/GetCompanies');
// const companies = await res.json();
// }
// return (
// <div>
// <p>{data}</p>
// </div>
// )
corresponding to an API call which works when we test it in Swagger
And I got generic error messages like TypeError: Failed to fetch
I guess the error is in how I pass in includeFiles and folderLocation since I haven't yet found documentation or search results for how to pass in parameters besides the URL, though I could be wrong.
I define all the arguments earlier in the portfolio component for now.
Do you see how else I should pass in includeFiles and folderLocation?
Also, please be kind because I'm learning and doing my best and I've worked on this for a few hours already.

Rx.Net - Publish method missing first few items when subscribing to Cold Observable

Inspired by Akavache I am trying to create a solution that provides me with an IObservable<IArticle>. The method essentially first try to get all the articles that are present in the database, then it tries to fetch updated articles from the webservice and as it is getting the latest articles from webservice it tries to save them back to the database.
Since the webservice is essentially a cold observable and I don't want to subscribe twice, I used Publish to connect to it. My understanding is that I am using the correct version of the Publish method, however, many times the method tend to miss first couple of Articles from the GetNewsArticles. This was observed through the UI and also the Trace calls added in the call below.
Apart from solving the problem, it would be great to also understand how to debug/test this code (apart from introducing DI to inject NewsService).
public IObservable<IArticle> GetContents(string newsUrl, IScheduler scheduler)
{
var newsService = new NewsService(new HttpClient());
scheduler = scheduler ?? TaskPoolScheduler.Default;
var fetchObject = newsService
.GetNewsArticles(newsUrl,scheduler)
.Do(x => Trace.WriteLine($"Parsing Articles {x.Title}"));
return fetchObject.Publish(fetchSubject =>
{
var updateObs = fetchSubject
.Do( x =>
{
// Save to database, all sync calls
})
.Where(x => false)
.Catch(Observable.Empty<Article>());
var dbArticleObs = Observable.Create<IArticle>(o =>
{
return scheduler.ScheduleAsync(async (ctrl, ct) =>
{
using (var session = dataBase.GetSession())
{
var articles = await session.GetArticlesAsync(newsUrl, ct);
foreach (var article in articles)
{
o.OnNext(article);
}
}
o.OnCompleted();
});
});
return
dbArticleObs // First get all the articles from dataBase cache
.Concat(fetchSubject // Get the latest articles from web service
.Catch(Observable.Empty<Article>())
.Merge(updateObs)) // Update the database with latest articles
.Do(x => Trace.WriteLine($"Displaying {x.Title}"));
});
}
UPDATE - Added GetArticles
public IObservable<IContent> GetArticles(string feedUrl, IScheduler scheduler)
{
return Observable.Create<IContent>(o =>
{
scheduler = scheduler ?? DefaultScheduler.Instance;
scheduler.ScheduleAsync(async (ctrl, ct) =>
{
try
{
using (var inputStream = await Client.GetStreamAsync(feedUrl))
{
var settings = new XmlReaderSettings
{
IgnoreComments = true,
IgnoreProcessingInstructions = true,
IgnoreWhitespace = true,
Async = true
};
//var parsingState = ParsingState.Channel;
Article article = null;
Feed feed = null;
using (var reader = XmlReader.Create(inputStream, settings))
{
while (await reader.ReadAsync())
{
ct.ThrowIfCancellationRequested();
if (reader.IsStartElement())
{
switch (reader.LocalName)
{
...
// parsing logic goes here
...
}
}
else if (reader.LocalName == "item" &&
reader.NodeType == XmlNodeType.EndElement)
{
o.OnNext(article);
}
}
}
o.OnCompleted();
}
}
catch (Exception e)
{
o.OnError(e);
}
});
return Disposable.Empty;
});
}
UPDATE 2
Sharing the link to source code here.
There's a few things I don't like about your code. I assume NewsService is an IDisposable as it takes an HttpClient (which is disposable). You're not doing a proper clean up.
Also, you haven't provided a complete method - because you've tried cutting it down for the question - but that makes it hard to reason about how to rewrite the code.
That said, the one thing that sticks out to me as quite horrid looking is the Observable.Create. Can you please try this code instead and see if it helps things work for you?
var dbArticleObs =
Observable
.Using(
() => dataBase.GetSession(),
session =>
from articles in Observable.FromAsync(ct => session.GetArticlesAsync(newsUrl, ct))
from article in articles
select article);
Now, if that does, try rewriting fetchObject to use the same Observable.Using when newing up the `NewService.
In any case, it would be good if you could provide a complete implementation of GetContents, NewsService and your dataBase code in your question.

Url as req.params in Express

I'd like to use express and mongo DB to find a document based off of a URL.
My Schema includes
bandUrl: {
type: String
}
This is my Rout inside of the Express server.
// Get Single Band By bandUrl
router.get('/bandUrl/:url', (req, res) => {
quoteGenerator.find({bandUrl: req.params.url}).then(gen => res.json(gen))
})
I set one of the documents to have bandUrl as 'http://localhost:3000/'.
I tested the route using something other than a URL - just using a string works fine... I'd really like to use the URL though. Is there a way to do this?
Here is my fake/test route form the application..
const getFakeInfo = async () => {
try {
const response = await fetch(`/api/autoquotegenerators/bandUrl/http://localhost:3000/"`, {
method: 'GET',
})
const responseData = await response.json()
console.log(responseData)
} catch (error) {
console.log(error)
}
}
I am thinking the extra slashes in the URL are whats causing the issue.
Thanks for your help!
What you want to you use is encodeURIComponent(). This function escapes all URI specific characters, so they get interpreted properly. Your request code should look something like this:
const response = await fetch(`/api/autoquotegenerators/bandUrl/${encodeURIComponent("http://localhost:3000/")}`, {
method: 'GET',
})
If you want to learn more about this function, you can have a look over here.

display single record by id with vue js and axios

I have a mongodb express vue js app that displays a list of items in cards which are links to a detail view of each record. If I hover over the card the correct id for the link displays but click any card and it goes to the first document from mongo and the record does not display. The view retrieves an item but always the first one.
How to display a record of the ID of item clicked?
Report.vue
the backend request which works in postman is
// Get Simgle Report
router.get('/:id', async (req, res) => {
const reports = await loadReportsCollection()
await reports.findOne({_id: new mongodb.ObjectID( req.params.id)})
res.send(await reports.find({}).limit(1).toArray())
res.status(200).send()
}
)
ReportService.js looks like
//Find Single Report
static getReport(id) {
return axios.get(`${url}${id}`)
}
and the Report.vue file looks like
mounted () {
this.getReport()
},
methods: {
async getReport() {
try {
const response = await ReportService.getReport(this.$route.params.id)
this.report = response.data
} catch(err) {
this.err = err.message
}
},
}
many thanks for help!
It would seem you are trying to access a param in your api without passing one in your request. You ask for params here:
await reports.findOne({_id: new mongodb.ObjectID( req.params.id)})
but haven't passed any in your request. This should do it:
return axios.get('/:id', {
params: {
id: `${id}`
}
})
To not only get the first entry, but the one you are looking for you need to change your send() parameter.
Here is the working code:
// Get Simgle Report
router.get('/:id', async (req, res) => {
const reports = await loadReportsCollection()
const report = await reports.findOne({_id: new mongodb.ObjectID(req.params.id)})
res.send(await report)
res.status(200).send()
}
)
And as Andrew1325 stated you need to change your axios.get() call also to pass the correct params to it.

Pg-promise - How to stream binary data directly to response

Forgive me I'm still learning. I'm trying to download some mp3 files that I have stored in a table. I can download files directly from the file system like this:
if (fs.existsSync(filename)) {
res.setHeader('Content-disposition', 'attachment; filename=' + filename);
res.setHeader('Content-Type', 'application/audio/mpeg3');
var rstream = fs.createReadStream(filename);
rstream.pipe(res);
I have stored the data in the table using pg-promise example in the docs like so:
const rs = fs.createReadStream(filename);
function receiver(_, data) {
function source(index) {
if (index < data.length) {
return data[index];
}
}
function dest(index, data) {
return this.none('INSERT INTO test_bin (utterance) VALUES($1)', data);
}
return this.sequence(source, {dest});
} // end receiver func
rep.tx(t => {
return streamRead.call(t, rs, receiver);
})
.then(data => {
console.log('DATA:', data);
})
.catch(error => {
console.log('ERROR: ', error);
});
But now I want to take that data out of the table and download it to the client. The example in the docs of taking data out of binary converts it to JSON and then prints it to the console like this:
db.stream(qs, s => {
s.pipe(JSONStream.stringify()).pipe(process.stdout)
})
and that works. So the data is coming out of the database ok. But I can't seem to send it to the client. It seems that the data is already a stream so I have tried:
db.stream(qs, s => {
s.pipe(res);
});
But I get a typeerror: First argument must be a string or Buffer
Alternatively, I could take that stream and write it to the file system, and then serve it as in the top step above, but that seems like a workaround. I wish there was an example of how to save to a file in the docs.
What step am I missing?