<p>I see a few problems. The first is that <code>{{ grid.item(entry.image) }}</code> is actually an <a href="http://buildwithcraft.com/docs/templating/elementcriteriamodel" rel="nofollow">ElementCriteriaModel</a> (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 <code>entry.image.first</code> or <code>entry.image[0]</code>.</p>

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

<pre><code>{% macro item(thumbnail) %}
    {% if thumbnail %}
        &lt;img src="{{ thumbnail.url }}"/&gt;
    {% endif %}
{% endmacro %}

{% from _self import item %}

{% for entry in craft.entries.section('handle') %}
    {{ item(entry.image.first) }}
{% endfor %}
</code></pre>

<p><strong>Update:</strong> 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:</p>

<pre><code>{% macro item(thumbnail) %}
    {% if thumbnail.first %}
        &lt;img src="{{ thumbnail.first.url }}"/&gt;
    {% endif %}
{% endmacro %}

{% from _self import item %}

{% for entry in craft.entries.section('handle') %}
    {{ item(entry.image) }}
{% endfor %}
</code></pre>

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

CC BY-SA 3.0
2014-10-27T15:20:51.263Z
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
CC BY-SA 3.0
2014-10-27T15:22:10.460Z
I would like to do this since I'm reusing my macro across multiple templates. Maybe that's bad practice?
naboovalley
CC BY-SA 3.0
2014-10-27T15:49:05.993Z
@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
CC BY-SA 3.0
2014-10-27T15:52:47.400Z
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
CC BY-SA 3.0
2014-10-27T15:53:28.553Z
... also importing the macro at the top of the template and reusing it further down... will that increase page load? Isn't the import only made once?
naboovalley
CC BY-SA 3.0
2014-10-27T15:53:57.900Z
@naboo to help you with your problem: you could try and feed your macro an array of element models instead of that elementcriteriamodel, by adding `find()`. Additionally it is always good to use the plural with your vars or fieldnames if there's multiple elements: `{{ grid.item(entry.images.find()) }}` :)
carlcs
CC BY-SA 3.0
2014-10-27T15:56:23.443Z
The user can only select one image, so the naming should be fine. Regarding my original question I'm taking it that passing the entire "ElementCriteriaModel" isn't doable. I can only pass the "ElementModel"?
naboovalley
CC BY-SA 3.0
2014-10-27T15:56:48.877Z
Ouups... no you can always have your macro output nothing, I don't see any bad practice there. And yes, if you don't call the import multiple times, say with a loop :)
carlcs
CC BY-SA 3.0
2014-10-27T15:59:28.753Z
It's not what the user selects, but how Craft returns request. It's always multiple images and you have to use `first()` to get the one selected. Did `find()` do the trick?
carlcs
CC BY-SA 3.0
2014-10-27T16:01:49.507Z
To better understand what I mean with an array of element models read here about the difference to ecm: http://buildwithcraft.com/docs/templating/elementcriteriamodel#find
carlcs
CC BY-SA 3.0
2014-10-27T20:27:23.633Z
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
CC BY-SA 3.0
2014-10-27T20:32:46.190Z
Ah Douglas - right on. It's not the macro complaining, it's the code _WITHIN_ the macro. I didn't realize this at first, now I see what's wrong. Thank you for pointing this out! :)
naboovalley
CC BY-SA 3.0
2014-10-27T22:28:55.960Z
@naboovalley if this correct, can you hit the checkmark? This will help others. Thanks.
Douglas McDonald
CC BY-SA 3.0
2014-10-27T14:41:46.007Z
2014-10-27T20:39:08.037Z
2014-10-27T20:39:08.037Z
Douglas McDonald
<p>I'm trying to pass an AssetModel into a twig macro but all I'm getting is:</p>

<pre><code>Object of class Craft\ElementCriteriaModel could not be converted to string 
</code></pre>

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

<p>This is my macro</p>

<pre><code>{% macro item(thumbnail) %}
    {% if thumbnail %}
        &lt;img src="{{ thumbnail }}"/&gt;
    {% endif %}
{% endmacro %}
</code></pre>

<p>This is my template</p>

<pre><code>{% import "macros/grid.html" as grid %}

{% for entry in craft.entries.section('handle') %}
    {{ grid.item(entry.image) }}
{% endfor %}
</code></pre>

<p><em>entry.image</em> is an Asset field</p>

CC BY-SA 3.0
2014-10-27T13:45:39.170Z
Can you share your code, so we can see it in context?
Douglas McDonald
CC BY-SA 3.0
2014-10-27T13:57:46.317Z
code added Douglas
naboovalley
<templating><macro>
How pass an ElementModel to a Macro in Twig
# How pass an ElementModel to a Macro in Twig

(Asked by: username_0 on 2014-10-27)

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 %}
        
    {% 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

**Tags:** templating, macro

> **Comments:**
> **username_1**: Can you share your code, so we can see it in context?  
> **username_0**: code added Douglas  

---

## 1 answers

### Answer by username_1 on 2014-10-27. Score: 3 | Accepted answer

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,  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 %}
        
    {% 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 %}
        
    {% 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.

> **Comments:**
> **username_0**: 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?  
> **username_0**: I would like to do this since I'm reusing my macro across multiple templates. Maybe that's bad practice?  
> **username_2**: @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.  
> **username_0**: 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 :)  
> **username_0**: ... also importing the macro at the top of the template and reusing it further down... will that increase page load? Isn't the import only made once?  
> **username_2**: @naboo to help you with your problem: you could try and feed your macro an array of element models instead of that elementcriteriamodel, by adding `find()`. Additionally it is always good to use the plural with your vars or fieldnames if there's multiple elements: `{{ grid.item(entry.images.find()) }}` :)  
> **username_0**: The user can only select one image, so the naming should be fine. Regarding my original question I'm taking it that passing the entire "ElementCriteriaModel" isn't doable. I can only pass the "ElementModel"?  
> **username_2**: Ouups... no you can always have your macro output nothing, I don't see any bad practice there. And yes, if you don't call the import multiple times, say with a loop :)  
> **username_2**: It's not what the user selects, but how Craft returns request. It's always multiple images and you have to use `first()` to get the one selected. Did `find()` do the trick?  
> **username_2**: To better understand what I mean with an array of element models read here about the difference to ecm: http://buildwithcraft.com/docs/templating/elementcriteriamodel#find  
> **username_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.  
> **username_0**: Ah Douglas - right on. It's not the macro complaining, it's the code _WITHIN_ the macro. I didn't realize this at first, now I see what's wrong. Thank you for pointing this out! :)  
> **username_1**: @username_0 if this correct, can you hit the checkmark? This will help others. Thanks.  

---

