How do Meteor's blaze and Famo.us play together?
Asked Answered
C

5

12

2 Technologies:

  • Meteor with the blaze templating engine
  • Famo.us with their awesome gui framework

I come from the meteor side, I personally like using {{mustache}} (handlebars) to drive the gui from data, the reactive session / database makes this really efficient and intuitive.

Now came famo.us and all its advantages, but the drawback of a code based gui is that there is no place for handlebars anymore…

  • What is the current practice for mixing both technologies together ?
  • Are they completely dissociative ?
  • Is using the "observe" / "Deps.autorun" mechanism a common practice everywhere a famo.us element to be updated by a meteor reactive item ?
Cioffred answered 15/4, 2014 at 12:15 Comment(2)
@gadicc I just saw your post on the meteor digest, it seems that it is still early for a definitive answer, waiting for more contributors.Cioffred
deleted my comment. since the code is public now, i've posted as an Answer. happy to see what other approaches people come up with.Nebulose
N
16

I just released a preview of famous-components, which is an attempt at a tight integration between Blaze and Famous. All the other approaches I've seen so far side step most of Blaze, and require writing large amounts of code in JavaScript, which felt very unnatural to me in Meteor. Meteor code should be small, concise and easy with powerful results. Here are a few examples of what it looks like: (each template forms a renderNode, any HTML gets put on a Surface. Modifiers/views/options are specified as a component attributes)

<template name="test">
  {{#Surface size=reactiveSizeHelper}}
    <p>hello there</p>
  {{/Surface}}

  {{#if loggedIn}}
    {{>SequentialLayout template='userBar' direction="X"}}
  {{else}}
    {{>Surface template='pleaseLogIn' origin="[0.5,0.5]"}}
  {{/if}}
</template>

Scrollview (can be split into sub templates):

<template name="famousInit">
  {{#Scrollview size="[undefined,undefined]"}}
    {{#famousEach items}}
      {{#Surface size="[undefined,100]"}}{{name}}{{/Surface}}
    {{/famousEach}}
  {{/Scrollview}}
</template>

Template.famousInit.items = function() { return Items.find() };

Events:

Template.blockSpring.events({
  'click': function(event, tpl) {
    var fview = FView.fromTemplate(tpl);
    fview.modifier.setTransform(
      Transform.translate(Math.random()*500,Math.random()*300),
      springTransition
    );
  }
});

It also works out the box with iron-router. More details, docs, live demos, all at http://famous-views.meteor.com/

Nebulose answered 18/4, 2014 at 17:8 Comment(0)
D
3

Here's a presentation from the February 2014 Devshop about integrating Meteor with Famous. I haven't seen it in two months, but I do distinctly remember them mentioning that yes, you leverage the Collection.observe pattern.

In short, just like using React or Three.js, Famous is obtuse to the Blaze templating engine. It sidesteps it completely, and renders all elements as flat DOM. Read Mark's answer about this.

A package that leverages the require.js API was submitted to Atmosphere a few days ago. It's called Famono.

I've successfully used it to whip up a minimalistic proof of concept, with observe. You can find the source code on Github, and I also deployed it with meteor deploy.

The code itself is really simple. A collection:

// collections/clicks.js
Clicks = new Meteor.Collection('clicks');

A little fixture on the server to add an item:

// server/fixtures.js
if (Clicks.find().count() === 0) {
  Clicks.insert({ 'number': 0 });
}

And the index.js file:

// client/index.js
UI.body.rendered = function() {
  require("famous-polyfills"); // Add polyfills
  require("famous/core/famous"); // Add the default css file

  var Engine = require('famous/core/Engine');

  var Surface = require('famous/core/Surface');
  var Modifier = require('famous/core/Modifier');

  var mainContext = Engine.createContext();

  var containerModifier = new Modifier({
    origin: [0.5, 0.5]
  });

  mainContext = mainContext.add(containerModifier);

  var square = new Surface({
    size: [200, 200],
    properties: {
      lineHeight: '200px',
      textAlign: 'center',
      background: 'rgba(200, 200, 200, 0.5)'
    }
  });

  Clicks.find().observe({
    added: function(clickCounter) {
      // This is the way that you replace content in your surface.
      // Injecting handlebars templates here will probably do nothing.
      square.setContent(clickCounter.number);
    },

    changed: function(clickCounter) {
      square.setContent(clickCounter.number);
    }
  });

  square.on('click', function() {
    // Hardcoded to work with only the first item in the collection.
    // Like I said, minimal proof of concept.
    var clickCounter = Clicks.findOne();

    Clicks.update(clickCounter._id, { number: clickCounter.number + 1 });
  });

  mainContext.add(square);
};
Desai answered 16/4, 2014 at 17:10 Comment(0)
P
1

It's important to note that surfaces in Famo.us are just divs, and you can plug Blaze templates directly into surfaces.

Zol on GitHub has code for a Famous-Meteor leaderboard

Pops answered 12/5, 2014 at 5:40 Comment(1)
Sure, I just posted an answer with the corresponding code to achieve this easily.Cioffred
C
1

In addition to "Namal Goel"'s answer: here is an example on how to render a Meteor template into a famous surface:

In a .html file

<template name="test">
    This is rendered using Blaze template
</template>

Adding the template to a context:

var MeteorSurface = require('library/meteor/core/Surface');

var meteorTest = new MeteorSurface({
    template: Template.test,
    size: [200, 200]
})

aContext.add(meteorTest);
Cioffred answered 19/5, 2014 at 7:45 Comment(2)
what is MeteorSurface? is this something from Gadi or famono codebase?Cathleencathlene
@Cathleencathlene it's from famonoCioffred
A
0

Here's a vanilla implementation without having to use a library.

Create and empty div for blaze to render into and pass that as content to your famous surface. you now have a reactive content in famous.

mainContext = famous.core.Engine.createContext();

  div = document.createElement('div');
  Blaze.render(Template.moo,div)

  surface = new famous.core.Surface(  
    content: div,
    size: [200, 200],
    properties: {
      backgroundColor: 'rgb(240, 238, 233)',
      textAlign: 'center',
      padding: '5px',
      border: '2px solid rgb(210, 208, 203)',
      marginTop: '50px',
      marginLeft: '50px'
    }
  )

  mainContext.add(surface)
Abode answered 21/5, 2015 at 20:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.