|
| 1 | +--- |
| 2 | +title: Advanced Configuration |
| 3 | +--- |
| 4 | +In addition to supplying static values for configurations options, some of the Ractive options |
| 5 | +can be specified using a function that will resolve when the ractive instance is instantiated, |
| 6 | +and re-evaluated upon {{{createLink 'ractive.reset()'}}}. |
| 7 | + |
| 8 | +An option function may be supplied to either {{{createLink 'Ractive.extend()'}}} or {{{createLink 'new Ractive()'}}}. |
| 9 | + |
| 10 | +Option functions receive the post-configured `data` option as the first argument and `this` in |
| 11 | +the function refers to the ractive instance being instantiated. |
| 12 | +Bear in mind that the ractive instance is in the process of being configured, so not all options |
| 13 | +are necessarily configured yet, and functional methods like `observe` or `set` should not be called. |
| 14 | + |
| 15 | +## Template |
| 16 | + |
| 17 | +The template can be specified using the return value of an option function: |
| 18 | + |
| 19 | +```js |
| 20 | +new Ractive({ |
| 21 | + template: function ( data ) { |
| 22 | + return data.foo ? '<p>hello world</p>' : '<div>yes, we have no foo</div>'; |
| 23 | + }, |
| 24 | + data: { foo: true } |
| 25 | +}); |
| 26 | +``` |
| 27 | +The return value can be any of the valid template options: a preparsed template, |
| 28 | +a string that will parsed as a template, or an string starting with `#` that refers to an element id from which |
| 29 | +the template should be retrieved. |
| 30 | + |
| 31 | +In general, these should be sufficient for most use cases. However, if you need to dissect templates or extract |
| 32 | +partials dynamically, the template option function also receives a second argument |
| 33 | +with a helper parser object `p` that offers the following methods: |
| 34 | + |
| 35 | +> ### p.fromId( id ) |
| 36 | +> Retrieves the template from the DOM `<script>` tag specified by `id`. Leading `#` is optional. Make sure to set `type='text/ractive'` on the `<script>` tag or the browser will try and execute the contents as javascript and you'll get an exception. |
| 37 | +
|
| 38 | +> ### p.isParsed( template ) |
| 39 | +> Test whether the supplied instance has already been parsed |
| 40 | +
|
| 41 | +> ### p.parse( template [, parseOptions ] ) |
| 42 | +> Parses the template via {{{createLink 'Ractive.parse()' }}}. If no `parseOptions` specified, defaults to those |
| 43 | +> of the current instance. Full Ractive runtime must be loaded. |
| 44 | +
|
| 45 | +During a {{{createLink 'ractive.reset()' }}} operation, an option function for a template will be re-evaluated |
| 46 | +and _if_ the return value changes the ractive instance will be re-rendered. |
| 47 | +
|
| 48 | +## Partials |
| 49 | +
|
| 50 | +The value for a named partial can also be specified using a function: |
| 51 | +
|
| 52 | +```js |
| 53 | +new Ractive({ |
| 54 | + template: '<div>\{{>dynamicPartial}}</div>', |
| 55 | + partials: { |
| 56 | + dynamicPartial: function ( data ) { |
| 57 | + return data.condition ? '<p>hello world</p>' : '<div>yes, we have no foo</div>'; |
| 58 | + } |
| 59 | + } |
| 60 | +}); |
| 61 | +``` |
| 62 | +
|
| 63 | +Partial option functions also received the helper parser `p` as the second argument. This is useful in |
| 64 | +partials as you cannot return an element id from a partial function and must use `p.fromId` to return |
| 65 | +the template content of an element. |
| 66 | +
|
| 67 | +Partial functions also cannot directly return the string token of a registered partial. Instead, |
| 68 | +return the value from the ractive instance: |
| 69 | +
|
| 70 | +```js |
| 71 | + partials: { |
| 72 | + dynamicPartial: function ( data ) { |
| 73 | + // assuming data.partial is the string token of a registered partial: |
| 74 | + return this.partials[data.partial]; |
| 75 | + } |
| 76 | + } |
| 77 | +``` |
| 78 | +
|
| 79 | +## Components |
| 80 | +
|
| 81 | +A component value can be specified using an option function. The return value can either be |
| 82 | +a component or (unlike partials) the string token of a registered component: |
| 83 | +
|
| 84 | +```js |
| 85 | +Ractive.components.view1 = Ractive.extend({...}); |
| 86 | +Ractive.components.view2 = Ractive.extend({...}); |
| 87 | +
|
| 88 | +new Ractive({ |
| 89 | + template: '<div><dynamicComponent/></div>', |
| 90 | + components: { |
| 91 | + dynamicComponent: function ( data ) { |
| 92 | + return data.foo ? 'view1' : 'view2'; |
| 93 | + } |
| 94 | + } |
| 95 | +}); |
| 96 | +``` |
| 97 | +
|
| 98 | +## Data |
| 99 | +
|
| 100 | +The data option function can either return a value or use the prototype inheritance chain to construct the |
| 101 | +data object. Use `this._super` to call the parent data option. Ractive will handle integrating |
| 102 | +static data options and data option functions. If a return value is specified, further parent data options |
| 103 | +will not be considered. |
| 104 | +
|
| 105 | +```js |
| 106 | +
|
| 107 | +var Component1 = Ractive.extend({ |
| 108 | + data: { |
| 109 | + formatTitle: function (title) { |
| 110 | + return '"' + title.toUpperCase() + '"'; |
| 111 | + } |
| 112 | + } |
| 113 | +}); |
| 114 | +
|
| 115 | +var Component2 = Component1.extend({ |
| 116 | + data: function( data ) { |
| 117 | + this._super( data ); |
| 118 | + data.scale = 5; |
| 119 | + } |
| 120 | +}); |
| 121 | +
|
| 122 | +var ractive = new Component2({ |
| 123 | + data: { foo: 'bar' } |
| 124 | +}) |
| 125 | +
|
| 126 | +// r.data: { foo: "bar", formatTitle: function, scale: 5 } |
| 127 | +
|
| 128 | +``` |
| 129 | +
|
| 130 | +The data object instance passed to the instantiated ractive instance will always be retained as |
| 131 | +the `ractive.data` instance, _unless_ a return value is specified from an option function in which |
| 132 | + case that return value instance will be used as `ractive.data` |
| 133 | +
|
| 134 | +### Copying Parent Data |
| 135 | +
|
| 136 | +Because parent data is common to all instances, you can use an option function to return a |
| 137 | +unique copy of the data. |
| 138 | +
|
| 139 | +```js |
| 140 | +
|
| 141 | +var Shared = Ractive.extend({ |
| 142 | + data: { |
| 143 | + foo: { bar: 42 } |
| 144 | + } |
| 145 | +}); |
| 146 | +
|
| 147 | +var shared1 = new Shared(); |
| 148 | +var shared2 = new Shared(); |
| 149 | +shared1.set( 'foo.bar', 12 ); |
| 150 | +shared2.get( 'foo.bar' ); // returns 12 |
| 151 | +
|
| 152 | +
|
| 153 | +var NotShared = Ractive.extend({ |
| 154 | + data: function () { |
| 155 | + return { |
| 156 | + foo: { bar: 42 } |
| 157 | + }; |
| 158 | + } |
| 159 | +}); |
| 160 | +
|
| 161 | +var notShared1 = new NotShared(); |
| 162 | +var notShared2 = new NotShared(); |
| 163 | +notShared1.set( 'foo.bar', 12 ); |
| 164 | +notShared2.get( 'foo.bar' ); // returns 42 |
| 165 | +
|
| 166 | +``` |
| 167 | +
|
| 168 | +### Asynchronous Data |
| 169 | +
|
| 170 | +A data option function can be a handy way to fetch asynchronous data _and_ supply initial synchronous values: |
| 171 | +
|
| 172 | +```js |
| 173 | +data: function () { |
| 174 | +
|
| 175 | + $.get( 'somedata.url', function( data ) { |
| 176 | + this.set( '', data ); |
| 177 | + }.bind(this) ); |
| 178 | +
|
| 179 | + return { |
| 180 | + foo: 'default' |
| 181 | + }; |
| 182 | +} |
| 183 | +``` |
| 184 | +
|
| 185 | +### Specifying a Model |
| 186 | +
|
| 187 | +Another use of the data option function is to provide a model: |
| 188 | +
|
| 189 | +```js |
| 190 | +data: function ( data ) { |
| 191 | + return new Model( data ); |
| 192 | +} |
| 193 | +``` |
| 194 | +
|
| 195 | +If you use a constructor guard clause (currently popular for `new`-less use of javascript constructors), |
| 196 | +you can directly supply the model: |
| 197 | +
|
| 198 | +
|
| 199 | +```js |
| 200 | +function Model ( data ) { |
| 201 | + if ( !( this instanceof Model) ) { return new Model( data ); } |
| 202 | + // model setup |
| 203 | +} |
| 204 | +
|
| 205 | +var MyComponent = Ractive.extend({ |
| 206 | + data: Model |
| 207 | +}); |
| 208 | +
|
| 209 | +var r = new MyComponent({ |
| 210 | + data: { foo: 'bar' } |
| 211 | +}) |
| 212 | +``` |
0 commit comments