Search code examples
javascriptarraysractivejs

How do I style new DOM entries in an array using ractive?


I have a Ractive instance that modifies an array. When new values appear in the array, I'd like to have the corresponding element highlighted. I currently do this by having some styling on newly created elements. Here's a jsfiddle.

var ractive = new Ractive({
  el: 'main',
  template: `
    <h1>Hello {{name}}!</h1>

    {{ #things:index }}
      <p>{{ things[index] }}</p>  
    {{ /things }}

  `,
  data: function(){
    return {
      things: [
        'banana',
        'carrot'
      ]
    }
  },
  oncomplete: function(){
    var component = this;

    setTimeout(function(){
      component.set('things', ['apple', 'banana', 'carrot'])
    }, 5 * 1000)
  }
});

The only issue is that since ractive re-uses elements, the styling appears on the wrong element.

You'll see when 'banana', 'carrot'] is changed to ['apple', 'banana', 'carrot'], the 'carrot' element is highlighted, instead of the 'apple' element that corresponds with the new value.

What's the best way to style new entries in an array?


Solution

  • Use a recentlyAddedThings cache to add a cache of added items. Here's a working jsfiddle:

    var ractive = new Ractive({
      el: 'main',
      template: `
    
        {{ #things:index }}
    
          <p class="{{ #if recentlyAddedThings.includes(things[index]) }}new{{ /if }}">
            {{ things[index] }}
          </p>  
        {{ /things }}
    
      `,
      data: function(){
        return {
          things: [
            'banana',
            'carrot'
          ],
          recentlyAddedThings: [
    
          ]
        }
      },
      oncomplete: function(){
        var component = this;
    
        var addThing = function(newThing){
          var things = component.get('things')
          var newThing = newThing
          things.push(newThing)
          component.set('things', things.sort())
          component.push('recentlyAddedThings', newThing)
        }
    
        setTimeout(function(){
          addThing('apple') 
        }, 2 * 1000)
        setTimeout(function(){
          addThing('avocado') 
        }, 3 * 1000)
        setTimeout(function(){
          addThing('cheese')  
        }, 4 * 1000)
      }
    });