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

openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New
fireproofsocks
Forgive me if this is obvious, but how does one delete a database record WITHOUT selecting it first? Ecto.Repo — Ecto v3.14.0 has exampl...
New
komlanvi
Hi everyone, I was playing with phoenix liveView but I run into an issue. I have a form and want to validate each input text when the te...
New
aalberti333
As the title describes, I’m trying to run Enum.map() over a list of key/value pairs, where the value is a map. My data looks like this: ...
New
marius95
Hello everyone, I try to use an Javascript Event Handler in my root.html.leex file. Therefore I created a function in the app.js file: ...
New
romenigld
I am trying to run a deploy with docker and I successfully runned with this command: docker build -t romenigld/blog-prod . but when I t...
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

Other popular topics Top

nobody
Hi! In PHP: $_SERVER[‘SERVER_ADDR’] - in Elixir? Searched the docs for ip address and the web, no good results. Thanks!
New
hariharasudhan94
I would like to know what is the best IDE for elixir development?
New
Brian
What is the proper way to load a module from a file in to IEX? In the python world, doing something like this pretty standard: from ....
New
nsuchy
Hi. I’ve noticed that Windows Powershell has it’s own IEX command and you cannot access Elixir’s IEX due to the conflict. This isn’t a cr...
New
AstonJ
Seen any cool LiveView demos, sample apps or examples? Please post them here! :003:
New
Patoshizzle
After calling mix ecto.create I get this error: 17:00:32.162 [error] GenServer #PID&lt;0.412.0&gt; terminating ** (Postgrex.Error) FATAL...
New

We're in Beta

About us Mission Statement