<p>First, you need to import your macro, and not just call <code>{{ _self.doPeriod() }}</code>. <a href="http://twig.sensiolabs.org/doc/1.x/tags/macro.html" rel="nofollow noreferrer">From the documentation</a>:</p>

<blockquote>
  <p>When you define a macro in the template where you are going to use it, you might be tempted to call the macro directly via _self.input() instead of importing it; even if seems to work, this is just a side-effect of the current implementation and it won't work anymore in Twig 2.x.</p>
</blockquote>

<p>I always do: <code>{% import _self as self %}</code></p>

<p><a href="http://twig.sensiolabs.org/doc/2.x/filters/slice.html" rel="nofollow noreferrer">slice</a> returns a sequence - in your case an array with one element, and the key is <code>0</code>. Your macro is expecting a matrix block, not an array, which is why you get that error.</p>

<p>If you only want the first block, then <code>{% set period = timelineText.first %}</code> and <code>period</code> will be a matrix block. <code>{{ self.doPeriod(period) }}</code> will work.</p>

<p>If you want to call <code>doPeriod</code> on all of the matrix blocks, then:</p>

<pre><code>{% for period in timelineText %}
  ... {{ self.doPeriod(period) }} ...
{% endfor %}
</code></pre>

CC BY-SA 3.0
2017-01-06T19:17:29.997Z
2017-01-06T19:17:29.997Z
Marion Newlevant
<p>I want to fetch a specific block from a Matrix global then pass it through a macro which returns a response based on the block type. However, if I try to use <code>slice</code> the type doesn't appear to be available to the macro. Has anyone experienced something similar?</p>

<p>eg if I set <code>{% set timelineText = timeline.timeline %}</code> (where first <code>timeinline</code> is my global and second <code>timeline</code> is my Matrix field) then fetch a specific block from the Matrix: <code>{% set period = timelineText|slice(0,1) %}</code> should return the first instance/block from the field. I can then pass this to my macro: <code>{{ _self.doPeriod(period) }}</code></p>

<p>My macro is</p>

<pre><code>{% macro doPeriod(content) %}
{% switch content.type %}
{% case 'quote' %}
    ...
{% case 'period' %}
    ...
{% endswitch %}    
{% endmacro %}```
</code></pre>

<p>But this returns the following error: <code>Key "type" for array with keys "0" does not exist</code></p>

<p>Any thoughts?</p>

CC BY-SA 3.0
2017-01-06T16:27:33.843Z
To add some more detail, if I dump contents of, eg `timelineText|slice(0,1)` all the Matrix blocks are returned. However, if I do `timelineText.first` only the first block is returned. 

Is `slice` the right filter in this instance/for this use?
Cole Henley
CC BY-SA 3.0
2017-01-06T16:55:21.997Z
Okay, if my initial request just fetches the ids then this works as I can fetch specific blocks via an id() request, eg:

`{% set timelineIds = timeline.timeline.ids() %}`. Then
`{% set period = timeline.timeline.id(timelineIds[0:1]).first %}` with `{{ _self.doPeriod(period) }}`

However, this does mean a new DB request for each block which seems a bit excessive
Cole Henley
<matrix><switch>
Passing Matrix block to a macro
# Passing Matrix block to a macro

(Asked by: username_0 on 2017-01-06)

I want to fetch a specific block from a Matrix global then pass it through a macro which returns a response based on the block type. However, if I try to use slice the type doesn't appear to be available to the macro. Has anyone experienced something similar?
eg if I set {% set timelineText = timeline.timeline %} (where first timeinline is my global and second timeline is my Matrix field) then fetch a specific block from the Matrix: {% set period = timelineText|slice(0,1) %} should return the first instance/block from the field. I can then pass this to my macro: {{ _self.doPeriod(period) }}
My macro is
{% macro doPeriod(content) %}
{% switch content.type %}
{% case 'quote' %}
    ...
{% case 'period' %}
    ...
{% endswitch %}    
{% endmacro %}```

But this returns the following error: Key "type" for array with keys "0" does not exist
Any thoughts?

**Tags:** matrix, switch

> **Comments:**
> **username_0**: To add some more detail, if I dump contents of, eg `timelineText|slice(0,1)` all the Matrix blocks are returned. However, if I do `timelineText.first` only the first block is returned.   Is `slice` the right filter in this instance/for this use?  
> **username_0**: Okay, if my initial request just fetches the ids then this works as I can fetch specific blocks via an id() request, eg:  `{% set timelineIds = timeline.timeline.ids() %}`. Then `{% set period = timeline.timeline.id(timelineIds[0:1]).first %}` with `{{ _self.doPeriod(period) }}`  However, this does mean a new DB request for each block which seems a bit excessive  

---

## 1 answers

### Answer by username_1 on 2017-01-06. Score: 2 | Accepted answer

First, you need to import your macro, and not just call {{ _self.doPeriod() }}. From the documentation:

When you define a macro in the template where you are going to use it, you might be tempted to call the macro directly via _self.input() instead of importing it; even if seems to work, this is just a side-effect of the current implementation and it won't work anymore in Twig 2.x.

I always do: {% import _self as self %}
slice returns a sequence - in your case an array with one element, and the key is 0. Your macro is expecting a matrix block, not an array, which is why you get that error.
If you only want the first block, then {% set period = timelineText.first %} and period will be a matrix block. {{ self.doPeriod(period) }} will work.
If you want to call doPeriod on all of the matrix blocks, then:
{% for period in timelineText %}
  ... {{ self.doPeriod(period) }} ...
{% endfor %}


---

