I have some difficulties understanding the difference between a template and a class in Fuse.
Both seem to be mechanisms to create ‘reusable’ nodes. However, what is the exact use case for a template? Couldn’t I just use a class when a template is needed?
In short, you use ux:Template only where they are expected. Specifically, tags like Each
, Instance
and PageIndicator
expect you to specify templates.
ux:Class is generally used whenever you want to create a reusable component.
Templates are instantiated on demand, automatically. Classes must be instantiated / used (by you) explicitly.
Ok. So to follow up on this I have an example where I load in some data containing books and series. I want the books to be displayed on one page and the series to be displayed on another page. Below is my markup.
<App>
<JavaScript>
const records = [{
id: '1',
name: 'Serie 1',
type: 'serie'
},{
id: '2',
name: 'Book 1',
type: 'book'
},{
id: '3',
name: 'Book 2',
type: 'book'
},{
id: '4',
name: 'Book 3',
type: 'book'
},{
id: '5',
name: 'Serie 2',
type: 'serie'
}]
const getRecords = type => {
return records.map(record => {
return record.type == type
})
}
module.exports = {
books: getRecords('book'),
series: getRecords('serie')
}
</JavaScript>
<Page ux:Class="PageList">
<StackPanel>
<Each Items="{books}">
<Text Value="{name}" />
</Each>
</StackPanel>
</Page>
<DockPanel>
<PageControl ux:Name="Pages">
<PageList ux:Name="Books"/>
<PageList ux:Name="Series"/>
</PageControl>
</DockPanel>
</App>
How do I get the books-page to only display the books and the series-page to only display the series? I tried passing in the data with a property but bindings the curly-brace bindings don’t accept dynamic properties I guess. Would this be a good case for a template? And if so, how?
You’re venturing into territory that is not directly related to your original question. To reply in short: ux:Class
is what you would use to create your custom component, and it has nothing to do with ux:Template
.
Dynamic properties are ok, and that’s explained in Properties.
You will also want to spend some time reading about Observables.
Here’s a way to achieve what you wanted (ES5):
<App>
<JavaScript>
var Observable = require("FuseJS/Observable");
var records = Observable(
{id: '1', name: 'Serie 1', type: 'serie'},
{id: '2', name: 'Book 1', type: 'book'},
{id: '3', name: 'Book 2', type: 'book'},
{id: '4', name: 'Book 3', type: 'book'},
{id: '5', name: 'Serie 2', type: 'serie'}
);
var books = records.where(function(x) {
return x.type == "book";
});
var series = records.where(function(x) {
return x.type == "serie";
});
module.exports = {
books: books,
series: series
}
</JavaScript>
<Page ux:Class="PageList">
<object ux:Property="Items" />
<StackPanel>
<Each Items="{ReadProperty Items}">
<Text Value="{name}" />
</Each>
</StackPanel>
</Page>
<DockPanel>
<PageControl ux:Name="Pages">
<PageList ux:Name="Books" Items="{books}" />
<PageList ux:Name="Series" Items="{series}" />
</PageControl>
</DockPanel>
</App>
Thanks Uldis,
I have been trying to do something with creating properties earlier and passing them into the class. However i couldn’t get it to work, probably because I didn’t create an observable (rookie mistake :)).
Thanks again for clearing this up!
You don’t necessarily need to pass an Observable to an <object
type property. Regular arrays should work just fine there too.
However, that ES6 code of yours (getRecords
function) certainly didn’t return the actual objects that match your criteria. I think it was just an array of booleans. That might’ve been the problem.
My thinking: since you currently need to use Observables in Fuse apps anyway, why not just go with them and take advantage of the reactive operators (such as the .where
that I used) as well?