How to add multiple ractive objects on one page? - ractivejs

I am new to Ractive JS.I want to know that How to create multiple ractive objects for individual template?
Thanks In Advance
Samir Kahar

Sounds like you want to use a component. See also the extending Ractive tutorial.

You just create multiple Ractive instances. Here's about the simplest possible ractive template used twice on the same page with different data:
<div id="div1"></div>
<div id="div2"></div>
<script type="text/ractive" id="sampleTemplate">
Hello, {{name}}.
</script>
<script>
var ractive1 = new Ractive({
el: '#div1',
template: '#sampleTemplate',
data: { name: 'World' }
});
var ractive2 = new Ractive({
el: '#div2',
template: '#sampleTemplate',
data: { name: 'World 2' }
});
</script>

Related

global pub-sub/event-handling in ractive

I'm trying to determine the best way to establish cross-component-communication. My first thought was to use ractive.fire with a wildcard, but that doesn't seem to work. Am I trying to mis-use ractive.fire? What would be the suggested way for doing cross-component-communication with ractive?
Ractive.components.pubSub = Ractive.extend({
oninit() {
this.on('*.customEvent', () => alert('pub sub got your custom event!'))
}
})
Ractive.components.something = Ractive.extend({
template: '#something'
})
let ractive = new Ractive({
target: 'body',
template: '#app'
})
<script src="https://cdn.jsdelivr.net/npm/ractive#0.10.3/ractive.js"></script>
<script id="app" type="text/ractive">
<pubSub />
<something />
</script>
<script id="something" type="text/ractive">
<button on-click="#.fire('customEvent')">Fire Custom Event</button>
</script>
Ractive doesn't prescribe a convention for data sharing/cross-component communication. However, it does give you the facilities to do it. A common practice I've seen is to create a "dummy instance" and use its ractive.fire() and ractive.on() methods.
// The dummy instance, make it visible to components.
const pubsub = Ractive()
const SourceComponent = Ractive.extend({
template: '<button click="send()">Click me</button>',
send(){
pubsub.fire('message')
}
})
const ListeningComponent = Ractive.extend({
onInit(){
pubsub.on('message', () => {
console.log('called')
})
}
})
Alternatively, if all you want is to share state across all components, modify them anywhere you want, and have everyone re-render on change, you can put that state in #shared.

Filter Collections using iron-router

I have a template rendering my Collection using {{#each Collection}}, I'm using iron-router to route this template like this:
Router.route('/home', function () {
this.render('home');
this.layout('header');
});
how can i use a "books" filter button so iron-router apply that filter to the subscription so i can only see the filtered version of my Collection like the following:
Collection.find({category: "books"});
There are a number of ways to approach this but one simple way would be to define a sub-route that takes a category as a parameter:
Router.route('/collections/:category',{
name: 'collections',
layoutTemplate: 'header',
data(){
return Collections.find({category: this.params.category});
}
});
Then your button code can just do Router.go('/collections/books') but you can now have multiple buttons each tied to different categories.
As suggested here https://guide.meteor.com/data-loading.html#organizing-subscriptions you can manage your subscription in Template and not in the route. So you can do:
import {ReactiveDict} from 'meteor/reactive-dict';
import {Template} from 'meteor/templating';
Template.home.onCreated(function(){
var that = this;
that.state = new ReactiveDict();
//that.state.set('selected-category',YOUR_DEFAULT_CATEGORY);
that.autorun(function(){
that.subscribe('subscription-name',that.state.get('selected-category'));
});
});
Template.home.events({
'click .js-category':function(e,tpl){
let category = tpl.$(e.currentTarget).data('category');
tpl.state.set('selected-category',category);
}
});
And in your Template:
<button type="button" data-category="books" class="js-category">Books</button>
Hope this will help you to find the right solution for your

Can Ractive events work in markup rendered with the triple-stash syntax?

If I have the following in my Ractive template:
<span on-click='handleClick'>click me</span>
Then I can listen for the click with this:
app.on({
handleClick:function() {
alert("clicked!") ;
}
})
But lets say I have that same markup stored in a string variable called clicklyspan:
app.set("clicklyspan", "<span on-click='handleClick'>click me</span>")
and I render it in the template using the triple-stash syntax:
{{{clicklyspan}}}
The handleClick listener no longer gets fired. Is there anything I can do to force some kind of update to the rendered template so that the listener works? Say, after I do that app.set() call?
Here's a fiddle demonstrating the problem.
Thanks,
Dave
I have never used Ractive, but I did some research and it seems you have to use partials, like this:
var app = new Ractive({
el: 'container',
template: '#template',
data: {
myFunction: function() {
var template = '<a on-click="handleClick">I can now be clicked as well!</a>';
if (!this.partials.myFunction) {
this.partials.myFunction = template;
}
else {
this.resetPartial('myFunction', template);
}
return 'myFunction';
}
}
});
You will also need to use this instead of the triple mustache:
{{> myFunction() }}
Here's the corresponding jsfiddle.
Of course, replace myFunction with whatever name you like.
Related question I found useful:
RactiveJS events on tripple mustache

Not converted text/ractive to HTML

Why not converted text/ractive to HTML.
This is result in browser:
This is code in page which include template:
This is the template:
This is error in console:
This if instance using the template:
It's a template. You need to load Ractive in the browser and create a new instance using the template:
var ractive = new Ractive({
el: '#your-target-element',
template: '#step-1',
data: yourData
});

Recursive component inclusion

I'm looking at the Authoring Ractive.js components document on github from Rich-Harris.
It starts with invoking the foo component and including it this way:
<link rel='ractive' href='foo.html' name='foo'>
<p>This is an imported 'foo' component: <foo/></p>
Which I understand as declaring foo.html as a component and calling it on the foo tag, and this would not require doing a ractive.load (although I did not understand yet where the data loading would occur).
As it does not work at all (no loading of the component), I'm wondering if I mis-understood this part.
Has anyone use this and could give me a complete example?
Components themselves are independent of the loading mechanism.
In the simplest form, components can be declared in javascript:
Ractive.components.foo = Ractive.extend({
template: '#foo' // id of script tag, or can be inline string,
// other options
});
var ractive = new Ractive({
template: '<p>This is an main view with a 'foo' component: <foo/></p>'
});
Creating components is covered here in the docs.
There are many ways to package and load components. Using the link tag, as in your example, requires using ractive-load to actually load the components:
<!-- name is optional if same as file name -->
<link rel='ractive' href='foo.html' name='foo'>
<script src='ractive.js'></script>
<script src='ractive-load.js'></script>
<script>
// calling load() with no parameters loads all link tags and
// registers them as global components
Ractive.load().then( function () {
var ractive = new Ractive({
el: 'body',
template: 'I have access to the <foo/> component!',
data: { ... }
});
// or you could instantiate a component via:
var app = new Ractive.components.app({
... /options
});
}).catch( handleError );
</script>

Resources