2

I'm trying to pass an AssetModel into a twig macro but all I'm getting is:

Object of class Craft\ElementCriteriaModel could not be converted to string 

Is there any way to define my twig macro variable to be an object instead of a string?

This is my macro

{% macro item(thumbnail) %}
    {% if thumbnail %}
        <img src="{{ thumbnail }}"/>
    {% endif %}
{% endmacro %}

This is my template

{% import "macros/grid.html" as grid %}

{% for entry in craft.entries.section('handle') %}
    {{ grid.item(entry.image) }}
{% endfor %}

entry.image is an Asset field

  • Can you share your code, so we can see it in context? – Douglas McDonald Oct 27 '14 at 13:45
  • code added Douglas – naboovalley Oct 27 '14 at 13:57
3

I see a few problems. The first is that {{ grid.item(entry.image) }} is actually an ElementCriteriaModel (i.e. which behaves like an array of images) and not an ElementModel (i.e. a single image), even if only one image is defined. To get the first image you can use entry.image.first or entry.image[0].

The second problem is that in your macro, <img src="{{ thumbnail }}"/> is trying to set the url string using the whole ElementModel (or in your case the ElementCriteriaModel). Instead use: {{ thumbnail.url }}

{% macro item(thumbnail) %}
    {% if thumbnail %}
        <img src="{{ thumbnail.url }}"/>
    {% endif %}
{% endmacro %}

{% from _self import item %}

{% for entry in craft.entries.section('handle') %}
    {{ item(entry.image.first) }}
{% endfor %}

Update: If on the other hand, for some reason you want to pass the ElementCriteriaModel then you just need to handle it appropriately in the macro:

{% macro item(thumbnail) %}
    {% if thumbnail.first %}
        <img src="{{ thumbnail.first.url }}"/>
    {% endif %}
{% endmacro %}

{% from _self import item %}

{% for entry in craft.entries.section('handle') %}
    {{ item(entry.image) }}
{% endfor %}

As a side note — keep in mind that the macro can also exist in the same template and imported using _self.

|improve this answer|||||
  • Thing is I would like to make the check if there's any image select in my macro to keep the code of my template more clean. So I would like to pass the entire ElementCriteriaModel into my macro and in there run my if model|length > 0 to get any image selected. Possible? – naboovalley Oct 27 '14 at 15:20
  • I would like to do this since I'm reusing my macro across multiple templates. Maybe that's bad practice? – naboovalley Oct 27 '14 at 15:22
  • @naboo Id say it's no bad practice at all to import macros, but I can also imagine that importing many files could indeed increase load time. What I do is to put my macros all in one file "includes/macros.html" that I import from my base template "_layout.html". On the other hand, I read somewhere that Twig does extends and include very performant and import is maybe not that different. – carlcs Oct 27 '14 at 15:49
  • Oh sorry. I meant the practice of passing an ElementCriteriaModel to my macro and within the macro making the check if there's an image present or not :) – naboovalley Oct 27 '14 at 15:52
  • 1
    You can pass anything you want to the macro, including ElementCriteriaModel. You just need to handle it correctly in the macro. So, instead the macro would be {% if thumbnail.first %}<img src="{{ thumbnail.first.url }}">{% endif %}. I only mentioned the macro import thing because this was such a simple macro and could easily be inline vs a macro at all. By all means, import your macros! That's what it's there for. – Douglas McDonald Oct 27 '14 at 20:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.