Matti
Matti

Reputation: 515

Can i add conditional events on svelte components?

is it possible for an event to be fired on a condition defined in the parent component ?

I have an input component where i want to capture the input.. sometimes, but most of the time i dont want the event to fire

   //App.html
   <Input on:inputData="doStuff(event)" fireEvent=true />    

   //Input.html
   <input bind:value=value (fireEvent ? on:keyup='fire("inputData", { value })' : false )/>

What happens currently is that fireEvent is ignored and on:keyup allways fires

UPDATE
I changed the keyup into a function call where i checked the parameter before firing the event, it works but its kinda wacky

//App.html
<Input on:inputData='doStuff(event.value)' fireEvent={true} />
 ...
  methods: {
  doStuff(text) {
    console.log('here is the stuff', text);
  }

//Input.html
<input bind:value=value on:keyup='setData({ value })'/>
...
methods: {
  setData(text) {
    if(this.get().fireEvent) {
      this.fire("inputData", text)
    }
  }
}

Anyone got a prettier solution to this problem ?

Upvotes: 2

Views: 4201

Answers (3)

kindoflew
kindoflew

Reputation: 106

Very late to the party, but I had a similar problem and ended up solving it with an action. For mine, I needed to attach a click listener to a button only if a certain condition was truthy. A more generic example could be:

<button use:conditionalEvent({condition: foo, event: 'click', callback: bar})>...</button>

...

function conditionalEvent(node, {condition, event, callback}) {
    if (condition) {
        node.addEventListener(event, callback);
    }

    return {
        destroy() {
            node.removeEventListener(event, callback)
        } 
    }
}

The markup could be less verbose if it was only for a single callback or event type, but you get the point. If the condition can change with user input, you can also return an update function:

function changingCondition(node, {condition, event, callback}) {
    function update(condition) {
        if (condition) {
            node.addEventListener(event, callback);
        } else {
            node.removeEventListener(event, callback);
        }
    }

    update(condition);

    return {
        update,
        destroy() {
            node.removeEventListener(event, callback)
        } 
    }
}

And the update will run whenever condition changes.

Upvotes: 4

Matti
Matti

Reputation: 515

I dont know why i didnt think of this but this is excatly what onupdate is for

//App.html
<Input on:inputData='doStuff(event.value)' fireEvent={true} />
     ...
methods: {
 doStuff(text) {
   console.log('here is the stuff', text);
 }

//Input.html
<input bind:value=value />
...
onupdate({ changed, current, previous }) {
  if(this.get().fireEvent) {
    this.fire("inputData", current)
  }

Upvotes: 4

JasonWilson
JasonWilson

Reputation: 136

I tried the following and it worked. note the lower case 'fireevent'. The capital letter threw it off. Naturally you'd have to change it to on:inputData etc.

	methods: {
	    test(evt) {
		console.log('evt.fireEvent', evt.target.getAttributeNode("fireEvent").value);
		if (evt.target.getAttributeNode("fireevent").value && evt.target.getAttributeNode("fireevent").value=="true")
		    console.log('do the happy dance');
		else
		    console.log('do NOTHING');

	    }
	}
<button on:click="test(event)" fireevent="false">Test</button>

Upvotes: 0

Related Questions