4

Let's say I have two templates: An index template with my main content, and a changelog template with the changelog. They are considered different templates:

<script id='index' type='text/ractive'>
// ...
</script>

<script id='changelog' type='text/ractive'>
// ...
</script>

ractive = new Ractive({...});

What would be the best way to be able to change between these templates on the fly and programmatically? I was thinking that I could change the template variable for the Ractive instance, i.e. ractive.template = '#changelog'; but changing that doesn't update the output content. Ideally, I'd like it so that a user could click a button in a menu and switch between index and changelog.

josh
  • 9,656
  • 4
  • 34
  • 51

2 Answers2

7

Changing templates dynamically is something that we're looking at for a future release - see this GitHub thread for some background.

At present, the best way to achieve this would be something like this:

<script id='main' type='text/ractive'>
  {{# page === 'index' }}
    {{>index}}
  {{/}}

  {{# page === 'changelog' }}
    {{>changelog}}
  {{/}}
</script>

<script id='index' type='text/ractive>...</script>
<script id='changelog' type='text/ractive>...</script>

Then, inside your app, ractive.set('page', 'changelog') to hide the index template and display the changelog.

If you wanted to do this without having loads of <script> tags, you'd set the options like this:

ractive = new Ractive({
  /* other options... */
  template: mainTemplate,
  partials: {
    index: indexTemplate,
    changelog: changelogTemplate
  }
});
Rich Harris
  • 28,091
  • 3
  • 84
  • 99
  • Ah, okay, thanks! That's what I was thinking but wasn't sure. I tried something like that earlier today but it seemed to reset certain variables within the template, which made some sections disappear or not work properly until I refresh the content. Are there any known bugs with this method? – josh Jun 16 '14 at 12:56
  • That sounds very odd - sounds like a bug, any chance you could reproduce it by forking this fiddle? http://jsfiddle.net/rich_harris/va6jU/ Thanks – Rich Harris Jun 16 '14 at 16:44
  • Actually, after looking more closely during some testing I noticed that it's not a bug with the templates - the DOM shows the fields that should be there - but may be a bug with the way that the template system affects inline styles. When I changed the page back and forth, the inline styles disappeared on those elements which causes rendering issues. – josh Jun 16 '14 at 18:39
  • Are the inline styles added via Ractive, or is something else setting those styles? Ractive will create fresh DOM each time you switch between the two pages (though you could hide the non-visible page rather than destroying it if that's what you need to do to preserve added styles) – Rich Harris Jun 16 '14 at 21:50
  • Yeah I thought about that after I added my comment; I'm using jQuery to add the styles, which means that when the template gets re-rendered it'll disappear. Is there a built in way for Ractive to add styles? I assume probably not, and I didn't see anything in the docs. – josh Jun 16 '14 at 22:07
  • The best way to do any kind of imperative DOM manipulation is with [decorators](http://docs.ractivejs.org/latest/writing-decorator-plugins). See [this SO answer](http://stackoverflow.com/questions/23083841/ractivejs-and-jquery-plugins) for an example. With decorators, the work is done as soon as the node enters the DOM, and you supply a teardown method that *undoes* any work before it leaves the DOM again. Alternatively, you can always do `
    ...
    ` or similar.
    – Rich Harris Jun 17 '14 at 01:52
3

I'm not sure if I agree with the checked answer. There is a much simpler way to change templates, given you know the id of said template. There's a neat function in ractive called 'resetTemplate' which allows you to change templates of a given ractive object. As such:

var rxObject = new Ractive({
  el: '#element',
  template: '#template_1'
});

//what you can do at any point in your code is call ractive.resetTemplate, as such:

rxObject.resetTemplate('#template_2');
<script id="template_1" type="text/html">
  
  //content of this script
  
</script>

<script id="template_2" type="text/html">
  
  //content of this script
  
</script>

I believe it's more complicated and more work doing it the way the 'checked' answer describes.

Omeed
  • 53
  • 1
  • 8