Cms: GraphQL transform argument doesn't work with image width and height properties

Created on 18 Aug 2020  路  14Comments  路  Source: craftcms/cms

Description

I have the following graphQL snippet (as part of a larger query not shown here):

image {
    url
    width
    height
    small_url: url(transform: "small")
    small_width: width(transform: "small")
    small_height: height (transform: "small")
}

which results in the following output:

"image": [
    {
        "url": "http://portal-cms.test/assets/content-images/logo.png",
        "width": 1700,
        "height": 494,
        "small_url": "http://portal-cms.test/assets/content-images/_small/logo.png",
        "small_width": 1700,
        "small_height": 494
    }
]

As you can see above, the transform argument works for the url property, but doesn't work for the width and height properties even through you can set a transform argument on them. In the above case, the small_width and small_height properties should be 170 and 50 respectively (as that is what I have set the transform to).

I think this is a bug, but it could also be something wrong with how I am fetching image transforms in GraphQL. It is important to note that the above image field is part of a matrix block, so not sure if that is the reason why this isn't working as expected.

Secondly, I have a question about the above JSON structure. Is there a way to return the image transform data in a structure somewhat similar to the structure below?

"image": [
    {
        "original": {
            "url": "http://portal-cms.test/assets/content-images/logo.png",
            "width": 1700,
            "height": 494
        },
        "small": {
            "url": "http://portal-cms.test/assets/content-images/_small/logo.png",
            "width": 170,
            "height": 50
        },
        "medium": {
            "url": "http://portal-cms.test/assets/content-images/_medium/logo.png",
            "width": 340,
            "height": 100
        }
    }
]

Is this possible to have this data structure returned by a graphql query where each specified transform returns as a separate object with generic url, width and height field instead of my solution at the top using graphql aliases? I have been reading the graphql documentation and haven't found a way to do something like this yet.

Also, apologies if this is a duplicate issue. I did go through the graphql and image transform related issues and couldn't find anything similar.

Thank you! 馃檹

Additional info

  • Craft version: 3.5.4 / 3.5.5
  • PHP version: 7.4
  • Database driver & version: pgsql 11
  • Plugins & versions:
bug

Most helpful comment

@jesuismaxime We鈥檝e added that for the next release!

{
  original: asset(id: X) {
    url
    width
    height
  }
  square: asset(id: X) @ transform (transform: "square") {
    url
    width
    height
    srcset(sizes:["100w"", "200w"])
  }
}

All 14 comments

I just resolved this via f54fa5faeefa5c8bddc4aa057ad905048a59ba28, this will be part of the next Craft 3.5 release.

Sorry about this - really a rookie mistake :)

@andris-sevcenko, no problems at all. Thank you for resolving it so quickly.

Also, not sure if you saw my second question above. Do you know if it is possible to output the JSON structure in my last code snippet above using the GraphQL API? Here it is again for convenience:

"image": [
    {
        "original": {
            "url": "http://portal-cms.test/assets/content-images/logo.png",
            "width": 1700,
            "height": 494
        },
        "small": {
            "url": "http://portal-cms.test/assets/content-images/_small/logo.png",
            "width": 170,
            "height": 50
        },
        "medium": {
            "url": "http://portal-cms.test/assets/content-images/_medium/logo.png",
            "width": 340,
            "height": 100
        }
    }
]

Please note that I am not asking for changes to the GraphQL API. I am just wondering if it is somehow possible to structure the output like this given the current GraphQL schema for image transforms.

cc @brandonkelly

@sidm1983 sorry, forgot to respond to that part.

In GraphQL your data is returned in exactly the same format you queried for it - there is no way around it.

The only way to get the data structured _exactly_ like how you want it would be to leverage the fact that the transform directive can be applied to an asset on the GraphQL field level, too.

{
  original: asset(id: X) {
    url
    width
    height
  }
  small: asset(id: X) @transform (handle: "small") {
    url
    width
    height
  }
  medium: asset(id: X) @transform (handle: "medium") {
    url
    width
    height
  }
}

handle is an alias for transform, by the way, so don't be confused about that :)

@andris-sevcenko I don't think I can use your sample query in this case as I don't know the asset ID while I am doing the query. I guess this would work if I first did a query to retrieve only the ID of the asset and then do this as a second query. Will experiment with it when I get a chance and will let you know if I have any questions. Thank you for the quick response. Much appreciated! 馃檹馃徑馃檶馃徑馃憤馃徑馃槉

@andris-sevcenko I played around with my GraphQL query and was able to get the structure I wanted using the @transform directive in your code sample, so thanks for that 馃槃馃檶

I thought I'd share my approach in case someone else lands here with the same question. Here is my approach:

image {
    url
    width
    height
}
imageSmall: image @transform(handle: "small") {
    url
    width
    height
}

and that results in:

"image": [
    {
        "url": "http://portal-cms.test/assets/content-images/logo.png",
        "width": 1700,
        "height": 494,
    }
],
"imageSmall": [
    {
        "url": "http://portal-cms.test/assets/content-images/_small/logo.png",
        "width": 170,
        "height": 50,
    }
]

As you can see above, the imageSmall property has the correct width and height even without your fix in commit f54fa5f thanks to the @transform directive. It is still definitely great to have your fix as well in case people need to transform the width/height properties directly.

Once again, thank you for your help with this. 鉂わ笍馃憤

I don't think I can use your sample query in this case as I don't know the asset ID while I am doing the query. I guess this would work if I first did a query to retrieve only the ID of the asset and then do this as a second query.

Right, that was just an assumption. Typically you would loop through an asset field like that, in which case the approach is just as valid - except instead of aliasing the asset query, you're aliasing the asset field.

Glad you got it all working!

Craft 3.5.6 is out now with this fix.

Following that issue, is there any way to use the new getSrcset() method (since 3.5) in GraphQL and in this kind of query :

{
  original: asset(id: X) {
    url
    width
    height
  }
  square: asset(id: X) @ transform (transform: "square") {
    url
    width
    height
  }
}

to get 1x/2x for the square transformation ?

@jesuismaxime We鈥檝e added that for the next release!

{
  original: asset(id: X) {
    url
    width
    height
  }
  square: asset(id: X) @ transform (transform: "square") {
    url
    width
    height
    srcset(sizes:["100w"", "200w"])
  }
}

@brandonkelly can we add the format argument to output the srcset as webp images?

@jaydensmith going forward, the srcset field will take into account whatever format the asset transform has set. Som in your case, you could do:

{ 
  asset @transform(format: "webp") {
    id
    title
    url
    srcset (sizes: ["1x", "2x"])
  }
}

@jaydensmith worth noting that, as of the next release, it will be possible to set the webp format on named transforms as well, if your server supports it.

Craft 3.5.16 is out now with that fix.

Was this page helpful?
0 / 5 - 0 ratings