Search code examples
ractivejs

global pub-sub/event-handling in ractive


I'm trying to determine the best way to establish cross-component-communication. My first thought was to use ractive.fire with a wildcard, but that doesn't seem to work. Am I trying to mis-use ractive.fire? What would be the suggested way for doing cross-component-communication with ractive?

Ractive.components.pubSub = Ractive.extend({ 
    oninit() {
        this.on('*.customEvent', () => alert('pub sub got your custom event!'))
    }
})
Ractive.components.something = Ractive.extend({ 
    template: '#something'
})
let ractive = new Ractive({
    target: 'body',
    template: '#app'
})
<script src="https://cdn.jsdelivr.net/npm/[email protected]/ractive.js"></script>
<script id="app" type="text/ractive">
    <pubSub />
    <something />
</script>
<script id="something" type="text/ractive">
    <button on-click="@.fire('customEvent')">Fire Custom Event</button>
</script>


Solution

  • Ractive doesn't prescribe a convention for data sharing/cross-component communication. However, it does give you the facilities to do it. A common practice I've seen is to create a "dummy instance" and use its ractive.fire() and ractive.on() methods.

    // The dummy instance, make it visible to components.
    const pubsub = Ractive()
    
    const SourceComponent = Ractive.extend({
      template: '<button click="send()">Click me</button>',
      send(){
        pubsub.fire('message')
      }
    })
    
    const ListeningComponent = Ractive.extend({
      onInit(){
        pubsub.on('message', () => {
          console.log('called')
        })
      }
    })
    

    Alternatively, if all you want is to share state across all components, modify them anywhere you want, and have everyone re-render on change, you can put that state in @shared.