I am starting to develop for relay coming from Apollo.
I have a dumb server running on a SQLITE3 database just for testing while I am refactoring.
Using graphql-relay on the backen.
Currently I have something like this:
{
root: {
allFoo: [FooType]
}
}
I was wondering how I would add a new FooType item to the allFoo list.
On the getConfigs the RANGE_ADD only acts upon connections.
So do I need to make my allFoo type a connection instead of a GraphqlList(FooType) ? Or can I use FIELD_CHANGE somehow?
Take a look at this example:
https://github.com/bfwg/relay-gallery/blob/master/frontend/src/app/mutation/AddImageMutation.js#L47
The below example is a demo on how to add an image to the image list.
getConfigs() {
return [{
type: 'RANGE_ADD',
parentName: 'User',
parentID: this.props.images.id,
connectionName: 'images',
edgeName: 'newImageEdge',
rangeBehaviors: {
'': 'prepend',
},
}];
}
Hope this helps!
Related
I've been trying to build an app and for brevity, assuming that I only have two types of objects with the following fields:
User: user_uid, name, Settings(reference)
Settings: settings_uid, some_settings_json
So far, I've tried creating Settings object first then linking the ready Settings object to the User object getting created.
Creating the settings object:
mutation createSettings {
createSettings(data: {some_settings_json: "{"some_key": "some_value"}" }) {
settings_uid
}
}
Creating the User object:
mutation createUser {
createUser(data: {name: "some_user", settings: <SETTINGS_OBJECT>) {
user_uid
}
}
Although I've checked documentations, tutorials, web; I haven't been able to figure out how to replace <SETTINGS_OBJECT>, so that these two objects would get linked. Note: I don't want to create settings while user is getting created. For that, a tutorial already provides an example.
Any help would be appreciated.
I found it. The link is provided via connect keyword.
mutation createUser {
createUser(data: {
name: "some_name", settings: {
connect: {
settings_uid: "settings_uid"
}
}
}) {
user_uid
}
}
In a KeystoneJS GraphQL project I'm trying to create a new data object (an "Article") in the 'resolveInput' hook of another, existing, data object (a "Proposal" -- when a Proposal is approved, I create an Article based on that Proposals'data).
This worked fine using the Mongoose adapter, but I've tried to do it using the built in GraphQL API, using keystone.executeQuery and I get the following error:
My Article list has a relationship with one Proposal (I'm leaving out the other fields)
fields: {
proposal: {
isUnique: false,
type: fields_1.Relationship,
ref: 'Proposal',
access: {
create: true,
read: true,
update: false
}
}
}
and I create the new Article thus (I'm omitting some code)
hooks: {
resolvedInput: async params => {
const articleCreateInput = {
title: cleanTitle,
text: cleanText,
visible: HIDDEN,
proposal: {
connect: {
id: proposalId
}
}
};
const articleCreationResult = await keystone.executeQuery(createArticle, { variables: articleCreateInput });
}
}
As far as I can see this is the correct way to do it, using connect, connecting an existing item to one you are creating.
My query is
const createArticle = `mutation createArticle($data:ArticleCreateInput) {
createArticle(data:$data) {
id
title
visible
publishDate
}
} `;
and as far as I can see I'm following the schema correctly
I'm sure I'm making an obvious mistake but at the moment I don't see it -- and I'm not sure whether that mistake is a GraphQL mistake or a KeystoneJS mistake (or both).
The translation of generics inputs was the same for all resources, so how can i specifiy it in the resource file ?
something like this should be great !
export default {
resources: {
'*': {
fields: {
lastname: 'Nom',
},
},
},
}
That's not possible for now but that looks like a good feature request. Would you mind opening an issue about it on our repository?
I've been playing with GraphQL recently, and am currently learning about mutations. I'm a bit confused with something. I have a model Post with relation Comments. I have a mutation that looks like this:
mutation addCommentToPost {
updatePost(
id: "POST-1",
comments: [{
body: "Hello!"
}]
) {
id,
comments {
id,
body
}
}
}
The problem is, whenever I run this, it seems to remove all the comments and sets the comments to only the one I just added. To be more specific, how do I write a mutation that pushes to the comments array rather than replacing it?
You are using a mutation called updatePosts, which I assume (based on the name) simply updates a post by replacing the fields that are passed. If you want to use the updatePosts mutation to add a comment, you will first have to query for the post to get the current list of comments, add your comment to the end, and then call updateComment with the entire list of comments (including the one that you just added to the end).
However, this isn't really a good solution, especially if the list of comments is potentially very long. If you have the ability to change the GraphQL server, you should create a new mutation on the server with a signature like addComment(postId: ID, comment: CommentInput). In the resolve function for that mutation, simply add the comment that is passed to the end of the list of current comments.
// resolver for addComment:
addComment(root, args) {
// validate inputs here ...
const post = db.getPost(args.postId);
post.comments.append(args.comment);
db.writePost(post.id, post);
}
db.getPost and db.writePost are functions you have to define yourself to retrieve/write a post from/to wherever you store it.
It's important to note that unlike a SQL or Mongo query, a GraphQL mutation itself doesn't have any meaning without the resolve functions. What the mutation does is defined entirely inside its resolve function. Mutation names and arguments only gain meaning together with the resolve function. It's up to you (or the GraphQL server developers in your company) to write the resolve functions.
The way this situation is currently solved in the Graphcool API is to use a create mutation for the Comment that links to the Post. This is called a nested connect mutation.
This is how it would look like:
mutation {
createComment(
text: "Hello!"
postId: "POST-1"
) {
id
text
post {
comments {
id
}
}
}
}
In the future, other nested arguments like comments_set or comments_push could be introduced, then pushing would be possible like this:
mutation addCommentToPost {
updatePost(
id: "POST-1",
comments_push: [{
body: "Hello!"
}]
) {
id,
comments {
id,
body
}
}
}
Disclosure: I work at Graphcool.
You can use those code as an example for mutation.
module.exports = (refs) => ({
type: refs.commentType,
args: {
id: {
type: GraphQLString
},
body: {
type: GraphQLString
}
},
resolve: (parent, args, root) => {
return createUser(args);
}
});
How to write outputFields, getFatQuery, getConfigs for create new item and update items list
Please take a look gist or live
Questions are
getFatQuery() {
return Relay.QL`
???
`;
}
getConfigs() {
return [???];
}
outputFields: {
???
},
The outputFields in your schema make up the GraphQL type CreateActivityPayload that will be generated from your schema.js file. A mutation is like a regular query, but with side effects. In outputFields you get to decide what's queryable. Since your store is the only thing in your app that can change as a result of this mutation, we can start with that.
outputFields: {
store: {
type: storeType,
resolve: () => store,
},
}
The fat query operates on these output fields. Here you tell Relay what could possibly change as a result of this mutation. Adding an activity could change the following fields:
getFatQuery() {
return Relay.QL`
fragment on CreateActivityPayload #relay(pattern: true) {
store {
activities
}
}
`;
}
Finally, the config tells Relay what to do with the query when it gets it, or even if it needs to be made at all. Here, you're looking to update a field after creating a new activity. Use the FIELDS_CHANGE config to tell Relay to update your store.
getConfigs() {
return [{
type: 'FIELDS_CHANGE',
fieldsIDs: {
store: this.props.storeId,
},
}];
}
See more: https://facebook.github.io/relay/docs/guides-mutations.html