How to add a row counter column to an html table generated from ecto

I hope this is not going to sound very dumb.
We have a set of records coming to the application from ecto.
We use these records to create our table but we want to add a column to show the record number. So this would be a simple serial number incrementing the value as each row is generated from the loop.
Being that elixir is immutable the methods we are used to will not work. We have been searching the internet for a few hours but with no success.
For this we also need to think about pagination. So the idea would be to break records in groups of five for the first group our counter would start at 1 for the second group the counter would start at 6 and so forth.
Any suggestion how we should go ahead and implement this would be greatly appreciated.

The Enum module is probably the first place to look at.

Enum.with_index()

Enum.chunk_every()

Pagination is another beast, and should probably be managed by db (limit, offset).

2 Likes

Hi thank you for this suggestion, however this is still very confusing.
Assuming that we get a list of records from ecto, that we process with a for loop like so:
“<%= for record<- @records do %>
<\tr>
<\td><%= record.title %></td>
<\td><%= record.description %></td>
</tr>
<%= end %>”
How could we implement Enum.with_index() or Enum.chunk_every() in this scenario.
In the above code we need to add a column on the table to show the serial number of the record that will be auto incrementing as the table gets populated.
I am mentioning pagination because regardless of how you get the records from ecto this incrementing value will have a different starting point depending on the set you are looking at.
If you could share some code with such an implementation that would be fantastic.
I hope this makes some sense.

Not sure if this is what you are looking for.

<%= for {record, index} <- Enum.with_index(@records) do %>
<tr>
<td><%= record.title %></td>
<td><%= record.description %></td>
<td><%= @page + index %></td>
</tr>
<%= end %>

With this you will have to assign the current @page from pagination to your template.

You can try a more elaborate solution with Ecto virtual field and row_number window function to get the row number assigned to the ecto schema too.

Edit: fixed index order in Enum.with_index function to last position as mentioned by @kokolegorille

2 Likes

It is not clear what You want to achieve… is it a virtual index, a field in the db?

What will be the use of this record when You start to order by different column?

There is already one auto increment field, it is inserted_at.

If it is virtual, then Enum.with_index would do the trick, as mentionned in the previous post.

If it is a real field, what would this field used for?

If You are using postgres, You can use :serial or :bigserial field.

I made such field, called position, and used to sort list of records per scope.

It is not on hex, but I use this as a replacement for acts_as_list and nested_set from Ruby.

1 Like

Hi again,

So this is going to be just a counter appearing in the html generated by the application for cosmetic purposes. It will have no usage in the logic of the application. The purpose is to have a counter just to make the table more readable.
For this I would be surprised if we had to involve ecto or the db in any way.
I will be trying the Enum.with_index function phrased the way phcurado suggests although I believe I need to first understand how Enum.with_index actually works. When I initially read the documentation I thought that with this function we would iterate through the records which would not make much sense since we are already iterating through the records with the for loop. I guess all this function does is add an index to a list.
In any case for your question the purpose of this counter is purely cosmetic and only relevant in the html view.
I hope this clarifies what we are looking for some.

Enum.with_index adds an index to each element of the collection.

This is what You need, and not complicate to use, like the code provided by @phcurado

Except the index is at the last position…

["a", "b", "c"] |> Enum.with_index()
[{"a", 0}, {"b", 1}, {"c", 2}]
2 Likes

Yeah this sounds like what we need. I will research this a bit more and if there is anything else I will post back on the thread. In any case thank you very much for helping out.