Alterer

Alterers allow us to change the outcome of resolved data, maybe prefix a string with 'http://', format a date, that kind of thing. They do not affect the actual model data, they just alter the resolved data before the binder uses it.

What Actually ARE Alterers?

Alterers are the way we tweak our data, before handing it over to the binder. It is the middle man between resolvable attribute data and the binder. They are very handy when playing with real data, such as prefixing web addresses with 'http://' in a href, or maybe you want to format an SQL date into a nice human readable date, maybe you want to invert a boolean (!). Alter the data how you see fit, before letting the binder use it, and you can fine tune what your binder gets.

Tell me More Sir!

Well there is a big difference between the data we get and what we want, maybe all our web address are not URL's, we want URL's but cannot afford to change all the data, well prefix it. You can do lots of interesting things like prefix, suffix and joining arrays of strings, or maybe you want to truthyfy data, invert it, format it, this is where you would use an alterer. Commun use cases are date formatting, we have ported dateFormat by Steven Levithan to an alterer just for this very purpose.

How do we Use Alterers?

Any alterer can be used with any binder, some alterers expect to see specific resolved data types though (based on js typeof command). They do not work with resolvers, they work on the resolved data befor eit is handed over to the binder. So if the data resolved to a string, and an alterer can take a string and add something to it, then all is good. If you feed data into an alterer that it cannot handle, it will ignore it and let the binder use it as is.

Alterers are injected into the core on load, either automatically using the daddy module razilobind or manually when using razilbind-core class directly. We use them as injectables to allow you the option to add the alterers you wish, your own alterers, a mix of both, or something not yet thought of. Yes thats right, you can add your own too, via the razilobind methods or via core injection.

Usage Example

Remember to compile to ES6 peeps, add a watcher if you are continually developing!

Altering a Binders Resolved Data

<!-- single alterer which gets the alterer type from the bound foobar property of the model -->
<p bind-text="foobar" alter-text="foobar"></p>

<!-- single alterer (as a string value) -->
<p bind-text="foobar" alter-text="'trim'"></p>

<!-- multiple alterers (as a strings or property) affects accumulate in order -->
<p bind-text="foobar" alter-text="['trim', 'another', foobar,...]"></p>

<!-- alterers with options (send in data to the alterer) -->
<p bind-text="foobar" alter-text="{'trim': 'options', 'another': ['options'],...}"></p>

A note of Alterering

We don't link arbitary functions to an alterer, if you bind a property or a method, it will use the result of this to look for the alterer to use! If you use a method as the alterer options, the alterer will be supplied the result of the function. If you want custom alterers, then define these and inject them into the tool correctly, see how further down.

If you want to change data with a custom method, you do not need an alterer, just use the method directly with the binder and send the data you want to change, into the method. When the data changes, the method will be re-run! See resolvers to see how to use updateable one way methods.

Show me the Alterers

These are the default alterers at present, they are loaded automatically via razilobind, if you are using the core directly, don't forget to import and inject them, see razilobind-core on how to do this.

All alterers work with resolved data, they work with all or some types of resolved data, derived from JS typeof command.

Stringyfication

Taking data and making a string.

trim Trim whitespace

Trim whitespace from start and end of resolved string.

  • Accepts Resolved Data: string
  • Options Allowed: none
  • Returns Type: string
<span bind-text="foo" alter-text="'trim'"></span>

json JSON stringify

Stringifies various data types to a JSON readable string.

  • Accepts Resolved Data: all types
  • Options Allowed: none
  • Returns Type: string
<span bind-text="foo" alter-text="'json'"></span>

prefix Prefix string with string

Add a string to the start of a string, such as http:// infront of a web address.

  • Accepts Resolved Data: string
  • Options Allowed: string
  • Returns Type: string
<span bind-text="foo" alter-text="{'prefix': 'http://'}"></span>

suffix Suffix string with string

Add a string to the end of a string, such as .com to a TLD name.

  • Accepts Resolved Data: string
  • Options Allowed: string
  • Returns Type: string
<span bind-text="foo" alter-text="{'suffix': '.com'}"></span>

join Catenate strings to string

Catenate an array/object of strings together into a single string.

  • Accepts Resolved Data: object (includes array object!)
  • Options Allowed: none
  • Returns Type: string
<span bind-text="[foo, 'bar']" alter-text="join"></span>
<span bind-text="{'a': foo, 'b': 'bar'}" alter-text="join"></span>

Formatting

Formatting data in specific ways.

date Format date

Format various data types to a date string in a specified format. Ported from dateFormat by Steven Levithan please visit this package to find out more about format types.

  • Accepts Resolved Data: string, number, object, symbol
  • Options Allowed: string
  • Returns Type: string
<span bind-text="'1988/10/10'" alter-text="{'date': 'mmmm d, yyyy'}"></span>
<span bind-text="something.date" alter-text="{'date': 'yyyy-mm-dd'T'HH:MM:ss'}"></span>
<span bind-text="1234567890" alter-text="{'date': 'isoUtcDateTime'}"></span>

Booleanification

Checking if something does or does not.

not Boolean inversion

Return a boolean inversion of the resolved data. False becomes true, '' becomes true, [1,2] becomes false.

  • Accepts Resolved Data: all types
  • Options Allowed: none
  • Returns Type: boolean
<span bind-show="foo" alter-show="not"></span>

equal Check if the same

Checks if the resolved data is equal to an option value.

  • Accepts Resolved Data: all types
  • Options Allowed: all types
  • Returns Type: boolean
<span bind-show="foo.bar" alter-text="{'equal': foo.bar2}"></span>

identical Check if identical

Checks if the resolved data is identical (equal in value and type) to an option value.

  • Accepts Resolved Data: all types
  • Options Allowed: all types
  • Returns Type: boolean
<span bind-show="foo.bar" alter-text="{'identical': foo.bar2}"></span>

Making your own Alterers

There are two ways to add your own alterers to the system, by injecting them with the addAlterers() method bundled with razilobind, or if you have decided to import the core and have extended it, you may inject them along with all the other alterers in the same fashion.

First off you will need a new alterer, you can start off by taking an existing alterer and copying it, changing the necessary parts. Lets call this your-test.alterer.js.

import {RaziloBindAlterer} from 'razilobind-alterer'

/**
 * Test Alterer
 * A new test alterer
 *
 * Inherits
 *
 * properties: name, accepts
 * method: detect(name, resolved) { return bool }
 */
export default class YourTestAlterer extends RaziloBindAlterer {
  constructor() {
    super();
    this.name = 'your-test'; // this is the name you use in the html, it is how we detect if alterer should be used along with accepts below
    this.accepts = ['string']; // as returned by 'typeof resolvedData'..... [] = any type, ['string'] = string only
  }

  /**
   * alter()
   * Changes resolved data based on options
   * @param mixed resolved The data to change
   * @param mixed options Any options sent in with the alterer
   * @return mixed Changed resolved data
   */
  alter(resolved, options) {
    // add Boom!!! to end of string
    return resolved + ' Boom!!!';
  }
}

You can now import this into your project logic along with razilobind, injecting YourTestAlterer into razilobind by adding custom alterer.

import RaziloBind from 'razilobind'
import YourTestAlterer from './your-test.alterer.js'

var model = {foo: 'foo', bar: 'bar'};

var rb = new RaziloBind();
rb.addAlterers({YourTest: YourTestAlterer});
rb.bind('#test', model);

Or if you have extended the core with your own class, you can add them as follows.

import {RaziloBindCore, RaziloBindCoreDetector} from 'razilobind-core'
import {RaziloBindTrimAlterer, ...} from 'razilobind-alterer'
import {RaziloBindForBinder, ...} from 'razilobind-binder'
import {RaziloBindBooleanResolver, ...} from 'razilobind-resolver'
import YourTestAlterer from './your-test.alterer.js'

export default class YourProjectBind extends RaziloBindCore {
  constructor(options) {
    super(options);

    // Inject injectables, pull in what you need!
    RaziloBindCoreDetector.defaultAlterers = {TrimAlterer: RaziloBindTrimAlterer, ...};
    RaziloBindCoreDetector.defaultBinders = {ForBinder: RaziloBindForBinder, ...};
    RaziloBindCoreDetector.defaultResolvers = {BooleanResolver: RaziloBindBooleanResolver, ...};

    // Inject custom injectables
    RaziloBindCoreDetector.customAlterers = {YourTest: YourTestAlterer, ...};
  }
}

Either way will inject custom alterers, should you wish to replace all default alterers with your own custom ones, substitute the default injectables with your custom ones. Default injectables will also be parsed first, followed by custom ones, you choose how to and what to inject.

Once your new alterer is injected, you should be able to use it like so (don't forget strings are in quotes, miss the quotes and you will be sending a property in!).

<span bind-text="foo" alter-text="'your-test'"></span>

Thats all there is to it folks!