bluejack

bluejack

What is defeating me today:

I want a component, included from a layout template, to have access to conn and/or assigns

What I am doing:

  1. Add a plug to the browser pipeline that takes information from the conn session and puts it into the assigns map.
    user = get_session(conn, :current_user)
    conn = assign(conn, :avatar, user.avatar)
    conn = assign(conn, :userid, user.id)

So far so good; if I then access this from a controller-driven template, we’re happy campers.

However, in components included from a layout template, assigns does NOT contain these values, and instead contains only %{__changed__: nil}

Sequentially, via logging, I can see that:

  1. The plug runs, and assigns the values, which are viewable in the conn struct.
  2. They layout component renders, but assigns at this point has the __changed__ value only
  3. The controller renders, at which point assigns is back to what I expected it to be.

So: something is shadowing assigns for the layout/component sequence? Where does that come from?

I presume this is a bug in my code, but I am not even sure where to look for it.

UPDATE – none of this is for Live View; this is all layout / controller driven content. Much of the prior conversations I have been able to find pertain to debugging live view interactions.

UPDATE – so, I have come to understand that “assigns” for a component is only what is directly passed in from the parent template:

     <.account_widget />

Which is implemented by a module with method:

  def account_widget(assigns) do

    ~H"""
    <div><%= @avatar %></div>
    """
  end

Only gets paramaters passed into it from the dot-notation, which in this case does not include @avatar – even though that data IS on the assigns portion of the conn struct.

So!

I can either pass the specific data I want down the “call stack” of template inclusion, from the point where it IS available – UGLY! –

OR

I can obtain the conn object from the component module? Is this possible? It certainly seems like it should be, but it’s not obvious how. Simply importing Plug.Conn does not seem sufficient. Thoughts on best practice here? This doesn’t seem like it should be such a difficult scenario, but other than doing the ugly thing, I’m a bit baffled.

UPDATE #3

So, I sort of successfully implemented the ugly approach, but it gets uglier when an attribute is not available: passing a nil value down the inclusion chain does not pass the compiler test.

Some of the components in the chain are pure templates, no explicit module in which to handle alternate attribute values or set defaults.

So, not only does it make the component NOT self contained, but it would force all kinds of hinky logic up the inclusion chain.

There MUST be a way to access the conn struct from a component! Or else I am really using this framework in the wrong way.

Showing Posts 1 to 5

cmo

cmo

This is the way.

msmithstubbs

msmithstubbs

My guess is there might be some misconceptions here - so I’m glad you’ve posted on the forum!

You probably don’t want to access the conn struct from the component. Just give it the minimal data it needs to render.

<.account_widget avatar={@avatar} />
bluejack

bluejack OP

Well, having gone through the api/function docs more closely, I came to the conclusion that y’all are telling me and ended my implementation there.

I don’t love it as an answer, as it means that components cannot be nearly as independently self-contained as one might want in many use cases, and with nested components, it means extra passing-down-the-stack of stuff that could have been independently obtained.

But that is probably my new-ness to the framework showing, and in due course I shall see the overall elegance of such a limitation.

In any case… thanks for the help & confirmation!

msmithstubbs

msmithstubbs

I understand the feeling. I think there can be some adjustment required if you’re coming from different frameworks. But stick with it if you can. Hopefully it will start to make sense and you’ll come to love it :grin:

Hypothetically you could just pass the whole conn struct around everywhere and each component consumes it and does whatever it wants. The drawback I find with that is that at some point you might change what’s in the conn, or how it’s structured, and then a bunch of components all over the place break.

You’re probably already aware of it but I have found it useful to deal with nil values by conditionally rendering a component with the :if directive. For example, if the account widget should only render if the @avatar value is available:

<.account_widget avatar={@avatar} :if={assigns[:avatar]} />
bluejack

bluejack OP

Thanks for the additional tips @msmithstubbs Matt. Absolutely: I prefer to use a framework as it is intended to be used. Makes everyone’s lives easier.

I’m particularly grateful for the tip on :if – I have used that on standard elements, and (doh) it didn’t occur to me it could also be used on components. Ultimately not what I want to do in this instance, but definitely a useful tool!

— All posts loaded —

Where Next? Top

Trending in Questions Top

RSP87
I’m working on a project that simulates the bumbl example in the programming phoenix book. It acts almost like an email client. We have a...
New
kszambelanczyk
Hello! Could someone please give me a help/sample code, how to delete a file from s3 using waffle/waffle_ecto from Phoenix app. I creat...
New
RemyXRenard
I’m seeing that a list inside a Kino.DataTable will be interpreted as a charlist, even if the Kino.configure() is set to charlists: :as_l...
New
velrest
So my question is quite simple and i have found no conclusive answer on forum, google or AI. Should we use :erlang.float for Integer to ...
New
samoloth
Hi, I’ve just set up an application with ash_authentication. There is only magic link strategy for now, so there is no confirmation add o...
New
FlyingNoodle
If a change or preparation module uses Ash.Changeset.get_argument/2 or Ash.Query.get_argument/2 (or any of the other get_argument functio...
New
ryanwinchester
apply_graft/2 doesn’t rewrite an add_many sub-workflow’s deps on an add step. Grafted jobs cancel with “upstream job was deleted” Version...
New

Other Trending Topics Top

mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
garrison
Hobbes is a low-level distributed database for the Elixir programming language. Hobbes provides a simple, safe, and scalable storage lay...
New
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Dmk
Xamal is a deployment tool for Elixir apps that deploys native releases to bare metal servers over SSH. It’s a port of GitHub - basecamp/...
New
Damirados
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge &amp; Solve. They are GUI (Emerge) and State management (S...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews