1

I'm still quite new to Typescript and react and unfortunately don't understand what I'm doing wrong. I have a tab style nav with a NavDropdown. Unfortunately the dropdown is the only tab that does not get the active class when one of the dropdown items is selected. I have already seen that some people had this problem and could solve it somehow but I can't find a way to do it in my case. Can anyone help me?

Currently my nav looks like this:

  <Nav variant="tabs">
    <Nav.Item>
      <Nav.Link
        onClick={(e: React.MouseEvent<Element, MouseEvent>) => setTab(e, "today")}
        href="#today"
      >
        today
      </Nav.Link>
    </Nav.Item>

    <NavDropdown
      title={activeTab === "month" ? dateFormat(dateStart!, "MMMM yyyy") : "month"}
      id="month"
    >

      {months.map((m) => (
        <NavDropdown.Item onClick={() => setMonth(m)} key={dateFormat(m, "MMMM yyyy")}>
          {dateFormat(m, "MMMM yyyy")}
        </NavDropdown.Item>
      ))}
    </NavDropdown>
axelhaar
  • 39
  • 1
  • 7
  • To have the selection on click add `eventKey` to `NavDropdown.Item`. But to make it selectable with state change it also required the `active` prop (e.g. changing to current Month). Please have a look at the following [Codesandbox](https://codesandbox.io/s/react-bootstrap-navbar-demo-yq2sk). – AWolf Jun 06 '21 at 13:55
  • @AWolf Thanks a lot for the codesandbox, it helped me already a bit :-) The problem is that the tab for the month is not shown as active when selecting a month, even in your example... :( That's what I'm trying to do, or how it should look: https://prnt.sc/14dlm4n Unfortunately I just can't get it to work in react-bootstrap.... Can you please help me with this? – axelhaar Jun 06 '21 at 14:35
  • You can add that with the `title` on the `NavDropDown`. I've changed it in the Codesandbox. If there is no other format needed, you could also use directly `{month}` for the title. – AWolf Jun 06 '21 at 15:00
  • Sorry, I think I'm bad at describing my problem exactly. I was able to set the title to the current month. My problem is that the tab with the current month is not displayed as an active tab when a month is selected. So this is what it currently looks like when a month is selected: https://prnt.sc/14dq5ce But this is what it should look like when a month is selected: https://prnt.sc/14dlm4n Or do you already know what I mean and I just didn't understand your answer? :/ – axelhaar Jun 06 '21 at 15:11
  • OK, no problem. Now, I've got the problem. Set `active` prop on `NavDropdown` with the `activeTab` state variable. I've updated the code in the sandbox. So the tab of `month` is activated once a month is selected. – AWolf Jun 06 '21 at 16:19
  • Yess, that solved my problem! Thank you very much for your help <3 @AWolf – axelhaar Jun 06 '21 at 16:29

1 Answers1

0

I've modified the following parts to fix the tab navigation and month selection:

  • Added defaultActiveKey={activeTab} to the Nav component to activate the tab on load
  • Nav.Link added eventKey="today" to have the key for the today tab set up properly
  • On NavDropdown.Item added active={m === month} where m is the iterator of the map (e.g. Jan 2021, Feb 2021 etc) and month is the selected month. This is needed so the selection in the drop-down is working.
  • In the onClick of the drop-down items added setMonth & setTab to update the state.
  • On NavDropdown added active={activeTab === "month"} so the tab navigation is correctly updating.

I've also used moment.js to generate the month array and to format the months. Generation of the array is from this SO answer.

You can have a look at the code below or in this Codesandbox.

/*import moment from "moment";
import { useState } from "react";
import Nav from "react-bootstrap/Nav";
import NavDropdown from "react-bootstrap/NavDropdown";
import "./styles.css";
import "bootstrap/dist/css/bootstrap.min.css";*/

const {useState} = React;
const {Nav, NavDropdown} = ReactBootstrap;
const MONTH_FORMAT_STR = "MMM yyyy";
const months = Array.apply(0, Array(12)).map(function (_, i) {
  return moment().month(i).format(MONTH_FORMAT_STR);
});

const curMonth = moment().format(MONTH_FORMAT_STR);

function App() {
  const [month, setMonth] = useState(curMonth);
  const [activeTab, setTab] = useState(`month`);
  const [dateStart, setStart] = useState(""); // not implemented yet

  return (
    <Nav variant="tabs" defaultActiveKey={activeTab}>
      <Nav.Item>
        <Nav.Link
          eventKey="today"
          onClick={() => {
            setTab("today");
            console.log("set month", curMonth);
            setMonth(curMonth);
          }}
          href="#today"
        >
          today
        </Nav.Link>
      </Nav.Item>
      <Nav.Item>
        <NavDropdown
          id="month"
          active={activeTab === "month"}
          title={moment().month(month).format("MMMM YYYY")}
        >
          {months.map((m) => (
            <NavDropdown.Item
              title={m}
              eventKey={m}
              active={m === month}
              onClick={() => {
                setMonth(m);
                setTab("month");
              }}
              key={m}
            >
              {m}
            </NavDropdown.Item>
          ))}
        </NavDropdown>
      </Nav.Item>
      {activeTab} {month}
    </Nav>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
<script crossorigin src="https://unpkg.com/react@17/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js" integrity="sha512-qTXRIMyZIFb8iQcfjXWCO8+M5Tbc38Qi5WzdPOYZHIlZpzBHG3L3by84BBBOiRGiEb7KKtAOAs5qYdUiZiQNNQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-bootstrap/1.5.2/react-bootstrap.min.js" integrity="sha512-Mw0NWa5M4d73pjqO5CY7Olq0yjPg80GsKCRHpy114idMaX8v+scJmRvhWbXTct8inkKGJNzBvMyWG4ok79zigQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<link
  rel="stylesheet"
  href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css"
  integrity="sha384-B0vP5xmATw1+K9KRQjQERJvTumQW0nPEzvF6L/Z6nronJ3oUOFUFpCjEUQouq2+l"
  crossorigin="anonymous"
/>

  
<div id="root"/>
AWolf
  • 8,770
  • 5
  • 33
  • 39