Is there more documentation for Hanami views and parts?

Hello. :wave: I’ve been trying to understand how to leverage parts within my views by reading the Dry Views documentation but seem to fail to properly get parts to work within my Hanami 2.0.0 application. Is there some special wiring necessary to use a custom part instead of always seeing the generic Hanami::View::Part objects?

I have a working Hanami demonstration application here that you can play with where I used HTMX to send HTML over the wire to nice effect. …but if you look closely, you’ll notice I’m using duplicated template code in lieu of being able to leverage more of the power of views and parts.

I know the view layer isn’t fully formed yet but I’d definitely be grateful to learn how to wire this up properly (or at least point me to source code examples that would direct me in the right direction). Thanks. :bow:

Hi @bkuhlmann! Cool to see you’re digging into all of this :slight_smile:

Sorry, we don’t have any more docs than what already exists for the dry-view. We’ll of course be updating everything as we get closer to finishing the full integration of hanami-view into the broader app framework and prepare that for release (work on this is already underway, but the docs part will still be a while).

So when you’re using hanami-view standalone, the way to get custom part classes returned is to configure a part_namespace on a view class. I’d recommend you do this on the base class for a given view class hierarchy. It’d look something like this:

module MyNamespace # app or slice or what have you
  class View < Hanami::View
    config.part_namespace = MyNamespace::Views::Parts # or whatever you like
  end
end

Then any exposure in a view subclass will be matched with a part class from MyNamespace::Views::Parts, if one exists.

The good thing about doing this in Hanami is that we take care of this for you! By default, we configure the part_namespace to match SliceNamespace::Views::Parts, if that module exists or can be autoloader.

I’ve just tested this in my personal Hanami demo app (GitHub - decafsucks/decafsucks: Rebuilding decafsucks.com as an OSS Hanami 2.0 example app) by creating a slices/main/views/parts/cafe.rb that looks like this:

module Main
  module Views
    module Parts
      class Cafe < Hanami::View::Part
      end
    end
  end
end

My base view class for this slice looks like this (apologies for the FIXME, by the time we release hanami-view 2.0 this will be an empty class):

# auto_register: false
# frozen_string_literal: true

module Main
  class View < Decafsucks::View
    # FIXME(Hanami): base slice views should override paths from the base app view
    config.paths = [File.join(File.expand_path(__dir__), "templates")]
  end
end

But the important thing to note here is that there is no explicit config.part_namespace assignment.

After that I tested the config in the console:

Main::View.config.part_namespace
# => Main::Views::Parts

Looking good!

Lastly, just to really be sure that things are working like we expect, I loaded my "views.home.show" view from the main slice and confirmed my new part class was being used:

main["views.home.show"].call.locals[:cafes].first
# => #<Main::Views::Parts::Cafe name=:cafe value=#<ROM::Struct::Cafe id=1>>

Looks like we’re in business!

Please let me know if that makes sense, and how you go getting it setup from here!

Thanks! OK, I see where I went wrong. Originally, I had this structure (with top level structure removed for simplicity):

/views
/parts

I didn’t realize that parts are a sub-structure within the views. So like this;

/views/parts

Once I did that, everything clicked into place. At one point, I did attempt to configure the part_namespace but – as you highlighted above – I realized Hanami was already dynamically registering those parts for me which is nice.

This is the first time I’ve actually seen views and parts work together before. Definitely a fun and new experience. :tada: