Submenu Bootstrap in Jquery for Typescript

Asked

Viewed 220 times

-3

I am starting my studies with Typescript and I am trying (and need) to modify a code that I found ready, which is in Jquery. But I need it all in Typescript, but I’m not able to make it work yet. Someone there can give me a help ?

The link from where I found the code is that.

There is code in Jquery working and html and css to test.

For ease, here is the code in Jquery:

$('.dropdown-menu a.dropdown-toggle').on('click', function(e) {
  if (!$(this).next().hasClass('show')) {
    $(this).parents('.dropdown-menu').first().find('.show').removeClass("show");
  }
  var $subMenu = $(this).next(".dropdown-menu");
  $subMenu.toggleClass('show');


  $(this).parents('li.nav-item.dropdown.show').on('hidden.bs.dropdown', function(e) {
    $('.dropdown-submenu .show').removeClass("show");
  });


  return false;
});

Code I’ve tried to make: (getParents function I took from that question.)

function getParents(parentSelector) {

    // If no parentSelector defined will bubble up all the way to *document*
    if (parentSelector === undefined) {
        parentSelector = document;
    }

    var parents = [];
    parents.push(parentSelector); // Push that parentSelector you wanted to stop at

    return parents;
}

    var addDropDown = document.querySelectorAll('.dropdown-menu a.dropdown-toggle');

    for (var i = 0; i < addDropDown.length; i++) {
        addDropDown[i].addEventListener('click', function (e) {

            if (!this.nextElementSibling.classList.contains('show')) {

                var elemento = getParents(this)[0].querySelectorAll('.show');

                for (var z = 0; z < elemento.length; z++) {
                    elemento[i].addEventListener('click', function (e) {
                        elemento[z].classList.remove("show");
                    });
                }

            }
            var $subMenu = this.nextElementSibling(".dropdown-menu");
            $subMenu.classList.toggle('show');

            this.parentNode('li.nav-item.dropdown.show').addEventListener('hidden.bs.dropdown', function (e) {
                var itensLista = document.querySelectorAll('.dropdown-submenu .show');

                for (var x = 0; x < itensLista.length; x++) {
                    itensLista[i].classList.remove("show");
                }
            });


            return false;
        });
    }

Console error:

Uncaught Typeerror: this.nextElementSibling is not a Function At Htmlanchorelement.

The line indicated by the error is this:

var $subMenu = this.nextElementSibling(".dropdown-menu");

NOTE: I AM NOT USING JQUERY

  • Why can’t you make it work? Compiler shows some error?

  • @user140828, I still don’t quite understand Typescript, that’s why kk. I’m not now with the code I was trying, but then I leave on the question... but I didn’t go too far no. Better start from scratch.

  • @user140828, I edited the question by placing the code I have already made, and I will leave what error is being presented in the compiler

  • The last fragment does not help at all because in Typescript depending on where the keyword is used this it takes different values. In a constructor, member function, or property this points to the current instance of the class in which it is used. In a static method or static property this points to the constructor of the class in which it is used. In a function declaration this points to the scope of the function itself in which it is used. This exists as a parameter possessing its own logic. Edit the question put the full declaration of the element where the problematic 'this' occurs.

  • I appreciate the comment, but could I leave an answer as to what the code would look like with all this in mind? @Augustovasques

  • As I explained without knowing what the context is this and without knowing which object it references is impossible to answer the question.

Show 1 more comment

1 answer

2

I tested, the problems and their corrections:

var $subMenu = this.nextElementSibling(".dropdown-menu");

for

var $subMenu = this.nextElementSibling;

this.parentNode('li.nav-item.dropdown.show').addEventListener

for

this.parentNode.addEventListener

and add to prevent the menu from closing at the wrong time

e.stopPropagation();
e.preventDefault();

var addDropDown = document.querySelectorAll('.dropdown-menu a.dropdown-toggle');

    for (var i = 0; i < addDropDown.length; i++) {
        addDropDown[i].addEventListener('click', function (e) {
    e.stopPropagation();
    e.preventDefault(); 
            if (!this.nextElementSibling.classList.contains('show')) {

                var elemento = getParents(this)[0].querySelectorAll('.show');

                for (var z = 0; z < elemento.length; z++) {
                    elemento[i].addEventListener('click', function (e) {
                        elemento[z].classList.remove("show");
                    });
                }

            }
            var $subMenu = this.nextElementSibling;
            $subMenu.classList.toggle('show');
            this.parentNode.addEventListener('hidden.bs.dropdown', function (e) {
                var itensLista = document.querySelectorAll('.dropdown-submenu .show');

                for (var x = 0; x < itensLista.length; x++) {
                    itensLista[i].classList.remove("show");
                }
            });

            return false;
        });
    }

function getParents(parentSelector) {

    // If no parentSelector defined will bubble up all the way to *document*
    if (parentSelector === undefined) {
        parentSelector = document;
    }

    var parents = [];
    parents.push(parentSelector); // Push that parentSelector you wanted to stop at
    return parents;
}
.dropdown-submenu {
  position: relative;
}

.dropdown-submenu a::after {
  transform: rotate(-90deg);
  position: absolute;
  right: 6px;
  top: .8em;
}

.dropdown-submenu .dropdown-menu {
  top: 0;
  left: 100%;
  margin-left: .1rem;
  margin-right: .1rem;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-beta/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.11.0/umd/popper.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-beta/js/bootstrap.min.js"></script>




<nav class="navbar navbar-expand-lg navbar-light bg-light">
  <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarTogglerDemo01" aria-controls="navbarTogglerDemo01" aria-expanded="false" aria-label="Toggle navigation">
    <span class="navbar-toggler-icon"></span>
  </button>
  <div class="collapse navbar-collapse" id="navbarTogglerDemo01">
    <a class="navbar-brand" href="#">Hidden brand</a>
    <ul class="navbar-nav mr-auto mt-2 mt-lg-0">
      <li class="nav-item active">
        <a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a>
      </li>
      <li class="nav-item">
        <a class="nav-link" href="#">Link</a>
      </li>
      <li class="nav-item">
        <a class="nav-link disabled" href="#">Disabled</a>
      </li>
   <li class="nav-item dropdown">
        <a class="nav-link dropdown-toggle" href="http://example.com" id="navbarDropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
          Dropdown link
        </a>
        <ul class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
          <li><a class="dropdown-item" href="#">Action</a></li>
          <li><a class="dropdown-item" href="#">Another action</a></li>
          <li class="dropdown-submenu"><a class="dropdown-item dropdown-toggle" href="#">Submenu</a>
            <ul class="dropdown-menu">
              <li><a class="dropdown-item" href="#">Submenu action</a></li>
              <li><a class="dropdown-item" href="#">Another submenu action</a></li>


              <li class="dropdown-submenu"><a class="dropdown-item dropdown-toggle" href="#">Subsubmenu</a>
                <ul class="dropdown-menu">
                  <li><a class="dropdown-item" href="#">Subsubmenu action</a></li>
                  <li><a class="dropdown-item" href="#">Another subsubmenu action</a></li>
                </ul>
              </li>
              <li class="dropdown-submenu"><a class="dropdown-item dropdown-toggle" href="#">Second subsubmenu</a>
                <ul class="dropdown-menu">
                  <li><a class="dropdown-item" href="#">Subsubmenu action</a></li>
                  <li><a class="dropdown-item" href="#">Another subsubmenu action</a></li>
                </ul>
              </li>



            </ul>
          </li>
        </ul>
      </li>
    </ul>
    <form class="form-inline my-2 my-lg-0">
      <input class="form-control mr-sm-2" type="text" placeholder="Search" aria-label="Search">
      <button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
    </form>
  </div>
</nav>

  • Now that I saw it is a function. I had lost myself in the question endentation. The answer is correct and my comments on the question are invalid.

  • Hudson, I don’t understand, I put the code the same way yours is but it didn’t work, the only thing I didn’t put were these links from the scripts. Your code is dependent on them?

  • What happens is that it just doesn’t work, but it also doesn’t show me an error. When I click on the submenu to open, it only goes to the href="#" and does not open the other level.

  • your code has basic errors and missing the default evente Prevent according to what you showed, if there is something wrong in your code should be the order of the js references, see if jquery is the first in the order that makes all the difference.

  • Hudson, I’m getting a code that’s already ready in jQuery to pass to Typescript and NAY depending on jQuery... I would like the code to work without I need to use jQuery in my project. Because if I were to use jQuery, I would take that code that is already ready and I left in question.

  • @SAMU I think you are confusing Typescript with pure JS. The code it says it tried to do doesn’t look like TS.

  • Well, I need in TS :/

Show 2 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.