willoma / bulma-gomponents

Bulma helpers for Gomponents
MIT License
10 stars 1 forks source link

Sometimes need some ability to select on which element a child should apply (raised for b.Select and HTMX attributes) #5

Closed chrismalek closed 6 months ago

chrismalek commented 6 months ago

I apologize for the issues if they are bugging you. If you open the GH Disucssions I find those better for code sharing and just general questions.

I am trying to integrate this library with some HTMX functionality. I just noticed the bulma.select is misbehaving. Well at least according to my current naive understanding of how the library works as well as gomponents.

I think this is because in Bulma the select is wrapped in a div and the hx attribute is being added to the div and not the select element. The other b. form controls don't seem to have this issue.

Truncated Imports for clarity:


import (

g "github.com/maragudk/gomponents"
hx "github.com/maragudk/gomponents-htmx"
b "github.com/willoma/bulma-gomponents"
"github.com/willoma/bulma-gomponents/el"
)

I have this function that returns a bulma dropdown. I want to add an htmx attribute to the select element. The hx.post is getting added to the div and not the select element which makes sense (sort of).

The hx.Post(RouteAdminQuestionFormPathFull) post is just dropped from the generated HTML.


func (q Question) bulmaAdminAnswerTypeField() b.Element {

    dropDown :=

        b.Field(
            b.Label(
                q.getFieldLabel(answerTypeFieldName),
            ),
            b.Control(
                b.Select(
                    hx.Post(RouteAdminQuestionFormPathFull),

                    b.FullWidth,
                    b.Option(answerTypeLongText, getAnswerTypeLabel(answerTypeLongText)),
                    b.Option(answerTypeShortText, getAnswerTypeLabel(answerTypeShortText)),
                    b.Option(answerTypeEnumerationSingle, getAnswerTypeLabel(answerTypeEnumerationSingle)),

                ),
            ),
        )

    return dropDown
}

The (truncated for clarity) generated HTML is:

<div class="select is-fullwidth" hx-post="/admin/questions/">
        <select>
                <option value="TextLong">Long Text</option>
                <option value="TextShort">Short Text</option>
        </select>
</div>

The hx-post attribute is being added to the div and not the select element. The documenation for the b.Select do have some mention of this. However, I can't seem to figure out how to add the hx-post attribute to the select element.

If I change the b.Select to a el.Select it does work but I don't get all my nice Bulma Classes that your wonderful library provides with el.Select but I can add those.

The expected HTML Output of the select element is:

<select class="is-fullwidth" hx-post="/admin/questions/">

I may be missing something obvious here.

https://github.com/willoma/bulma-gomponents/blob/0de0750590f703c7cda64a75e03226c3ac392770/form_select.go#L88

willoma commented 6 months ago

Hello,

(regarding the discussions space, this project being fairly new and me being alone on this on my spare time, I prefer having everything in one place. Moreover if something happens at this point in the project, it probably is an issue rather than a simple discussion - at least an issue for the docs).

There is currently no possibility to do this, and it is a problem. Thanks for raising it. It may also apply to other elements.

The most obvious possibility would be to add b.Inner and b.Outer markers in order to allow the developer to chose on which element they want to apply a child, but I would love to have something smarter than this. If you have any suggestion, don't hesitate to share it, I'm open to any idea!

chrismalek commented 6 months ago

Yes, I was looking at that library and was thinking about how to expose that inner select as some other function. I was struggling with the naming as compared to the other form controls that don't have that div wrapper which is a Bulma decision. So the developer "interface" would be a bit different for that select form control as compared to the Textarea or InputText.

After sleeping on it and considering your documentation is freaking awesome :heart_eyes: I think just having that Inner and Outer would be fine. Just my two cents. 😄

willoma commented 6 months ago

With v0.4.0, you may now simply provide the gomponents-htmx attribute to the bulma-gomponents functions, it will be applied to the <select>.

But you can also use b.Inner(xxx) and b.Outer(xxx) if needed.

chrismalek commented 5 months ago

I just upgraded to 0.5.0. I think this issue is regressing. This was working in 0.4.0

Creating an Select with some HTMX triggers on change.

    dropDown :=

        b.Field(
            b.Label(
                q.getFieldLabel(answerTypeFieldName),
            ),
            b.Control(

                b.Select(
                    b.FullWidth,

                    html.Name(answerTypeFieldName),
                    hx.Post(q.editPath()),
                    hx.Target(hxTargetQuestionCard),

                    b.Option(
                        answerTypeLongText,
                        getAnswerTypeLabel(answerTypeLongText),
                        g.If(q.AnswerType == answerTypeLongText, html.Selected()),
                        g.If(q.AnswerType == "", html.Selected()),
                    ),

                ),
            ),

        )

The name, hx-post and hx-target are being supplied to the outer div and not the select. I might have just missing something in the updated documents.

chrismalek commented 5 months ago

Oh...gees...now I see it staring at me in the docs.

b.OnSelect

Correct & it works!

dropDown :=

        b.Field(
            b.Label(
                q.getFieldLabel(answerTypeFieldName),
            ),
            b.Control(

                b.Select(
                    b.FullWidth,
                    b.OnSelect(
                        html.Name(answerTypeFieldName),
                        hx.Post(q.editPath()),
                        hx.Target(hxTargetQuestionCard),
                    ),
                    b.Option(
                        answerTypeLongText,
                        getAnswerTypeLabel(answerTypeLongText),
                        g.If(q.AnswerType == answerTypeLongText, html.Selected()),
                        g.If(q.AnswerType == "", html.Selected()),
                    ),
willoma commented 5 months ago

Yes, I struggled to get something working for this one, regarding the default target for children, it may have been better, but OnSelect is your saviour, at list for now :-)