rguliev / conditionize2.js

jQuery plugin for conditioning things
https://rguliev.github.io/conditionize2.js/demo/index.html
MIT License
22 stars 6 forks source link

Trigger an event after the state of a condition changed #18

Open Seb33300 opened 1 year ago

Seb33300 commented 1 year ago

Hello,

I need to detect when a condition has been triggered in order to run some extra process.

I tried to do something like this:

$('...').conditionize({
    ifTrue: [
        // ...
        function ($s) { $s.trigger('my-event-name'); }
    ],
    ifFalse: [
        // ...
        function ($s) { $s.trigger('my-event-name'); }
    ]
});

But unfortunately, the event is fired as many times as we have elements related to the condition. (If I have 10 elements using the same data-condition, the event is triggered 10 times, every time the condition has changed)

It will be very useful if conditionize2 could natively fire some events that we can listen when conditions are triggered (eg conditionize.before / conditionize.after)

rguliev commented 1 year ago

Hello,

Thank you for your feedback. I am not sure, I am getting your idea. 1) You can relate a specific element separately, i.e.

$('#your_specific_element').conditionize(...)
$('.other_elements').condidtionize(...)

2) How conditionize.before / conditionize.after is different from

$('...').conditionize({
    ifTrue: [
        // ...
        function ($s) { $s.trigger('my-event-name'); }
    ],
    ifFalse: [
        // ...
        function ($s) { $s.trigger('my-event-name'); }
    ]
});

?

Seb33300 commented 1 year ago

Hello,

I checked again and I can confirm this is working properly.

The issue I am encountering is a little bit different and made me confused. In reality, I am looking for a "state changed" event.

This is a specific case that can occur for example when working with multiple values input (returning an array of values). If I put a condition based on a specific element from the list. My event is triggered every time any element of the list is modified. Even if this is not changing the state of my condition (it was false before, and remains false after)

Here is an exemple to make this clearer: https://jsfiddle.net/8jy16go7/

Seb33300 commented 1 year ago

Another way to fix this could be to not rerun condition functions if the state did not change.

rguliev commented 1 year ago

From your example, I feel like the problem is that you are combining two different conditions but then want to trigger an event only for one specific condition. I.e. for your example, I would suggest:

$('.conditional1').conditionize( //here you trigger your event// )
$('.conditional2').conditionize( //here you do not trigger the event// )
Seb33300 commented 1 year ago

Actually, the same issue happens also with a single condition. See https://jsfiddle.net/Lzuqets7/

What happens:

On page load:

  1. conditionize is initialized on the <p> and data-condition returns false
  2. Current state of <p> is undefined (it's page load, we dont know the element state yet)
  3. false !== undefined => conditionize executes functions defined in the ifFalse option (working as expected)

On checkbox change:

  1. If I click on checkbox 2, it triggers conditionize on <p> and data-condition still returns false
  2. Current state of <p> is already false (initialized on page load)
  3. false === false => nothing should happen here, because the <p> is already in the state false so we can skip to execute functions defined in the ifFalse option
  4. But this is not what happens, the execution of functions defined in ifFalse is triggered all the time, even if the element is already in the same state, resulting in my event fired.

ifFalse / ifTrue should be executed only in case of different state:

  1. If I click on checkbox 1, it triggers conditionize on <p> and data-condition returns true
  2. Current state of <p> is false
  3. true !== false => conditionize executes functions defined in the ifTrue option
rguliev commented 1 year ago

Thank you for the explanation. Now I got it. A simple workaround at the moment could be:

let state = null;
$('.conditional1').conditionize({
  ifTrue: [
    'show',
    function ($s) {
      if (!state) {
        state = true;
        $s.trigger('my-event-name'); 
      }
    }
  ],
  ifFalse: [
    'hide',
    function ($s) {
      if (state) {
        state = false;
        $s.trigger('my-event-name'); 
      }
    }
  ]
});

However, I agree that it would be a good improvement to the package. I will keep this issue open.