How to destruct a complex object - react-native

One of my functions returns the object below:
Promise {
{
user: {
name: 'Ervin Howell',
email: 'Shanna#melissa.tv',
type: 'authenticated'
}
}
}
How to destruct user object from this json?

hi you can read the JSON API in this site. it has two methods:JSON.parse and JSON.sringify.
for your situation, you can use JSON.parse if your function return a JSON string
let json = "{
user: {
name: 'Ervin Howell',
email: 'Shanna#melissa.tv',
type: 'authenticated'
}
}
}"
obj = JSON.parse(json);
// when you want the user object
let user = obj.user
// when you want the user's name
let name = user.name

Related

Strapi graphql mutation Syntax Error: Unterminated string

I always get Syntax Error: Unterminated string when I try to update my database using javascript strapi sdk. this.chapter.content is a html string generated by ckeditor. How can I escape this string to update my database using graphql?
async updateChapter() {
const q = `
mutation {
updateChapter(input: {
where: {
id: "${this.$route.params.chapterId}"
},
data: {
content: "${this.chapter.content.replace(/[.*+?^${}()|[\]\\]/g, '\\$&').replace(/(?:\r\n|\r|\n)/g, '\n')}"
title: "${this.chapter.title}"
}
}) {
chapter{
title
id
content
}
}
}
`;
const res = await strapi.request("post", "/graphql", {
data: {
query: q
}
});
this.chapter = res.data.chapter;
}
Technically you could use block string notation to get around this issue. However, you really should supply dynamic input values using variables instead of string interpolation. This way you can easily provide any of sort of values (strings, numbers, objects, etc.) and GraphQL will parse them accordingly -- including strings with line breaks.
const query = `
mutation MyMutation ($chapterId: ID!, $content: String!, $title: String!) {
updateChapter(input: {
where: {
id: $chapterId
},
data: {
content: $content
title: $title
}
}) {
chapter{
title
id
content
}
}
}
`
const variables = {
chapterId: '...',
content: '...',
title: '...',
}
const res = await strapi.request("post", "/graphql", {
data: {
query,
variables,
},
})
Note that $chapterId may need to be of the type String! instead if that's what's called for in the schema. Since variables can also be input object types, instead of providing 3 different variables, you could also provide a single variable to be passed to the input argument instead:
const query = `
mutation MyMutation ($input: SomeInputObjectTypeHere!) {
updateChapter(input: $input) {
chapter{
title
id
content
}
}
}
`
const variables = {
input: {
where: {
id: '...',
},
data: {
content: '...',
title: '...',
},
},
}
Again, just replace SomeInputObjectTypeHere with the appropriate type in your schema.
Another solution maybe help
Code with issue: For example mainReason and actionTaken fields are text inputs and data contains some white spaces. This action give error: Unterminated string
mutation { updateApplicationForm(input:{ where:{id:"${ticketData.id}"}
data:{
mainReason: "${ticketData.mainReason}"
actionTaken: "${ticketData.actionTaken}"
appStatus: ${ticketData.appStatus}
action: "${ticketData.action}"
}
Fix this problem with JSON.stringify method
mutation { updateApplicationForm(input:{ where:{id:"${ticketData.id}"}
data:{
mainReason:${JSON.stringify(ticketData.mainReason)}
actionTaken:${JSON.stringify(ticketData.actionTaken)}
appStatus: ${ticketData.appStatus}
action: "${ticketData.action}"
}

How do I operate the m.withAttr tutorials code?

A contrived example of bi-directional data binding
var user = {
model: function(name) {
this.name = m.prop(name);
},
controller: function() {
return {user: new user.model("John Doe")};
},
view: function(controller) {
m.render("body", [
m("input", {onchange: m.withAttr("value", controller.user.name), value: controller.user.name()})
]);
}
};
https://lhorie.github.io/mithril/mithril.withAttr.html
I tried the above code does not work nothing.
It was the first to try to append the following.
m.mount(document.body, user);
Uncaught SyntaxError: Unexpected token n
Then I tried to append the following.
var users = m.prop([]);
var error = m.prop("");
m.request({method: "GET", url: "/users/index.php"})
.then(users, error);
▼/users/index.php
<?php
echo '[{name: "John"}, {name: "Mary"}]';
Uncaught SyntaxError: Unexpected token n
How do I operate the m.withAttr tutorials code?
Try returning m('body', [...]) from your controller.
view: function (ctrl) {
return m("body", [
...
]);
}
render should not be used inside of Mithril components (render is only used to mount Mithril components on existing DOM nodes).
The example is difficult to operate because it's contrived, it's not meant to be working out-of-the-box. Here's a slightly modified, working version:
http://jsfiddle.net/ciscoheat/8dwenn02/2/
var user = {
model: function(name) {
this.name = m.prop(name);
},
controller: function() {
return {user: new user.model("John Doe")};
},
view: function(controller) {
return [
m("input", {
oninput: m.withAttr("value", controller.user.name),
value: controller.user.name()
}),
m("h1", controller.user.name())
];
}
};
m.mount(document.body, user);
Changes made:
m.mount injects html inside the element specified as first parameter, so rendering a body element in view will make a body inside a body.
Changed the input field event to oninput for instant feedback, and added a h1 to display the model, so you can see it changing when the input field changes.
Using m.request
Another example how to make an ajax request that displays the retrieved data, as per your modifications:
http://jsfiddle.net/ciscoheat/3senfh9c/
var userList = {
controller: function() {
var users = m.prop([]);
var error = m.prop("");
m.request({
method: "GET",
url: "http://jsonplaceholder.typicode.com/users",
}).then(users, error);
return { users: users, error: error };
},
view: function(controller) {
return [
controller.users().map(function(u) {
return m("div", u.name)
}),
controller.error() ? m(".error", {style: "color:red"}, "Error: " + controller.error()) : null
];
}
};
m.mount(document.body, userList);
The Unexpected token n error can happen if the requested url doesn't return valid JSON, so you need to fix the JSON data in /users/index.php to make it work with your own code. There are no quotes around the name field.

Firebase make user object from auth data

So I'm using Angularfire in an ionic app and trying to figure out how to make a user object that is associated with the auth data from an Auth $createUser call. My first try had the auth call and the user got authenticated, then a user object was made and pushed into a $firebaseArray which works fine, but I don't know how to grab the current user after they are logged in to update, destory, or do anything with that users data. I have made it work with looping through the users array and matching the uid from the user array item and the auth.uid item which was set to be the same in the user array object creation. This seems really ineffecient to loop over if there is a large user array and it needs to be done on multiple pages.
My current attempt is using a different method like so:
angular.module('haulya.main')
.controller('RegisterController', ['Auth', '$scope', 'User', '$ionicPlatform', '$cordovaCamera','CurrentUserService',
function(Auth, $scope, User, $ionicPlatform, $cordovaCamera, CurrentUserService) {
//scope variable for controller
$scope.user = {};
console.log(User);
$scope.createUser = function(isValid) {
var userModel;
$scope.submitted = true;
//messages for successful or failed user creation
$scope.user.message = null;
$scope.user.error = null;
//if form is filled out valid
if(isValid) {
//Create user with email and password firebase Auth method
Auth.$createUser({
email: $scope.user.email,
password: $scope.user.password
})
.then(function(userData) {
userModel = {
uid: userData.uid,
photo: $scope.user.photo || null,
firstName: $scope.user.firstName,
lastName: $scope.user.lastName,
email: $scope.user.email,
cell: $scope.user.cell,
dob: $scope.user.dob.toString(),
city: $scope.user.city,
state: $scope.user.state,
zip: $scope.user.zip
}
// add new user to profiles array
User.create(userModel).then(function(user) {
$scope.sharedUser = User.get(user.path.o[1]);
});
$scope.user.message = "User created for email: " + $scope.user.email;
})
.catch(function(error) {
//set error messages contextually
if(error.code == 'INVALID_EMAIL') {
$scope.user.error = "Invalid Email";
}
else if(error.code == 'EMAIL_TAKEN'){
$scope.user.error = "Email already in use, if you think this is an error contact an administrator";
}
else {
$scope.user.error = "Fill in all required fields";
}
});
}
};
//Get profile pic from camera, or photo library
$scope.getPhoto = function(type) {
$ionicPlatform.ready(function() {
//options for images quality/type/size/dimensions
var options = {
quality: 65,
destinationType: Camera.DestinationType.DATA_URL,
sourceType: Camera.PictureSourceType[type.toUpperCase()],
allowEdit: true,
encodingType: Camera.EncodingType.JPEG,
targetWidth: 100,
targetHeight: 100,
popoverOptions: CameraPopoverOptions,
saveToPhotoAlbum: false
};
//get image function using cordova-plugin-camera
$cordovaCamera.getPicture(options)
.then(function(photo) {
$scope.user.photo = photo;
}, function(err) {
console.log(err);
});
});
};
}]);
And here's the service the controller is using:
angular
.module('haulya.main')
.factory('User', function($firebaseArray) {
var ref = new Firebase('https://haulya.firebaseio.com');
var users = $firebaseArray(ref.child('profiles'));
var User = {
all: users,
create: function(user) {
return users.$add(user);
},
get: function(userId) {
return $firebaseArray(ref.child('profiles').child(userId));
},
delete: function(user) {
return users.$remove(user);
}
};
return User;
});
This also works, but again I don't have a solid reference to the currently logged in users object data from the array. The objects id is only stored on the controllers scope.
I looked through other posts, but they were all using older versions of firebase with deprecated methods.
If you're storing items that have a "natural key", it is best to store them under that key. For users this would be the uid.
So instead of storing them with $add(), store them with child().set().
create: function(user) {
var userRef = users.$ref().child(user.uid);
userRef.set(user);
return $firebaseObject(userRef);
}
You'll note that I'm using non-AngularFire methods child() and set(). AngularFire is built on top of Firebase's regular JavaScript SDK, so they interoperate nicely. The advantage of this is that you can use all the power of the Firebase JavaScript SDK and only use AngularFire for what it's best at: binding things to Angular's $scope.
Storing user data is explained in Firebase's guide for JavaScript. We store them under their uid there too instead of using push(), which is what $add() calls behind the scenes.

How to use jsonschema for Loopback remoteMethod?

In my app I want define JSON schemas for custom API.
For example from: http://docs.strongloop.com/display/public/LB/Remote+methods#Remotemethods-Example
module.exports = function(Person){
Person.greet = function(msg, cb) {
cb(null, 'Greetings... ' + msg);
}
Person.remoteMethod(
'greet',
{
accepts: <generate definitions from jsonschema>,
returns: <generate definitions from jsonschema>
}
);
};
How to do that?
This is right way?
MY SOLUTION - validation decorator + remote method params with object type
var validate = require('jsonschema').validate;
bySchema = function (schema) {
return function (func) {
return function () {
var data = arguments[0],
callback = arguments[1];
var result = validate(data, schema);
if (result.errors.length > 0) {
// some errors in request body
callback(null, {
success: false,
error: 'schema validation error',
});
return;
}
return func.apply(this, arguments);
};
};
};
defaultRemoteArguments = {
accepts: {
arg: 'data',
type: 'object',
http: function(ctx) {
return ctx.req.body;
}
},
returns: {
arg: 'data',
type: 'object',
root: true
}
};
Example:
Auth.login = bySchema(require('<path to shcemajson json for this request>'))
(function(data, cb) {
// process request
});
Auth.remoteMethod('login', defaultRemoteArguments);
In this solution contrib loopback explorer will not be useful, because request/response are objects, not fields...
The correct way to do it is to set the type in the returns attribute to the model name.
In your case you would write:
Person.remoteMethod(
'greet',
{
...
returns: {type:'Person', ...}
}
);
You need to modify your output to match the format accepted by the returns property.
...
returns: [{arg: "key1", type: "string"}, {arg: "key2", type: "object"}, ...];
...

How to manage data template when serving an api using Node.js

I'm currently trying to create an api for my web app using Node.js. The api intended to return JSON data to the api user.
For example, i'm having following endpoint / object:
- Articles (collection of article)
- Article (single article, each article would be having tags)
- Tags
Each endpoint / object having they own json data format need to return, in example:
Articles: [{articleObject}, {articleObject}, {articleObject}]
Article
{
id: 12,
title: 'My awesome article *i said and i know it',
content: 'blah blah blah blah',
tags: [{tagObject}, {tagObject}, {tagObject}]
}
Each endpoint can call to other endpoint to get needed data, in example:
Article endpoint can calling the Tags endpoint to get the article tags collection, the Tags endpoint will be returning Array Object.
My questions:
How to manage the Object structures, so if a endpoint called from another endpoint it will return Array / Object, while it will be return JSON string when called from api user.
Should I create Object template for each endpoint. The process will be:
Endpoint will be calling Object Template;
The Object Template will fetching data from database;
Endpoint will return the Object Template when called from other endpoint;
Endpoint will call template engine to parse the Object Template to JSON string for api user. JSON string view will be provided for each endpoint.
What Template Engine can process below Object Template and treat them as variables, in PHP i'm using Twig that can receive PHP Object and treat them as variables. Here you can find how i do that using Twig
Object Template file content example:
var Tags = require('./tags');
module.exports = function(param){
/* do fetching data from database for specified parameters */
/* here */
var data = {};
return {
id: function() {
return data.id;
},
title: function() {
return data.title;
},
description: function() {
return data.description;
},
tags: function() {
return Tags(data.id);
}
}
}
Hope someone can show me the way for it.
I use express to do my apis...you can do something like this:
app.get('/api/article', authenticate, routes.api.article.get);
authenticate is just a middleware function that authenticates the user, typically this is grabbing the user from session and making sure they are logged in.
inside ./routes/api.js
var Article = require('../models/article.js');
exports.api = {}
exports.api.article = {}
exports.api.article.get = function(req, res){
//get article data here
Article.find({created_by: req.session.user._id}).populate('tags').populate('created_by').exec(function(err, list){
res.json(list);
});
};
This assume you're using mongoose and mongodb and have an Article schema similar to this, which includes a reference to a Tag schema:
var ArticleSchema = new Schema({
name : { type: String, required: true, trim: true }
, description: { type: String, trim: true }
, tags : [{ type: Schema.ObjectId, ref: 'Tag', index: true }]
, created_by : { type: Schema.ObjectId, ref: 'User', index: true }
, created_at : { type: Date }
, updated_at : { type: Date }
});