Question

My team is currently using Ractive to show a series of alerts. Each alert:

  • Renders a view with Ractive
  • Start Twitters widgets.js which does some DOM manipulation (to embed Tweets)
  • Changes the data in that view later (when the user selects a different alert)

Since Twitter's DOM changes interfere with Ractive's virtual DOM, we currently use ractive.reset() to reset the DOM after Twitter's widgets.js finishes - the reset() prevents a whole bunch of DOM problems like cannot appendChild of null which would occur because Twitter has manipulated the DOM behind Ractive's back.

However after we run ractive.reset() expressions no longer seem to work.

Is this the right way to handle other libraries that might manipulate the DOM? How can I make expressions continue to work after the reset() ?

Here's a quick demo - note the expression works before the reset() but not afterwards:

    <body>
        <h1>test</h1>
        <div class="bound"></div>
        <script src='http://cdn.ractivejs.org/latest/ractive.js'></script>

        <script>
            var binding = new Ractive({
                el: document.querySelector('.bound'),
                data: {
                    name: 'mike',
                    swaggify: function(string) {return 'SWAG'+string}
                },
                template: '<p>Hello, {{ swaggify(name) }}!</p>'
            })

            binding.reset().then(function(){
                binding.data.name = 'steve'
            })
        </script>
    </body>

And the obligatory JSFiddle

Was it helpful?

Solution

When you call ractive.reset(), it replaces the data object - in this case, that includes the swaggify function. If you put it back, it works fine: http://jsfiddle.net/rich_harris/49JAK/

(Note that I've put the update code immediately after the call to binding.reset() - the changes happen synchronously, the .then() just allows you to schedule a function for when any transitions have completed. It's Promises/A+ compliant so the code inside .then() will always be asynchronous - in some situations that can cause flicker, so sync > async where possible.)

That's probably not what you want though - you want to be able to treat the data and the formatters differently. A good approach is to put the formatters on the prototypal data object that all others inherit from:

var helpers = Ractive.defaults.data; // Ractive.defaults === Ractive.prototype
helpers.swaggify = function(string) {return 'SWAG'+string};

var binding = new Ractive({
  el: document.querySelector('.bound'),
  data: {
    name: 'mike',
    swaggify: function(string) {return 'SWAG'+string}
  },
  template: '<p>Hello, {{ swaggify(name) }}!</p>'
})

Demo of this approach here: http://jsfiddle.net/rich_harris/chYD6/.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top