Storefront API: querying for variable parameters? - graphql

The Shopify Storefront API examples show an App.js view listing all products on one page. In these examples, products are added to the cart from this index page, and there is no product detail page. Unlike the examples, I want to click through to a product details page from an index of products.
The products index was easy. But I'm having alot of trouble understanding how to create a page per product.
Seems I can't use a graphql query with a variable on Shopify Storefront. For example, this fails:
query myQuery($id: ID!) {
Product(id: $id) {
id
title
}
}
I'm using nuxt and vue-apollo to build the frontend.
Any pointers appreciated.

The query you've provided is missing the actual variable value that you're querying.
The body of the HTTP request to the GraphQL endpoint should look like this:
query:"query myQuery($id: ID!) {
Product(id: $id) {
id
title
}
}"
variables:{id: "ce03707f-971e-4c64-853c-06a8c2e21448"}
Edit: Vue specific example:
// Apollo-specific options
apollo: {
// Query with parameters
ping: {
// gql query
query: gql`query PingMessage($message: String!) {
ping(message: $message)
}`,
// Static parameters
variables: {
message: 'Meow',
},
},
},
from: https://akryum.github.io/vue-apollo/guide/apollo/queries.html#query-with-parameters

Related

Using slug as a filter with Graphql and Strapi V4

Trying to use slug as an uuid to fetch single pages from a strapi backend v4.
my query to get pages works well. It's just I can't filter using slug:
my pages query:
query {
pages {
data {
attributes {
Name
slug
}
}
}
}
how to get single page using slug uuid within this schema ? every trails to implement ($slug: String!) fails as where to locate slug.
You can use filters. Just pass slug as argument and use the 'eq' keyword for comparison which stands for equals.
query pages($slug:String) {
pages(filters:{slug:{eq:$slug}}) {
data {
attributes {
Name
slug
}
}
}
}
Try this
query pages($id: ID) {
page(id: $id) {
data {
attributes {
name
slug
}
}
}
}
base on this blog, from strapi, a resolver must be coded
I Found a Blog for strapi v4

How can I query my data by published date (newest first) using Apollo and Graphql?

I have React page that is fetching data via Graphql.
I'm using Strapi as backend and queries are already generated.
I´m querying my data in the frontend like this
query GetData{
datas(limit:3){
id
published_at
}
}
In the documentation I found this example about how to sort my queries by some especific order
GET /users?_sort=email:ASC,dateField:DESC
but is not really clear how to use it with the query structure.
I tried something like this and other variations
query GetPodcasts{
podcasts?_sort=published_at:DESC(limit:3){
id
published_at
}
}
but it didn't work.
I may need some help understanding this.
In a forum some nice people also gave me an answer.
When using graphql in frontend and want to sort or filter the data, just have to use "" to specify the sort or filter.
In my case it just had to be:
query GetData{
datas(limit:3, sort:"published_at:desc"){
id
published_at
}
}
Graphql is like an Rest Api but with one end point to the server ,
this query with name GetData , point to datas query but you should define this query in the backend.
please watch some tutorials that will guide you step by step.
you can learn more about graphql here
https://graphql.org/learn/
try this:
query GetData{
datas(input:{
sort:{id:"asc"},
data:{limit:3}
}){
id
published_at
}
}
for more info
https://strapi.io/documentation/developer-docs/latest/development/plugins/graphql.html#query-api
This seem to work for me in Strapi v4:
sort: "publishedAt:DESC"
...
query GetVideos($page: Int!, $pageSize: Int!) {
videos(
pagination: { page: $page, pageSize: $pageSize }
sort: "publishedAt:DESC"
) {
__typename
data {
__typename
id
attributes {
__typename
createdAt
publishedAt
}
}
}
}
}
`

GraphQL retrieve data for specific blocks - Gatsby + Wordpress

I have a React + Gatsby JS project that retrieves data from a Wordpress site through their headless API. I'm a total newbie to Gatsby.
Every page on my site is made up of blocks, which are in turn made up of fields. I'm using ACF to build these.
I am currently able to retrieve every page and a list of the blocks within that page by using the following GraphQL query:
query ($id: String!) {
currentPage: wordpressPage(id: {eq: $id}) {
title
acf {
page_blocks {
block_type {
acf_fc_layout
}
}
}
}
}
This returns the following data for page with id f4c4f4a7-ba0d-55b1-8877-16f543c22b80
{
"data": {
"wordpressPage": {
"id": "f4c4f4a7-ba0d-55b1-8877-16f543c22b80",
"acf": {
"page_blocks": [
{
"block_type": [
{
"acf_fc_layout": "page_title_and_text"
},
{
"acf_fc_layout": "two_column_media_and_text"
}
]
}
]
}
}
}
}
The blocks are next to afc_fc_layout. Both page_title_and_text and two_column_media_and_text are page blocks in that page.
Now, I would think that the next step would be to make a React component for each of those blocks, passing in the custom field data for each, to that component. If a page doesn't have a block, then there wouldn't be a need for me to retrieve the fields for that block, right?
Initially I thought I would run another query from my React component, requesting the fields for that particular block. But I realized I can't really add variables (page Id) to a static query within my components, per Gatsby docs, so I wouldn't be able to query that specific page for its fields. Please correct me if I'm wrong.
I believe I have to retrieve those fields I need from my main query that I've shown you here, but it seems absolutely bonkers to have to query for every possible custom field on the site, when not all pages are going to have the same blocks.
Ideally there would be some sort of syntax like
...
acf {
page_blocks {
block_type {
acf_fc_layout
if (acf_fc_layout eq page_title_and_text) {
title
text
}
if (acf_fc_layout eq two_column_media_and_text) {
media
text
}
}
}
}
...
And then I would pass those fields to their corresponding React component.
What is the proper way to go about this?
Note: I am currently at the point where I'm able to retrieve the fields from the API to render blocks. I am more wondering if there is any way my graphQL query can filter out the data for me, or if there is a way to customize the WP endpoint to show me field data filtered by the blocks that are actually on the page.
Ex: the site queries the data in blocks 4,3,2,10,12,15.... even though the page only has block 2.
I'm worried that devs that want to add blocks in the future will have to rewrite the query each time, hurting the site's scalability and potential performance.
You say you are a beginner with Gatsby but what you are trying to do touches many advanced topics inside Gatsby. My answer is most likely incomplete and you will need to figure many things out for yourself.
Prepare yourself for lots of documentation reading and lots of debugging to get things to work with Gatsby.
You want to programmatically create pages depending on the result of your GraphQL query. That means you need to create a page wide page template component.
In your templates folder of your Gatsby project, you create one template that programmatically picks the right components for each of your routes. To get your ACF data you use GraphQL page queries.
What is the proper way to go about this?
One alternative is this: You create React components that retrieve their data via props. You don't need to give each of those components their own GraphQL query since you already query in your page templates.
acf: acf_fc_layout eq page_title_and_text -> React component PageTitleAndText.jsx
const PageTitleAndText = ({ title, text}) => {
return (
<div>
<h1>{title}</h1>
<p>{text}</p>
</div>
);
};
// NO GraphQL query
export default PageTitleAndText;
Instead, you pass props inside your page template to your component:
acfPageTemplate.jsx
const acfPageTemplate = (props) => {
return (
<div>
{/* pass props as data from the GraphQL query result here */}
<PageTitleAndText title={props.data.currentPage.acf.page_blocks.block_type.acf_fc_layout.title }
text ={props.data.currentPage.acf.page_blocks.block_type.acf_fc_layout.text} />
</div>
);
};
export const query = graphql`
query ($id: String!) {
currentPage: wordpressPage(id: {eq: $id}) {
title
acf {
page_blocks {
block_type {
acf_fc_layout
}
}
}
}
}
`;
export default acfPageTemplate;
Define a page template for each of your acf layouts. Pick the right components for each layout and pass props as data from the GraphQL query result.
You need to pass variables to your page query. The only way to do this is to use page context as described in this question:
gatsby-node.js
createPage({
path: `/my-acf-page-title-and-text-page/`,
component: path.resolve(`./src/templates/PageTitleAndText.jsx`),
// The context is passed as props to the component as well
// as into the component's GraphQL query.
context: {
id: acfFieldId, // pass the acf field id
},
})
// define a createPage action for each of your acf layouts
But I realized I can't really add variables (page Id) to a static query within my components, per Gatsby docs, so I wouldn't be able to query that specific page for its fields. Please correct me if I'm wrong.
Correct. That's why you need to go the way with a page query, page template, and page context variable in gatsby-node.js
If a page doesn't have a block, then there wouldn't be a need for me to retrieve the fields for that block, right?
Yes. That's why you create a different page template for each of your acf layouts. You can create one big tempalte for all layouts but then you need to programmatically decide what components to add. This is out of scope of this question. You should ask a new question if you want to do this.
My advise is to get this to work with one specific layout before you go down this next rabbit hole, if you decide to do this at all.

Wordpress Gatsby - How do i access ACF relationship content in graphql, or otherwise

Using gatsby-source-wordpress I have a content type called 'student' which has a ACF relationship field that links to content type 'posts'. I want to show the related posts (title and other fields) on the student page.
On a student post i can get various fields of the related content, wordpress_id seems most useful (below is an example of the ACF relationship field on a 'student' set to show 'wordpress_id's:
{
"node": {
"acf": {
"related_projects": [
64,
88,
1
]
}
}
}
What i'd like to do is construct a graphQL query on the student page the selects all posts that match enter code herea set of wordpress_ids. I can see how to match a single id, but not multiple. Or can a single graphQL query be looped over on a page?
If you're using the ACF to REST API plugin on your WordPress site, then you can query related posts added via an ACF Relationships field.
Here is a GraphQL query example using a Flexible Content layout field called Related Content and a ACF relationship field called Related Posts:
{
allWordpressPost {
edges {
node {
title
acf {
content_post {
__typename
... on WordPressAcf_related_content {
related_posts {
post_title
post_content
}
}
}
}
}
}
}
}

Is it possible to use nested / namespaced query variables in a GraphQL query?

I'd like to namespace / nest query variables like this:
query ($params: {$id: ID!}) {
getUser(id: $params.id) {
email
username
}
}
with the variables:
{
"params": {
"id": "42"
}
}
but it's not a valid query.
However a query like:
query ($id: ID!) {
getUser(id: $id) {
email
username
}
}
with the variables:
{
"id": "42"
}
will work just fine.
The reason I want to do this is to automatically send in query options into the ApolloReact graphql higher order component with the params prop from that is applied to the wrapped component from react router. This question essentially has nothing to do with react router, apart from the fact that the params prop is applied to the component by react router.
ApolloReact will try to use the props from the component to automatically build the variables object, and since id is nested in props it can't find it.
The alternative is to specifically define where to find id, by defining an options method that receives ownProps and returns the variables object in graphql but I would like to avoid it if possible.
No, you can't use the fields of that composite type in the query.
I think your best option will be to create the following function:
const options = ({params: variables}) => ({variables})
and export the wrapped component like so:
export default graphql(QUERY, {options})(Component)
That way the params property passed by react-router will become the variables object passed to the query and you can use it like this:
<Component id="1" otherVar="some value"/>
With the regular query:
query ($id: ID!) {
getUser(id: $id) {
email
username
}
}

Resources