Reactive - Remove JS event listener with anonymous function
Application Type
Reactive

Hello,

In some of my previous forum posts I have had support with creating a new dropdown "autocomplete" widget, 



There was one issue I still had with it. That the list would still be visible when the user had clicked in other areas of the screen. So after a bit of digging i created a JS node with an event listener to close the list when the user clicks away.

I put the JS node in the OnReady action for the widget:

  

    document.addEventListener('click', function(event) {

    if ( event.target.id === $parameters.ElementJobParentId || event.target.closest('#' + $parameters.ElementJobParentId)) {

     }else{

            $actions.CloseJobList(

    }

 });

This works well. However when going to a new screen where the widget doesnt exist i get error messages every time i click: 

"Invalid call of the 'CloseJobList' client action of the 'Defect.NewDefect' since the latter is not currently active. This is likely due to a platform's client action being used as an event handler or in a setTimeout function. Consider removing this call by using the 'On Destroy' event of the screen/block or moving your logic to a global client action."

Now I realise this is because the event listener is still working but obviously since the widget has been destroyed it can no longer get to "closeJobList" action. 


I have looked at putting another JS node in the OnDestroy Action but since the event listener uses an anonymous function I am unable to reference the correct listener to remove. 


any help would be greatly appreciated. Ive attached an OML to replicate the issue. My custom Dropdown is on the first screen, and when you navigate to the second screen you will see the errors appear on click in the error log.

TestJob.oml

Solution

Hi,

Can you try this?

  1. Remove OnReady/OnDestroy events.
  2. In client action Input_EmployeeSearchOnClick add your jscript with some modifications to remove the event listener.

The logic would be when you click in the input widget, open the list widget and add an event listener in order to click outside widgets. This event listener will close the list widget and will remove the event listener.

Kind regards, David.

Hello David,

This nearly worked, though i still got the error messages, however I made a slight tweak to your suggestion which has worked: 

Using the JS node where you suggested and editing the code to (just moving the remove listener to the else clause):


document.addEventListener('click', function _listener(event) {

  if ( event.target.id === $parameters.ElementJobParentId || event.target.closest('#' + $parameters.ElementJobParentId)) {

    

  }else{

        $actions.CloseEmployeeList()

        this.removeEventListener('click', _listener);

  }

  });


Thank you for your help! much appreciated. Ill mark yours as the solution.

Chris

Hi Cristopher,

I think you should consider another perspective of solving the problem. I wouldn't use the OnReady/OnDestroy action of the widget to add listener that affects the entire document object. It may have side effects later.

You can remove OnReady/OnDestroy events and add onblur event in input widget to close the list.

I hope you find it useful.

Kind regards, David.

Hello David,

thanks for the reply.

Unfortunately that does not work as you would expect. This will result in the list closing when trying to click on an item in it, which results in the item not being selected.

I have tried to make the parent container have the onblur event hoping that the onblur event wouldnt be triggered by clicking on child containers/items, but this also results in the list closing when trying to select from the list.

any other suggestions?

Chris

Solution

Hi,

Can you try this?

  1. Remove OnReady/OnDestroy events.
  2. In client action Input_EmployeeSearchOnClick add your jscript with some modifications to remove the event listener.

The logic would be when you click in the input widget, open the list widget and add an event listener in order to click outside widgets. This event listener will close the list widget and will remove the event listener.

Kind regards, David.

Hello David,

This nearly worked, though i still got the error messages, however I made a slight tweak to your suggestion which has worked: 

Using the JS node where you suggested and editing the code to (just moving the remove listener to the else clause):


document.addEventListener('click', function _listener(event) {

  if ( event.target.id === $parameters.ElementJobParentId || event.target.closest('#' + $parameters.ElementJobParentId)) {

    

  }else{

        $actions.CloseEmployeeList()

        this.removeEventListener('click', _listener);

  }

  });


Thank you for your help! much appreciated. Ill mark yours as the solution.

Chris

Community GuidelinesBe kind and respectful, give credit to the original source of content, and search for duplicates before posting.