0

What's the best way to scope an event on two similar Riot components using two different RiotControl stores?

Right now, no matter what button is pressed, the action is applied on both tags, since the control stores are global. I'm trying to figure out what's the best way to scope one tag per store.

My actual use case will have multiple nested tags, so passing the Store around may not be ideal.

I've set up an example at: https://jsfiddle.net/Lsc3znng/

My Tag:

<script type="riot/tag">
  <play>
    <button onclick={ toggle }>{opts.name}</button>
    <p name="status">unclicked</p>
      var self = this   

      RiotControl.on('play', function() {
        self.status.innerText = "clicked"
      })

      toggle(e) {
        RiotControl.trigger('play_toggle')           
      }
  </play>
</script>

My Store:

function ButtonControlStore() {
    riot.observable(this)  
  var self = this

  self.on('play_toggle', function() {
    self.trigger('play')
  })  
}

var controlStoreOne = new ButtonControlStore()
var controlStoreTwo = new ButtonControlStore()

RiotControl.addStore(controlStoreOne)
RiotControl.addStore(controlStoreTwo)
Mataniko
  • 2,212
  • 16
  • 18

2 Answers2

0

The most elegant solution I came up with so far is to create a global Mixin that defines a scope for all of the controls based on either an attribute on the root element, or its id.

var ScopeMixin = {
  // init method is a special one which can initialize
  // the mixin when it's loaded to the tag and is not
  // accessible from the tag its mixed in
  init: function() {
    this.scope = this.getScope();
  },

  getScope: function() {
    var root = this
    while (root.parent) {
      root = root.parent
    }

    return root.opts.scope || root._riot_id
  }
}

This is combined with every trigger to include a scope

toggle(e) {
    RiotControl.trigger('play_toggle', { scope: self.scope })           
}
Mataniko
  • 2,212
  • 16
  • 18
0

An approach I have used is;

  1. when you new your stores, namespace/scope them.
    var controlStoreOne = new ButtonControlStore({namespace1}) var controlStoreTwo = new ButtonControlStore({namespace2})
    The stores are coded up to listen on namespaced events.
    self.on(self.namespace+':'+'play_toggle', function(ack) { self.trigger(ack.evt,ack,'play') })

    i.e. when you riot.control an event to them it is RiotControl.trigger('{namespace1}:play_toggle', ack)

  2. Pass an ack object;
    { evt:'{my listenter}', extraData:{} } The stores are coded to trigger on an event name that is passed in. So no blindly triggering on some hard-coded event name.
    my stores then respond back to something like this. self.trigger(ack.evt, ack,{the store's produced data})

In the end, your stores are scoped and they only fire events to whomever wants them

Herb Stahl
  • 439
  • 1
  • 6
  • 23