unModified()

Break stuff. Now.

Ractive Tricks

I've got a few of them up my sleeve

January 17, 2016

Recently, I've been writing my projects with Gobble. It's a pretty neat build tool. Feed it files, you get processed files, done. Pull in Rollup and Babel, then you've got an ES6-guzzling machine, ready to pull in your shiny JS. Drop in RactiveJS, a lesser-known but very powerful UI library, now we're talking business. Today, I'm going to show you some neat time-saving tricks.

Inlined templates and scoped styles

Ractive components definitions look similar to Angular directive definitions. However, if your template grows huge, Ractive doesn't have a built-in way to externalize the template the same way Angular directives have templateUrl. Ractive provides the single file component method ala Web Components, but it requires the use of loaders, a bunch of tools and maybe a change in workflow.

But with template strings, you can write your templates right in vanilla JS. This throws away the need for single file components and loaders. You can also write the component CSS this way too!

export default Ractive.extend({
  template: `
    <div class="some-ractive-component">
      <span>{{ message }}</span>
    </div>
  `,
  css: `
    .some-ractive-component{
      color: red;
    }
  `
  data: {
    message: "Hello World"
  }
});

Constants in templates

There are times where I'd need constants on my template, like UI-level limits, minimums and maximums. In order to get them into the template, I merged them into the data. It's even messier if the data was dynamic like from an AJAX response, as I can't pop in the POJO straight away with set. This became messy fast.

const CONSTANTS = {
    LIMIT: 50,
    _minimum,: 2,
}

export default Ractive.extend({
  template: "<div>{{#if population < LIMIT || population > _minimum}}Raaar!{{/if}}</div>"
  data: Object.assign({
    population: 100,
  }, CONSTANTS),
  oninit(){
    $.get().then(response => {
      this.set(Object.assign(response, CONSTANTS));
    })
  }
});

With template strings comes interpolation. I can just pop them in to the string directly. When the parser gets the template, it's essentially hard-coded to the string. But it's still "dynamic" from the authoring perspective.

const LIMIT = 50;
const MINIMUM = 2;

export default Ractive.extend({
  template: `
    <div>
      {{#if population < ${LIMIT} || population > ${MINIMUM} }}Raaar!{{/if}}
    </div>
  `,
  data: {
    population: 100,
  }
});

Shorthand component registration

Ractive isn't like React where it melds JS and markup and make it look like they live in the same space. Ractive takes a more traditional route of data and template. When the parser encounters component-like markup, it checks if a component constructor of the same name was registered in the component.

import Foo from './foo.js';

export default Ractive.extend({
  ...
  template: "<div><Foo /></div>",
  components: {
    "Foo": Foo
  },
  ...
});

One neat trick brought by ES6 is the new notation to initialize object literals. In this new syntax, the key takes its name from the name of the variable that was assigned to it. This makes the code very slick.

import Foo from './foo.js';

export default Ractive.extend({
  ...
  template: "<div><Foo /></div>",
  components: {
    Foo
  },
  ...
});

Conclusion

The one thing I like about Ractive is that it's super flexible. There is no convention. The Right Way™ is subjective as no two apps are the same. There are a lot of ways of doing things, your imagination is the limit. There's nothing stopping you from breaking the rules in programming, I'd say the same when writing with Ractive.