<p>Max - it looks like there might be an issue in how you are looping through the table. Table data is stored as JSON in the database, so calling entry.myTable should give you an array of rows, with each row as a sub-array of values.</p>

<p>From your example:</p>

<pre><code>{% if entry.myTable | length %}
    &lt;table&gt;
        &lt;thead&gt;
            &lt;td&gt;City&lt;/td&gt;
            &lt;td&gt;Population&lt;/td&gt;
            &lt;td&gt;Urban Population&lt;/td&gt;
        &lt;/thead&gt;
        &lt;tbody&gt;
        {% for row in entry.myTable %}
            &lt;tr&gt;
                &lt;td&gt;{{row.city}}&lt;/td&gt;
                &lt;td&gt;{{row.population}}&lt;/td&gt;
                &lt;td&gt;{{row.urbanPopulation}}&lt;/td&gt;
            &lt;/tr&gt;
        {% endfor %}        
        &lt;/tbody&gt;
    &lt;/table&gt;
{% endif %}
</code></pre>

<p>will check to see if the table field exists and has data, then will go through each row, returning values by row.columnName.</p>

<p>Hope this helps!</p>

CC BY-SA 3.0
2015-02-01T15:42:23.530Z
hey, thanks for the reply - sure, you're right. But this way I can't write a template which I can use dynamically - as I'd have to write the handles manually.

The loop actually does work, but I get DOUBLE output, because not only `{{row.columnName}}` exists, but also `{{row.col1}}`. This is the cause why, if I loop through dynamically I get 2x Hamburg. You see the problem?
Max
CC BY-SA 3.0
2015-02-01T15:45:58.623Z
What are you trying to dynamically pull, the table headers?
Aaron Berkowitz
CC BY-SA 3.0
2015-02-01T15:49:56.277Z
I want to dynamically output the table data, no matter which column names the user creates.

This would actually work, if the Craft team would not store the data twice. And I don't know why they did it.

`array(2) { ["col1"]=> string(7) "Hamburg", ["city"]=> string(7) "Hamburg"
}`

so you can query by using `{{ row.col1 }}` and `{{ row.columnName }}` but you cant loop through dynamically, because you get all values twice.
Max
CC BY-SA 3.0
2015-02-01T15:53:57.373Z
Sorry, aberkie, I just edited my example - I had an error in the first sample. The second loop was misleading! -> 

`{% for data in row %}
    <td>{{ data }}</td>
  {% endfor %}`

is the right one
Max
CC BY-SA 3.0
2015-02-01T14:06:08.033Z
2015-02-01T14:06:08.033Z
Aaron Berkowitz
<p>Taken from <a href="https://craftcms.stackexchange.com/questions/2148/show-a-table-fields-column-headers-in-template">carlcs' example</a>, you'll probably want the clean "human readable" table headers. Looks like those aren't handed out in the template by default but you can get 'em with a trip to getFieldByHandle.</p>

<pre><code>{% set field = craft.fields.getFieldByHandle('whateverField') %}
</code></pre>

<p>So something like this:</p>

<pre><code>&lt;table&gt;
&lt;tr&gt;
&lt;thead&gt;
  {% set field = craft.fields.getFieldByHandle('whateverField') %}
  {% for column in field.settings.columns %}
    &lt;th&gt;{{ column.heading }}&lt;/th&gt;
  {% endfor %}
&lt;/thead&gt;
</code></pre>

<p>The just spit out the rest of the table like normal:</p>

<pre><code>&lt;tbody&gt;
    {% for row in entry.whateverField %}
      &lt;tr&gt;&lt;td&gt;{{ row.col1 }}&lt;/td&gt;&lt;td&gt;{{ row.col2 }}&lt;/td&gt;&lt;/tr&gt;
    {% endfor %}
&lt;/tbody&gt;        
&lt;/tr&gt;   
&lt;/table&gt;
</code></pre>

<p>If your table is within a matrix block—which complicates things—you need to do some additional finagling.  The above link will show how to do that.</p>

CC BY-SA 3.0
2015-02-02T07:29:57.020Z
Thanks for your answer. Actually I was not looking for human readable headers, just a clean way to loop through table data, without manually typing the row.VALUE. So if my client created new tables, which I did not manually implement, they get output fine. I was looking for a solution, which does not involve a complex statement like the one Douglas McDonald mentioned (`{% for key, data in row if not key|[0,2] == "col" %}`), which seems to be impossible.
Max
CC BY-SA 3.0
2015-02-01T23:56:57.363Z
2015-02-02T00:04:31.437Z
2017-04-13T12:51:00.303Z
RitterKnight
<p>Craft's Table Field Type probably isn't the right choice, if this is what you want to achieve:</p>

<blockquote>
  <p>So if my client created new tables, which I did not manually implement, they get output fine.</p>
</blockquote>

<p>The Table Field Type isn't really meant to be created by users. Besides column names, the user also has to configure the field handle and add the field to the right Entry Type in the Settings section of the CP.</p>

<p>Then there's also the problem with dynamically accessing the field with an unknown handle from the template.</p>

<p><pre><code>{% for row in entry.<b>unknownTableFieldHandle</b> %}
{% endfor %}
</pre></code></p>

<p>But there's this new plugin by <a href="http://plugins.supercooldesign.co.uk/plugin/table-maker" rel="nofollow">Supercool: Table Maker</a>. This should do exactly what you want (see the <a href="http://plugins.supercooldesign.co.uk/plugin/table-maker/docs/templating#templating-tables" rel="nofollow">field's template syntax</a>), plus it allows the user to define the table columns.</p>

<p><pre><code>{% for row in entry.<b>myTableFieldHandle</b>.rows %}
    &lt;tr&gt;
        {% for cell in row %}
            &lt;td&gt;{{ cell }}&lt;td&gt;
        {% endfor %}
    &lt;/tr&gt;
{% endfor %}
</pre></code></p>

CC BY-SA 3.0
2015-02-02T17:09:07.973Z
Just an aside here but I thought the same thing. A client is going to go through the trouble of setting up a new field so they can output it in a template somewhere that you originally didn't setup? Doubtful. That sounds like a recipe for disaster. The potential for breakage on a responsive website is huge if they would create too many columns, for example, and most tables need to be styled. That Tablemaker plugin seems interesting but what happens on mobile? You either need to hide columns, make CSS edits or do some funky scrolling so you an see the whole table. Percentages only go so far...
RitterKnight
CC BY-SA 3.0
2015-02-02T17:12:23.887Z
@RitterKnight https://github.com/filamentgroup/tablesaw
carlcs
CC BY-SA 3.0
2015-02-02T18:17:59.963Z
No doubt tablesaw is a great tool. You'd be surprised at how "crafty" clients are... I'd be afraid that using Table Maker a client would want to use it for layout purposes as well... I've seen it happen!
RitterKnight
CC BY-SA 3.0
2015-02-05T07:53:54.190Z
Actually, this depends on your client. In this special case, it is possible and - talking of tables - a pretty usual case. It is in the nature of tables to contain a lot of different data with different columns. Sometimes you simply can't set up a different table for each of these.

On mobile you can use different strategies for that, like the mentioned tablesaw, getbootstrap's responsive tables and so on. So no worries there.
Max
CC BY-SA 3.0
2015-02-02T10:38:07.860Z
2015-02-02T10:38:07.860Z
carlcs
<p>The data is not stored twice in the database. I suspect that craft adds the additional array items when prepping the data, so that they can be referenced by either column number or column title.</p>

<p>But with a little finesse, you might be able to do something like the following, using <a href="http://twig.sensiolabs.org/doc/tags/for.html#iterating-over-keys-and-values" rel="nofollow">key, value in the for loop</a> and <a href="http://twig.sensiolabs.org/doc/filters/slice.html" rel="nofollow">twig's slice filter</a>:</p>

<pre><code>&lt;table&gt;
    {% for row in entry.myTableFieldHandle %}
        &lt;tr&gt;
            {% for key, data in row if key|slice(0,3) == 'col' %}
                &lt;td&gt;{{ data }}&lt;/td&gt;
            {% endfor %}
        &lt;/tr&gt;
    {% endfor %}
&lt;/table&gt;
</code></pre>

CC BY-SA 3.0
2015-02-02T07:26:38.283Z
Hey Douglas, thanks - this is what I was thinking. So at the moment there seems to be no way to circumvent hacks like `for key, data in row if not key|[0,2] == "col"` , right?

That's a pity. I will test right away and mark as solved then. I'll try to get some information if this might be changed in the future. Anybody actually seeing the benefit of `colX` as you can reference the column number via the array itself?
Max
CC BY-SA 3.0
2015-02-03T21:11:46.577Z
Fyi... I expanded this code to [output the entire table including headers](http://craftcms.stackexchange.com/a/6964/784).
Douglas McDonald
CC BY-SA 3.0
2015-02-05T07:47:32.310Z
Yes, thanks. I marked it as solved, as it is as good as it can get - without having to use a plugin (which is not bad, but not the way I wanted to solve it - in reference to [carlcs' answer](http://craftcms.stackexchange.com/a/6914/2253)).
Max
CC BY-SA 3.0
2017-02-09T19:12:40.170Z
Using this code as shown will fail if you have any field name starting with "col" like "color".
Nazareno Lorenzo
CC BY-SA 3.0
2015-02-01T18:31:44.993Z
2015-02-03T21:12:49.157Z
2015-02-03T21:12:49.157Z
Douglas McDonald
<p>I'm currently creating some standard templates which should help to find good defaults for matrix output. This is where I stumpled upon the somehow <em>weird</em> structure of table data.</p>

<p>Here's a simplified structure of what I want to build:</p>

<pre><code>&lt;table&gt;
{% for row in table %}
  &lt;tr&gt;
  {% for data in row %}
    &lt;td&gt;{{ data }}&lt;/td&gt;
  {% endfor %}
  &lt;/tr&gt;
{% endfor %}
&lt;/table&gt;
</code></pre>

<p>Outputting table content like this:</p>

<pre><code>{% for row in table %}
  {{ dump(row) }}
{% endfor %}
</code></pre>

<p>shows me that each row has double entries:</p>

<pre><code>array(6) {
  ["col1"]=&gt; string(7) "Hamburg"
  ["col2"]=&gt; string(7) "1730000"
  ["col3"]=&gt; string(7) "2600000"

  ["city"]=&gt; string(7) "Hamburg"
  ["population"]=&gt; string(7) "1730000"
  ["urbanPopulation"]=&gt; string(7) "2600000"
}
</code></pre>

<p>While this might make sense in some cases, I don't get it. Why is this behavior and in which cases could the convention "col1", "col2", etc. make sense?</p>

<p>On first sight, this choice is very unfortunate as it prevents dynamic table output. Sure, you could use hacks like <code>loop.index</code> to target these, but that makes the code very unreadable and ugly.</p>

<p>Does anyone have the same issue with this?</p>

<templating><table-field>
Double storage of values in table-field
# Double storage of values in table-field

(Asked by: username_0 on 2015-02-01)

I'm currently creating some standard templates which should help to find good defaults for matrix output. This is where I stumpled upon the somehow weird structure of table data.
Here's a simplified structure of what I want to build:

{% for row in table %}
  
  {% for data in row %}
    {{ data }}
  {% endfor %}
  
{% endfor %}


Outputting table content like this:
{% for row in table %}
  {{ dump(row) }}
{% endfor %}

shows me that each row has double entries:
array(6) {
  ["col1"]=> string(7) "Hamburg"
  ["col2"]=> string(7) "1730000"
  ["col3"]=> string(7) "2600000"

  ["city"]=> string(7) "Hamburg"
  ["population"]=> string(7) "1730000"
  ["urbanPopulation"]=> string(7) "2600000"
}

While this might make sense in some cases, I don't get it. Why is this behavior and in which cases could the convention "col1", "col2", etc. make sense?
On first sight, this choice is very unfortunate as it prevents dynamic table output. Sure, you could use hacks like loop.index to target these, but that makes the code very unreadable and ugly.
Does anyone have the same issue with this?

**Tags:** templating, table-field


---

## 4 answers

### Answer by username_4 on 2015-02-01. Score: 4 | Accepted answer

The data is not stored twice in the database. I suspect that craft adds the additional array items when prepping the data, so that they can be referenced by either column number or column title.
But with a little finesse, you might be able to do something like the following, using key, value in the for loop and twig's slice filter:

    {% for row in entry.myTableFieldHandle %}
        
            {% for key, data in row if key|slice(0,3) == 'col' %}
                {{ data }}
            {% endfor %}
        
    {% endfor %}

> **Comments:**
> **username_0**: Hey Douglas, thanks - this is what I was thinking. So at the moment there seems to be no way to circumvent hacks like `for key, data in row if not key|[0,2] == "col"` , right?  That's a pity. I will test right away and mark as solved then. I'll try to get some information if this might be changed in the future. Anybody actually seeing the benefit of `colX` as you can reference the column number via the array itself?  
> **username_4**: Fyi... I expanded this code to [output the entire table including headers](http://craftcms.stackexchange.com/a/6964/784).  
> **username_0**: Yes, thanks. I marked it as solved, as it is as good as it can get - without having to use a plugin (which is not bad, but not the way I wanted to solve it - in reference to [username_3' answer](http://craftcms.stackexchange.com/a/6914/2253)).  
> **username_5**: Using this code as shown will fail if you have any field name starting with "col" like "color".  

---

### Answer by username_1 on 2015-02-01. Score: 2

username_0 - it looks like there might be an issue in how you are looping through the table. Table data is stored as JSON in the database, so calling entry.myTable should give you an array of rows, with each row as a sub-array of values.
From your example:
{% if entry.myTable | length %}
    
        
            City
            Population
            Urban Population
        
        
        {% for row in entry.myTable %}
            
                {{row.city}}
                {{row.population}}
                {{row.urbanPopulation}}
            
        {% endfor %}        
        
    
{% endif %}

will check to see if the table field exists and has data, then will go through each row, returning values by row.columnName.
Hope this helps!

> **Comments:**
> **username_0**: hey, thanks for the reply - sure, you're right. But this way I can't write a template which I can use dynamically - as I'd have to write the handles manually.  The loop actually does work, but I get DOUBLE output, because not only `{{row.columnName}}` exists, but also `{{row.col1}}`. This is the cause why, if I loop through dynamically I get 2x Hamburg. You see the problem?  
> **username_1**: What are you trying to dynamically pull, the table headers?  
> **username_0**: I want to dynamically output the table data, no matter which column names the user creates.  This would actually work, if the Craft team would not store the data twice. And I don't know why they did it.  `array(2) { ["col1"]=> string(7) "Hamburg", ["city"]=> string(7) "Hamburg" }`  so you can query by using `{{ row.col1 }}` and `{{ row.columnName }}` but you cant loop through dynamically, because you get all values twice.  
> **username_0**: Sorry, aberkie, I just edited my example - I had an error in the first sample. The second loop was misleading! ->   `{% for data in row %}     <td>{{ data }}</td>   {% endfor %}`  is the right one  

---

### Answer by username_2 on 2015-02-01. Score: 1

Taken from username_3' example, you'll probably want the clean "human readable" table headers. Looks like those aren't handed out in the template by default but you can get 'em with a trip to getFieldByHandle.
{% set field = craft.fields.getFieldByHandle('whateverField') %}

So something like this:



  {% set field = craft.fields.getFieldByHandle('whateverField') %}
  {% for column in field.settings.columns %}
    {{ column.heading }}
  {% endfor %}


The just spit out the rest of the table like normal:

    {% for row in entry.whateverField %}
      {{ row.col1 }}{{ row.col2 }}
    {% endfor %}
        
   


If your table is within a matrix block—which complicates things—you need to do some additional finagling.  The above link will show how to do that.

> **Comments:**
> **username_0**: Thanks for your answer. Actually I was not looking for human readable headers, just a clean way to loop through table data, without manually typing the row.VALUE. So if my client created new tables, which I did not manually implement, they get output fine. I was looking for a solution, which does not involve a complex statement like the one username_4 mentioned (`{% for key, data in row if not key|[0,2] == "col" %}`), which seems to be impossible.  

---

### Answer by username_3 on 2015-02-02. Score: 0

Craft's Table Field Type probably isn't the right choice, if this is what you want to achieve:

So if my client created new tables, which I did not manually implement, they get output fine.

The Table Field Type isn't really meant to be created by users. Besides column names, the user also has to configure the field handle and add the field to the right Entry Type in the Settings section of the CP.
Then there's also the problem with dynamically accessing the field with an unknown handle from the template.
{% for row in entry.unknownTableFieldHandle %}
{% endfor %}

But there's this new plugin by Supercool: Table Maker. This should do exactly what you want (see the field's template syntax), plus it allows the user to define the table columns.
{% for row in entry.myTableFieldHandle.rows %}
    
        {% for cell in row %}
            {{ cell }}
        {% endfor %}
    
{% endfor %}

> **Comments:**
> **username_2**: Just an aside here but I thought the same thing. A client is going to go through the trouble of setting up a new field so they can output it in a template somewhere that you originally didn't setup? Doubtful. That sounds like a recipe for disaster. The potential for breakage on a responsive website is huge if they would create too many columns, for example, and most tables need to be styled. That Tablemaker plugin seems interesting but what happens on mobile? You either need to hide columns, make CSS edits or do some funky scrolling so you an see the whole table. Percentages only go so far...  
> **username_3**: @username_2 https://github.com/filamentgroup/tablesaw  
> **username_2**: No doubt tablesaw is a great tool. You'd be surprised at how "crafty" clients are... I'd be afraid that using Table Maker a client would want to use it for layout purposes as well... I've seen it happen!  
> **username_0**: Actually, this depends on your client. In this special case, it is possible and - talking of tables - a pretty usual case. It is in the nature of tables to contain a lot of different data with different columns. Sometimes you simply can't set up a different table for each of these.  On mobile you can use different strategies for that, like the mentioned tablesaw, getbootstrap's responsive tables and so on. So no worries there.  

---

