niccolox

niccolox

Solid (Liquid) templating basic for loop in Phoenix

Using the Solid hex, which is a Liquid templating language implementation in Phoenix 1.6

How to I get a for loop working with a Phoenix generated list of structs, I am suspecting there is some format particular to Solid

iex(2)> alias App.Channels
App.Channels
iex(3)> channels = Channels.list_channels()
[debug] QUERY OK source="channels" db=10.2ms decode=1.3ms queue=12.0ms idle=788.2ms
SELECT c0."id", c0."about", c0."address", c0."banner", c0."contact", c0."description", c0."disclaimer", c0."footer", c0."icon", c0."meta_description", c0."name", c0."primary_color", c0."privacy", c0."secondary_color", c0."slug", c0."status", c0."tagline", c0."terms", c0."is_free?", c0."is_published?", c0."is_listed?", c0."is_featured?", c0."is_private?", c0."is_invitable?", c0."is_previewable?", c0."is_subscribable?", c0."is_suspended?", c0."snowflake", c0."creator_id", c0."owner_id", c0."contact_id", c0."website_id", c0."inserted_at", c0."updated_at" FROM "channels" AS c0 []
[
  %App.Channels.Channel{
    website_id: 1,
    is_listed?: nil,
    updated_at: ~N[2021-11-07 14:49:20],
    description: nil,
    banner: nil,
    status: nil,
    is_free?: false,
    owner_id: 1,
    secondary_color: nil,
    is_previewable?: nil,
    disclaimer: nil,
    meta_description: nil,
    is_private?: nil,
    snowflake: nil,
    icon: nil,
    hosts: #Ecto.Association.NotLoaded<association :hosts is not loaded>,
    tagline: nil,
    name: "niccolox-channel",
    channel_hosts: #Ecto.Association.NotLoaded<association :channel_hosts is not loaded>,
    address: nil,
    privacy: nil,
    terms: nil,
    primary_color: nil,
    is_suspended?: nil,
    is_invitable?: nil,
    __meta__: #Ecto.Schema.Metadata<:loaded, "channels">,
    inserted_at: ~N[2021-11-07 14:49:20],
    posts: #Ecto.Association.NotLoaded<association :posts is not loaded>,
    is_published?: nil,
    contact: nil,
    slug: nil,
    is_subscribable?: nil,
    is_featured?: nil,
    creator_id: nil,
    about: nil,
    website: #Ecto.Association.NotLoaded<association :website is not loaded>,
    id: 1,
    footer: nil,
    contact_id: nil
  },
  %App.Channels.Channel{
    website_id: 1,
    is_listed?: nil,
    updated_at: ~N[2021-11-07 14:49:20],
    description: nil,
    banner: nil,
    status: nil,
    is_free?: false,
    owner_id: 1,
    secondary_color: nil,
    is_previewable?: nil,
    disclaimer: nil,
    meta_description: nil,
    is_private?: nil,
    snowflake: nil,
    icon: nil,
    hosts: #Ecto.Association.NotLoaded<association :hosts is not loaded>,
    tagline: nil,
    name: "free-channel",
    channel_hosts: #Ecto.Association.NotLoaded<association :channel_hosts is not loaded>,
    address: nil,
    privacy: nil,
    terms: nil,
    primary_color: nil,
    is_suspended?: nil,
    is_invitable?: nil,
    __meta__: #Ecto.Schema.Metadata<:loaded, "channels">,
    inserted_at: ~N[2021-11-07 14:49:20],
    posts: #Ecto.Association.NotLoaded<association :posts is not loaded>,
    is_published?: nil,
    contact: nil,
    slug: nil,
    is_subscribable?: nil,
    is_featured?: nil,
    creator_id: nil,
    about: nil,
    website: #Ecto.Association.NotLoaded<association :website is not loaded>,
    id: 2,
    footer: nil,
    contact_id: nil
  },
  %App.Channels.Channel{
    website_id: 2,
    is_listed?: nil,
    updated_at: ~N[2021-11-07 14:49:20],
    description: nil,
    banner: nil,
    status: nil,
    is_free?: false,
    owner_id: 1,
    secondary_color: nil,
    is_previewable?: nil,
    disclaimer: nil,
    meta_description: nil,
    is_private?: nil,
    snowflake: nil,
    icon: nil,
    hosts: #Ecto.Association.NotLoaded<association :hosts is not loaded>,
    tagline: nil,
    name: "website-channel",
    channel_hosts: #Ecto.Association.NotLoaded<association :channel_hosts is not loaded>,
    address: nil,
    privacy: nil,
    terms: nil,
    primary_color: nil,
    is_suspended?: nil,
    is_invitable?: nil,
    __meta__: #Ecto.Schema.Metadata<:loaded, "channels">,
    inserted_at: ~N[2021-11-07 14:49:20],
    posts: #Ecto.Association.NotLoaded<association :posts is not loaded>,
    is_published?: nil,
    contact: nil,
    slug: nil,
    is_subscribable?: nil,
    is_featured?: nil,
    creator_id: nil,
    about: nil,
    website: #Ecto.Association.NotLoaded<association :website is not loaded>,
    id: 3,
    footer: nil,
    contact_id: nil
  },
  %App.Channels.Channel{
    website_id: 2,
    is_listed?: nil,
    updated_at: ~N[2021-11-07 14:49:20],
    description: nil,
    banner: nil,
    status: nil,
    is_free?: false,
    owner_id: 1,
    secondary_color: nil,
    is_previewable?: nil,
    disclaimer: nil,
    meta_description: nil,
    is_private?: nil,
    snowflake: nil,
    icon: nil,
    hosts: #Ecto.Association.NotLoaded<association :hosts is not loaded>,
    tagline: nil,
    name: "local-channel",
    channel_hosts: #Ecto.Association.NotLoaded<association :channel_hosts is not loaded>,
    address: nil,
    privacy: nil,
    terms: nil,
    primary_color: nil,
    is_suspended?: nil,
    is_invitable?: nil,
    __meta__: #Ecto.Schema.Metadata<:loaded, "channels">,
    inserted_at: ~N[2021-11-07 14:49:20],
    posts: #Ecto.Association.NotLoaded<association :posts is not loaded>,
    is_published?: nil,
    contact: nil,
    slug: nil,
    is_subscribable?: nil,
    is_featured?: nil,
    creator_id: nil,
    about: nil,
    website: #Ecto.Association.NotLoaded<association :website is not loaded>,
    id: 4,
    footer: nil,
    contact_id: nil
  }
]
iex(4)> template = "{% for channel in channels %} channel {% else %} The collection is empty. {% endfor %}"
"{% for channel in channels %} channel {% else %} The collection is empty. {% endfor %}"
iex(5)> {:ok, template} = Solid.parse(template)
{:ok,
 %Solid.Template{
   parsed_template: [
     tag: [
       {Solid.Tag.For,
        [
          field: ["channel"],
          enumerable: [field: ["channels"]],
          parameters: %{},
          result: [text: [" channel "]],
          else_exp: [result: [text: [" The collection is empty. "]]]
        ]}
     ]
   ]
 }}
iex(6)> Solid.render(template, %{ "channels" => channels }) |> to_string
" channel  channel  channel  channel "

but when I try to access channel.name I get an error

iex(7)> template = "{% for channel in channels %} {{ channel.name }} {% else %} The collection is empty. {% endfor %}"
"{% for channel in channels %} {{ channel.name }} {% else %} The collection is empty. {% endfor %}"
iex(8)> {:ok, template} = Solid.parse(template)
{:ok,
 %Solid.Template{
   parsed_template: [
     tag: [
       {Solid.Tag.For,
        [
          field: ["channel"],
          enumerable: [field: ["channels"]],
          parameters: %{},
          result: [
            text: [" "],
            object: [argument: [field: ["channel", "name"]], filters: []],
            text: [" "]
          ],
          else_exp: [result: [text: [" The collection is empty. "]]]
        ]}
     ]
   ]
 }}
iex(9)> Solid.render(template, %{ "channels" => channels }) |> to_string
** (UndefinedFunctionError) function App.Channels.Channel.fetch/2 is undefined (App.Channels.Channel does not implement the Access behaviour)
    (app 0.1.0) Appbot.Channels.Channel.fetch(%App.Channels.Channel{website_id: 1, is_listed?: nil, updated_at: ~N[2021-11-07 14:49:20], description: nil, banner: nil, status: nil, is_free?: false, owner_id: 1, secondary_color: nil, is_previewable?: nil, disclaimer: nil, meta_description: nil, is_private?: nil, snowflake: nil, icon: nil, hosts: #Ecto.Association.NotLoaded<association :hosts is not loaded>, tagline: nil, name: "niccolox-channel", channel_hosts: #Ecto.Association.NotLoaded<association :channel_hosts is not loaded>, address: nil, privacy: nil, terms: nil, primary_color: nil, is_suspended?: nil, is_invitable?: nil, __meta__: #Ecto.Schema.Metadata<:loaded, "channels">, inserted_at: ~N[2021-11-07 14:49:20], posts: #Ecto.Association.NotLoaded<association :posts is not loaded>, is_published?: nil, contact: nil, slug: nil, is_subscribable?: nil, is_featured?: nil, creator_id: nil, about: nil, website: #Ecto.Association.NotLoaded<association :website is not loaded>, id: 1, footer: nil, contact_id: nil}, "name")
    (elixir 1.12.2) lib/access.ex:285: Access.get/3
    (solid 0.10.0) lib/solid/context.ex:90: Solid.Context.do_get_in/2
    (elixir 1.12.2) lib/enum.ex:1582: Enum."-map/2-lists^map/1-0-"/2
    (solid 0.10.0) lib/solid/context.ex:21: Solid.Context.get_in/3
    (solid 0.10.0) lib/solid/argument.ex:35: Solid.Argument.get/3
    (solid 0.10.0) lib/solid/object.ex:11: Solid.Object.render/3
    (solid 0.10.0) lib/solid.ex:102: Solid.do_render/3
    (solid 0.10.0) lib/solid.ex:85: anonymous fn/3 in Solid.render/3
    (elixir 1.12.2) lib/enum.ex:2385: Enum."-reduce/3-lists^foldl/2-0-"/3
    (solid 0.10.0) lib/solid.ex:83: Solid.render/3
    (solid 0.10.0) lib/solid/tag/for.ex:96: anonymous fn/6 in Solid.Tag.For.do_for/5
    (elixir 1.12.2) lib/enum.ex:2385: Enum."-reduce/3-lists^foldl/2-0-"/3
    (solid 0.10.0) lib/solid/tag/for.ex:89: Solid.Tag.For.do_for/5
    (solid 0.10.0) lib/solid/tag.ex:89: Solid.Tag.eval/3
    (solid 0.10.0) lib/solid.ex:111: Solid.render_tag/3
    (solid 0.10.0) lib/solid.ex:85: anonymous fn/3 in Solid.render/3
    (elixir 1.12.2) lib/enum.ex:2385: Enum."-reduce/3-lists^foldl/2-0-"/3
    (solid 0.10.0) lib/solid.ex:83: Solid.render/3
    (solid 0.10.0) lib/solid.ex:71: Solid.render/3
iex(9)>

First Post!

cmo

cmo

You can see from that stacktrace it is suggesting rather strongly that it is calling get_in, which is not going to work on your struct unless you implement the Access behaviour.

You could read the docs/source for Solid.render or naively try turning your channels into maps to see if that works.

Last Post!

cmo

cmo

Sorry, I have no knowledge of this Solid thing.

Did you try it using Map.from_struct/1? You can use whatever call you want/need to get the data how you need it.

I’ve never used the phoenix context generators apart from the initial “let’s see how they work”. Remeber “contexts aren’t a thing” :wink:

Where Next?

Popular in Questions Top

vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
Lily
In templates/appointment/index.html.eex: &lt;%= for appointment &lt;- @appointments do %&gt; &lt;tr&gt; &lt;td&gt;&lt;%= appoi...
New
Darmani72
If I have a post route which an argument: post /my_post_route/:my_param1, MyController.my_post_handler How would get the post params ...
New
aadeshere1
I have a another noob question about loop. Since elixir is immutable, while loop is not directly possible. total = 10 while total != 0 ...
New
sergio_101
I am VERY much an elixir newbie. I have taken one elixir course and one phoenix course on Udemy. During that course, I saw the instructor...
New
SoCreat
i’m a new one to elixir which editor can i use vs code? or atom? Thanks! :smiley:
New
WestKeys
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New

Other popular topics Top

msaraiva
Surface is an experimental library built on top of Phoenix LiveView and its new LiveComponent API that aims to provide a more declarative...
564 44167 214
New
saif
Hello everyone, Long time lurker first time poster here. I’ve recently begun working on Elixir full-time again! :raised_hands: It’s been...
New
TunkShif
This post is an instruction guide to help you setup your Neovim for Elixir development from scratch. It includes general information on h...
274 42576 114
New
Harrisonl
We have an ECS cluster with 4 services, where each task joins a single cluster, via discovery ECS discovery service. Currently when I de...
New
senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New
AstonJ
Posting this to see if we can make things easier for people to get into Neovim. If you use Neovim and have a favourite distro please let ...
New

We're in Beta

About us Mission Statement