valor-software / ngx-bootstrap

Fast and reliable Bootstrap widgets in Angular (supports Ivy engine)
https://valor-software.com/ngx-bootstrap
MIT License
5.53k stars 1.69k forks source link

TypeError: _this._documentClickListener is not a function at ngx-bootstrap-dropdown.js:698 #5830

Open beingbing opened 4 years ago

beingbing commented 4 years ago

I already searched for this issue on internet, nobody has reported it.

Bug description: it's a small error on your part in declaring a defining a function on your part.

the error i am getting

core.js:4117 ERROR TypeError: _this._documentClickListener is not a function at ngx-bootstrap-dropdown.js:698 at SafeSubscriber.schedulerFn [as _next] (core.js:25527) at SafeSubscriber.push../node_modules/rxjs/_esm5/internal/Subscriber.js.SafeSubscriber.__tryOrUnsub (Subscriber.js:192) at SafeSubscriber.push../node_modules/rxjs/_esm5/internal/Subscriber.js.SafeSubscriber.next (Subscriber.js:130) at Subscriber.push../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber._next (Subscriber.js:76) at Subscriber.push../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber.next (Subscriber.js:53) at EventEmitter.push../node_modules/rxjs/_esm5/internal/Subject.js.Subject.next (Subject.js:47) at EventEmitter.push../node_modules/@angular/core/__ivy_ngcc__/fesm5/core.js.EventEmitter.emit (core.js:25488) at BsDropdownDirective.push../node_modules/ngx-bootstrap/__ivy_ngcc__/dropdown/fesm5/ngx-bootstrap-dropdown.js.BsDropdownDirective.hide (ngx-bootstrap-dropdown.js:416) at BsDropdownDirective.push../node_modules/ngx-bootstrap/__ivy_ngcc__/dropdown/fesm5/ngx-bootstrap-dropdown.js.BsDropdownDirective.toggle (ngx-bootstrap-dropdown.js:439)

the reason for this error - in ngx-bootstrap-dropdown.js file you made a silly mistake -

if (value) { _this._documentClickListener = _this._renderer.listen('document', 'click', function (event) { if (_this._state.autoClose && event.button !== 2 && !_this._element.nativeElement.contains(event.target) && !(_this._state.insideClick && _this._dropdown._contains(event))) { _this._state.toggleClick.emit(false); _this._changeDetectorRef.detectChanges(); } }); _this._escKeyUpListener = _this._renderer.listen(_this._element.nativeElement, 'keyup.esc', function () { if (_this._state.autoClose) { _this._state.toggleClick.emit(false); _this._changeDetectorRef.detectChanges(); } }); } else { _this._documentClickListener(); _this._escKeyUpListener(); }

you define _documentClickListener only if you find a value, but what if user doesn't select a value from dropdown, in that case, function get called in else block, without ever being defined, hence the error.

Versions of ngx-bootstrap, Angular, and Bootstrap:

ngx-bootstrap: v5.6.1

Angular: v9.1.2

Bootstrap: v4.1.1

Expected behavior

my only expectation is, handle that error, this error shouldn't be thrown in first place.

Sabbacus commented 4 years ago

My team have this problem as well.

ngx-bootstrap: v5.6.2

Angular: v9.1.0

Bootstrap: v3

RAHMANIABOUBEKER commented 4 years ago

Hello, I am facing the same issues with: ngx-bootstrap: v6.0.0 Angular v10.0.4

image

TomCockram commented 3 years ago

Also having this problem :(

reisandbeans commented 3 years ago

I'm having this problem as well. I've done some debugging, and at least in my case the root cause describe by @beingbing above is... incomplete, I'd say. When you open the modal, the listener is defined, so when you close the modal and value is set to false, the listener will be defined. The problem I observed in my case, is that the constructor for BsDropdownToggleDirective seems to be called twice, once when the page loads and again when I click on the dropdown toggle button (I'm using the component in a similar fashion to this example. I've also notice a couple more things: this error seems to only happen once, and also, I have two similar dropdowns in my page and it only happens for one of them, but I'm not sure what's exactly different between them.

Nokhoneryu commented 3 years ago

Another nuance to this issue: Everything works just fine if i use the expected structure as the examples show, such as:

<div class="btn-group" dropdown>
  <button id="button-basic" dropdownToggle type="button" class="btn btn-primary dropdown-toggle" aria-controls="dropdown-basic">
    Button dropdown <span class="caret"></span>
  </button>
  <ul id="dropdown-basic" *dropdownMenu class="dropdown-menu" role="menu" aria-labelledby="button-basic">
    <li role="menuitem">
      <a class="dropdown-item" href="#">Action</a>
    </li>
  </ul>
</div>

But the error is thrown if I use a custom template, such as:

<div class="btn-group" dropdown>
  <button id="button-basic" dropdownToggle type="button" class="btn btn-primary dropdown-toggle" aria-controls="dropdown-basic">
    Button dropdown <span class="caret"></span>
  </button>
  <ul id="dropdown-basic" *dropdownMenu class="dropdown-menu" role="menu" aria-labelledby="button-basic">
    <li role="menuitem">
      <form> {{...stuff inside the form...}}  </form>
    </li>
  </ul>
</div>

Don't now if the previous comments account for this as well