I'm using the following plugin https://github.com/EddyVerbruggen/nativescript-plugin-firebase allowing to access Firebase from Nativescript applicaiton.
For some reasons, when I do a query request to get my objects, some properties of the json objects are missed.
Below the query :
return firebase.query(
data => {
if(data.value) {
Object.keys(data.value).forEach(key => {
this.results.push(data.value[key]); // Here I dont get exactly the JSON, some properties disapears.....
}
}
}, "/ads/",
{ orderBy: { type: firebase.QueryOrderByType.KEY }})
.then(result => { return result; })
);
My database
Properties of type number are not loaded (totalProduct and state).
Regards
I find out that your forEach miss a ')'.
After modified, everything is fine. All of the JSON properties still exist.
Related
I am using react native and firebase realtime database to store and query a list of properties. It seems that when I run the below query in XCode for iOS the array created here shows a list of the property objects. However, when I run this android studio the array is empty. Do you know what may be causing this? Can someone please help here I am very new to react native and using firebase realtime database?
I really do apologies for the poor code formatting:
const array = []
await db.ref(`users/`).on(`value`, snapshot => {
if (snapshot.exists()) {
snapshot.forEach(function(userSnapshot){
if(userSnapshot.hasChild("properties")){
userSnapshot.child("properties").forEach((propertySnapshot) => {
array.push({
key: userSnapshot.key,
property: propertySnapshot.val(),
username: userSnapshot.val().username,
email: userSnapshot.val().email,
phoneNumber: (userSnapshot.val().phoneNumber != null)?userSnapshot.val().phoneNumber:null,
propertyName: propertySnapshot.key,
profile_pic: userSnapshot.val().profile_pic,
connectedAccount_id: (userSnapshot.val().connectedAccount_id != null)?userSnapshot.val().connectedAccount_id:null,
customer: (userSnapshot.val().customer != null)?userSnapshot.val().customer:null,
});
})
}
})
}
});
await database().ref(`users/${auth().currentUser.uid}/your_location`).once(`value`, function(snap){
....
Geocoder.init("******");
Geocoder.from(locationPostcode)
.then(json => {
var location = json.results[0].geometry.location;
global.latitude = location.lat;
global.longtitude = location.lng;
})
.catch(error => console.warn(error));
console.log("array result "+array)
.....
})
The log array shows an array of objects for iOS:
array result [object Object],[object Object],[object Object],[object Object],[object Object]
but for android it's empty:
array result
I have this function signature on schema.graphql, can I used it in order to call to lambda function that retrieve user list from Cognito server?
type Query
{
echo(msg: String): String #function(name: "getUsers-${env}")
}
How can I call it from Android ?
Do I need Apollo ?
Does Amplify library it's enough ?
Basically you can't query users from Cognito Amazon server directly using the schema.
In the Android application you must create and use the following Amplify plugins, you can read more about it from here:
https://docs.amplify.aws/start/q/integration/android
You must create lambda function as describe here:
const AWS = require('aws-sdk');
const cognito = new AWS.CognitoIdentityServiceProvider({apiVersion: '2016-04-18', region: 'eu-central-1'});
exports.handler = async (event) => {
// TODO implement
let users = [];
let roles = ['admin', 'user' ];
try
{
// (let i=0, len=roles.length; i<len; i++)
//{
//const role = roles[i];
let more = true;
let nextToken = '';
while (more)
{
let params = {
UserPoolId: "your pool id",
//GroupName: role,
Limit: 60
};
if (nextToken !== '')
{
params.NextToken = nextToken;
}
const rawUsers = await cognito.listUsers(params).promise();
const mapUsers = rawUsers.Users.map(user => {
let atts = {};
for (const att of user.Attributes)
{
atts[att.Name] = att.Value;
}
return {
username: user.Username,
name: atts.hasOwnProperty('name') ? atts.name : '',
email: atts.hasOwnProperty('email') ? atts.email : '',
status: user.UserStatus,
//role: role
};
});
users= users.concat(mapUsers);
if (rawUsers.hasOwnProperty('NextToken')) {
nextToken = rawUsers.NextToken;
} else {
more = false;
}
}
// }
const response = {
statusCode: 200,
// Uncomment below to enable CORS requests
// headers: {
// "Access-Control-Allow-Origin": "*"
// },
body: JSON.stringify(users),
};
return response;
}
catch(e)
{
const response = {
statusCode: 500,
// Uncomment below to enable CORS requests
// headers: {
// "Access-Control-Allow-Origin": "*"
// },
body: e,
};
return response;
}
};
Then create REST api:
Use the terminal Amplify CLI commands and connect it to the lambda function that was created including "Authenticated users only".
Run:
amplify add api
C:\DOV_AWS>amplify api add
? Please select from one of the below mentioned services: REST
? Provide a friendly name for your resource to be used as a label for this category in the
project: users
? Provide a path (e.g., /book/{isbn}):
C:\DOV_AWS>amplify api add
? Please select from one of the below mentioned services: REST
? Provide a friendly name for your resource to be used as a label for this category in the
project: DOV
? Provide a path (e.g., /book/{isbn}): /users
? Choose a Lambda source Use a Lambda function already added in the current Amplify projec
t
? Choose the Lambda function to invoke by this path getUsers
? Restrict API access Yes
? Who should have access? Authenticated users only
? What kind of access do you want for Authenticated users? create, read, update, delete
? Do you want to add another path? No
Successfully added resource DOV locally
Use the amplify push command:
amplify push
In order to update the API on the cloud.
Run the following code in your app in order to fetch the users.
RestOptions options = RestOptions.builder()
.addPath("/users")
.build();
Amplify.API.get("Users", options, response ->
Log.i("MyAmplifyApp", " ! ! ! ! ! Data Respond ! ! ! ! !"
+ response.getData().asString()),
error -> Log.e("MyAmplifyApp", "GET failed", error)
);
You must add permission rule for Cognito server in the lambda function in order to fetch the user data.
The authentication method will include IAM rule
I am exporting JSON by fetch from the URL. I think I have a binding issue if take from local data file working I'm not completely sure on how I should proceed to bind my function.
Data.js
const Json = require('./one.js'); // not working or const Json = require('./two.json'); // working
export default Json;
one.js
function getvals(){
return fetch('http://xxxxxx')
.then((response) => response.json())
.then((json) => {
return json.products;
})
.catch((error) => {
console.error(error);
});
}
getvals().then(response => response);
two.json
[{"id":"1","category":"kkk","title":"sss"}]
Nothing in one.js exports anything. With CommonJS-style modules, you export something by assigning it to a property on exports (or by reassigning the exports variable entirely).
But note that since what you're getting is only available asynchronously, other modules may request one.js's default export before the asynchronous process has completed. The usual solution to that is export the promise from fetch:
module.exports = fetch('http://xxxxxx')
.then((response) => {
if (!response.ok) {
throw new Error("HTTP error " + response.status);
}
return response.json();
})
.then((data) => {
return data.products;
});
Also note that you need to check for HTTP success (the footgun in the fetch API) and you don't want to hide errors; let the users of the module know if the fetch fails.
Code using that would need to use the promise, e.g.:
require("./one.js")
.then(data => {
// ...use the products...
})
.catch(error => {
// ...handle the fact the fetch failed and the data won't be coming...
});
I don't know the React Native ecosystem, but if you can to switch to JavaScript modules ("ESM" = ECMAScript Modules) instead (and if you want to), someday you'd be able to use a new feature called top-level await. The V8 engine has it (behind a flag), presumably JavaScriptCore will at some stage. That would let you suspend module evaluation until the fetch completed, and directly export the result:
// With top-level `await` in an ESM module
export default await fetch('http://xxxxxx')
.then((response) => {
if (!response.ok) {
throw new Error("HTTP error " + response.status);
}
return response.json();
})
.then((data) => {
return data.products;
});
Modules using it would be able to get the products directly:
import products from "./one.js";
If you're using Webpack (again, I don't know the React Native ecosystem), it has experimental support for it, too.
I got this data in my document:
I want to delete index 0. How do I do this? This should do the trick I thought:
db.collection("data").document("free").updateData(["deleteme.deletemee.0" : FieldValue.delete()]) { (errr) in
print(errr)
}
But the errr prints nil, and nothing is removed. When getting the document I noticed something strange about the data when using this code:
db.collection("data").document("free").getDocument { (doc, err) in
guard let _doc = doc,
doc?.exists ?? false else{ return }
print(_doc.data())
}
This prints out:
["deleteme": {
deletemee = (
1 //this is the value for the key, but where is my key?! :(
);
}]
I cannot see the key, where is it? How to delete something at an index in Firestore? Thanks.
Array operations have finally been supported. Deletion, addition, etc. are supported via the value (not the index) now:
At the moment, there are a few bugs at the moment though as this one I encountered.
The dev blog here:
It is not currently possible to modify individual elements of an array stored in Cloud Firestore.
If you stored the data as a map (the keys dont matter) like this:
{
name: "sam",
things: {
one: "value",
two: "value"
}
}
Then you can delete individual elements like this:
// Delete the things.one data
db.collection("whatever").document("whatever").updateData([
"things.one": FieldValue.delete(),
]) { err in
if let err = err {
print("Error updating document: \(err)")
} else {
print("Document successfully updated")
}
}
Now the data will look like this:
{
name: "sam",
things: {
two: "value"
}
}
export const deleteArrayIndex = (collectionName, id, index) => {
db.collection(collectionName).doc(id).update(
{ [index]: firebase.firestore.FieldValue.delete() }
).then(function () {
console.log(index + " is deleted");
}).catch(function (error) {
console.error("Error removing document: ", error);
});
}
I am making an app in ionic 3 and I am trying to fetch data from an url.
This is my code in data.ts and my data provider:
getVehicleStatus() {
return this.http.get<VehicleStatus>(this.url);
}
This is my vehicle class:
class VehicleStatus {
status: string;
plate: string;
code: string;
message: string;
}
I am calling the method into my home.ts file.
ionViewDidLoad() {
console.log(this.getStatus('test3'));
}
getStatus(plate: string) {
this.dataService.getVehicleStatus()
.subscribe((data: VehicleStatus) => this.vehiclestatus = [{ ...data }]);
}
To test out if everything works I hard code a license plate number to log it into my chrome developer tools. It said 'Undefined'.
This is how the json data looks like:
[{"status":"P","plate":"test2","code:"MGP150151","message":"fail"}
,{"status":"P","plate":"test3","code":"MGP160298","message":"fail"}
,{"status":"P","plate":"test4","code":"MGP140085","message":"succes"}
,{"status":"O","plate":"test5","code":"MGP150175","message":"succes"}]
I should get this object back:
{"status":"P","plate":"test3","code":"MGP160298","message":"fail"}
But it doesn't work and got the message undefined.
I have used the following source:
https://angular.io/guide/http
How can I search in the array and bind it to my HTML page in ionic 3?.
Can someone point me in the right direction?.
Kind regards .
The responsibility to find the VehicleStatus from the list should be of the service rather than of the Component itself.
Consider changing your Service Implementation to take up that responsibility. You can use the map operator to transform the response to return the VehicleStatus found based on the plate that will be passed as an arg while calling the getVehicleStatus method.
import { map } from 'rxjs/operators';
import { Observable } from 'rxjs';
getVehicleStatus(plate): Observable<VehicleStatus> {
return this.http.get<VehicleStatus[]>(this.url)
.pipe(
map(statuses => statuses.find(status => status.plate === plate))
);
}
Then in your home.ts:
ionViewDidLoad() {
this.getStatus('test3');
}
getStatus(plate: string) {
this.dataService.getVehicleStatus(plate)
.subscribe((data: VehicleStatus) => this.vehiclestatus = data);
}
You need array.find to get the matching value, which will return the first matching element from the array
this.vehiclestatus = data.find(vehicle=>vehicle.plate === plate);