yung peso
yung peso

Reputation: 1796

How to use HTMX to open and close a dropdown menu in a header?

I'm playing around with HTMX, after reading the docs, I'm a little confused on how to make a <button> from my header activate a dropdown <div>.

This is what I have so far, this button should contain the HMTX attributes to open the <div> aka dropdown, with an id and name of response (naming is only for testing purposes).

              <button
                type="button"
                aria-expanded="false"
                hx-get="#response"
                hx-target="#response"
                hx-indicator=".htmx-indicator"
              >

as seen here, this div wraps the dropdown together.

              <div
                id="response"
                name="response"
              >

Here's everything together, the mock-up I used is taken from TailwindCSS (except the HTMX attributes):

          <nav class="hidden md:flex space-x-10">
            <div class="relative">
              <!-- Item active: "text-gray-900", Item inactive: "text-gray-500" -->
              <button
                type="button"
                class="
                  text-gray-500
                  group
                  bg-white
                  rounded-md
                  inline-flex
                  items-center
                  text-base
                  font-medium
                  hover:text-gray-900
                  focus:outline-none
                  focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500
                "
                aria-expanded="false"
                hx-get="#response"
                hx-target="#response"
                hx-indicator=".htmx-indicator"
              >
                <span>Articles</span>
                <!--
                Heroicon name: solid/chevron-down

                Item active: "text-gray-600", Item inactive: "text-gray-400"
                -->
                <svg
                  class="text-gray-400 ml-2 h-5 w-5 group-hover:text-gray-500"
                  xmlns="http://www.w3.org/2000/svg"
                  viewBox="0 0 20 20"
                  fill="currentColor"
                  aria-hidden="true"
                >
                  <path
                    fill-rule="evenodd"
                    d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
                    clip-rule="evenodd"
                  />
                </svg>
              </button>

              <!--
                'Solutions' flyout menu, show/hide based on flyout menu state.

                Entering: "transition ease-out duration-200"
                From: "opacity-0 translate-y-1"
                To: "opacity-100 translate-y-0"
                Leaving: "transition ease-in duration-150"
                From: "opacity-100 translate-y-0"
                To: "opacity-0 translate-y-1"
            -->
              <div
                id="response"
                name="response"
                class="
                  absolute
                  z-10
                  -ml-4
                  mt-3
                  transform
                  px-2
                  w-screen
                  max-w-md
                  sm:px-0
                  lg:ml-0
                  lg:left-1/2
                  lg:-translate-x-1/2
                "
              >
                <div
                  class="
                    rounded-lg
                    shadow-lg
                    ring-1 ring-black ring-opacity-5
                    overflow-hidden
                  "
                >
                  <div
                    class="
                      relative
                      grid
                      gap-6
                      bg-white
                      px-5
                      py-6
                      sm:gap-8
                      sm:p-8
                    "
                  >
                    <a
                      href="#"
                      class="
                        -m-3
                        p-3
                        flex
                        items-start
                        rounded-lg
                        hover:bg-gray-50
                      "
                    >
                      <!-- Heroicon name: outline/chart-bar -->
                      <svg
                        class="flex-shrink-0 h-6 w-6 text-indigo-600"
                        xmlns="http://www.w3.org/2000/svg"
                        fill="none"
                        viewBox="0 0 24 24"
                        stroke="currentColor"
                        aria-hidden="true"
                      >
                        <path
                          stroke-linecap="round"
                          stroke-linejoin="round"
                          stroke-width="2"
                          d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z"
                        />
                      </svg>
                      <div class="ml-4">
                        <p class="text-base font-medium text-gray-900">
                          Analytics
                        </p>
                        <p class="mt-1 text-sm text-gray-500">
                          Get a better understanding of where your traffic is
                          coming from.
                        </p>
                      </div>
                    </a>
                  </div>
                 </div>
                </nav>

As of now when testing in development, every dropdown in my NAV bar is opened immediately once the page loads. There is no proper event to declare when the dropdowns should appear after clicking on a NAV header.

How can I fix and use HTMX to solve this issue?

HTMX docs can be found here

EDIT: Just to note that I have added the CDN script for HTMX and playing around with the attributes confirms that the script is working, I just don't understand how to solve the issue stated above.

Upvotes: 1

Views: 3709

Answers (2)

Gostega
Gostega

Reputation: 555

I think perhaps this isn't what htmx is designed to do.

Make the dropdown with normal html/javascript with optional templating on the server.

Then you make each element of the dropdown (like menuitem1, menuitem2) do things on click with htmx.

Upvotes: 1

guettli
guettli

Reputation: 27031

HTMX uses this pattern:

  1. event (for example button click)
  2. http request to server
  3. http response from server (containing an html fragment)
  4. fragment gets applied to the DOM.

After your button was clicked, you need to receive a http response. Maybe I am blind, but I think this is missing in your code.

Upvotes: 1

Related Questions