kaffy icon indicating copy to clipboard operation
kaffy copied to clipboard

[FEATURE-REQUEST] custom html tag for show/edit page

Open sulphur opened this issue 4 years ago • 7 comments

Describe the problem you're proposing to solve Since the show and edit are on the same page it would be good to be able to put custom HTML tags that aren't submitted as well. For example, there is no easy way to display a big image on the show/edit page. I know that this can be done via custom Ecto type but in my case, I already have a custom Ecto type from my upload lib (Arc/Waffle). Also, I'm not a fan of adding an admin logic code to the application code.

Describe the solution you'd like be able to add custom html tags to show/edit form so something like:

  def form_fields(_) do
    [
      status: %{choices: [{"Valid", "valid"}, {"New", "new"}, {"Invalid", "invalid"}]},
      id_card_front: %{name: "ID Front", type: :safe_html, value: fn v -> "<img src='#{v.url}'" end }

    ]
  end

Describe alternatives you've considered I was considering going with a custom page for the moment.

Additional context Add any other context or screenshots about the feature request here.

I can try to implement it but first, I need to know whether this kind of approach is ok with you guys. Or maybe you know some other alternatives that don't require a custom Ecto type since.

Cheers Piotr

sulphur avatar Oct 14 '20 15:10 sulphur

I've been playing around and basically, something like that would do the trick :

https://github.com/aesmail/kaffy/compare/master...sulphur:master

sulphur avatar Oct 14 '20 17:10 sulphur

Hey @sulphur Thanks for opening this issue. I do see the need for this. However, I feel like it needs to be discussed a bit more to come up with a well-designed solution.

Currently, we have the "custom types" solution which does work for your case (as can be seen here and here). Admittedly, it's more involved by design and your solution is much simpler for simpler cases.

Your changes seem good and working, but it needs to be a bit more "integrated" and polished. I believe if we're adding a :safe_html type, we should make it universal and maybe use it internally to build the other fields. Something like:

def build_text_field(), do: something() |> build_safe_html()
def build_image_field(), do: logic() |> build_safe_html()
def build_safe_html(), do: {:safe, some_html}

This way, in the future, if we want to add more fields, it would have a standard way of doing it. I like this feature, but let's explore a few more implementations so we can decide on how to proceed.

aesmail avatar Oct 14 '20 18:10 aesmail

Yeah, I totally agree my "example" was just to illustrate the need ;) the real solution should be something more elaborate ;) like the one you suggest. I had the same idea about having a generic function that is used by specific functions that facilitate the display.

sulphur avatar Oct 14 '20 22:10 sulphur

I have a very similar need... I'd like to customize a form field with a custom input, but I'm also already using a custom type and don't like to mix application code with web (admin).

So maybe the form_fields could accept something like

def form_fields(_) do
    [
      id_card_front: %{name: "ID Front", type: CustomType }
    ]
  end

and this custom type must have the function def render_form(conn, changeset, form, field, options) similar to the approach that you already have, but a bit more flexible since doesn't need to be an ecto type.

By the way, love this library and think it's very promising :)

jotaviobiondo avatar Oct 19 '20 18:10 jotaviobiondo

Hi, @aesmail I've created a image_preview type and rename safe_html to custom_html. I haven't combined both since it would be very similar to content_tag function. So basically we can have 2 approaches for image_preview either using something linke ;

     id_card_back: %{
        name: "ID Back",
        type: :image_preview,
        value_fn: fn v -> TotoWeb.IdBackUploader.url({v.id_back_file, v}, :original) end
      },

or

      id_card_back: %{
        name: "ID Back",
        type: :custom_html,
        value_fn: fn v -> "<img src='#{ToToWeb.IdNextToFaceUploader.url({v.id_next_to_face_file, v}, :original)}'/>" end
      },

we can also pass url directly and some style :

     id_card_back: %{
        name: "ID Back",
        type: :image_preview,
        inline_css: "width: 40rem",
        value: "https://some-url.com"
      },

sulphur avatar Oct 20 '20 14:10 sulphur

I've created a PR here : https://github.com/aesmail/kaffy/pull/161

sulphur avatar Oct 20 '20 14:10 sulphur

@jotaviobiondo I agree. It does make sense to provide type with a module which handles how the field is rendered. I think this will be the case for the next release.

aesmail avatar Oct 20 '20 17:10 aesmail