read


In this article, we'll look at the differences in coding style between different popular front-end tools:

  1. Blaze
  2. React
  3. Angular 1
  4. Angular 2

We'll also see how to install each of these with Meteor, then go over the different coding approaches. Coding is an art, as well as a science, so draw your own opinions.

If you're interested in more, this article is part of a series:

Meteor Install

Setting up a different frontend framework in Meteor is easy.

* "reactive-dict" is optional, but recommended.

meteor add reactive-dict

meteor add reactjs:react
meteor add react-meteor-data

meteor add urigo:angular

meteor add shmck:angular2

Note that Blaze comes pre-installed with the meteor-platform, added when you create a new app.

Setup

The basic "Hello, World" setup.

Model View

{{> demo }}

<template name="demo">
  Hello, World
</template>

App = React.createClass({
  render: function () {
    return(<p>Hello, World</p>);
});  

Meteor.startup(function () {
  React.render(<App />, document.getElementById("app-target"));
});

<div id="app-target">

angular.module('app', [
  'angular-meteor'
]);

function onReady() {
  angular.bootstrap(document, ['app']);
}

angular.module('app')
  .directive('demo', demo);

function demo() {
  return {
    templateUrl: 'client/demo.ng.html',
    controller: DemoCtrl,
    controllerAs: 'app'
  };
}
function DemoCtrl($meteor) {}
/client/index.html

<demo></demo>
/client/demo.ng.html
  
<p>Hello, World</p>

@Component({
  selector: 'demo'
})
@View({
  templateUrl: 'client/demo.ng.html'
})
class Demo {}

bootstrap(Demo);
/client/index.html

<demo></demo>
/client/demo.ng.html
  
<p>Hello, World</p>

Blaze apps are composed of templates, while React & Angular both use components (aka 'directives' in AngularJS).

Meteor Data

Subscribing to published data from a Meteor collection.


Meteor.subscribe('items');

Template.demo.helpers({
  'items': function () {
    return Items.find({});
  }
});

App = React.createClass({
  mixins: [ReactMeteor.Mixin, ReactMeteorData],
  startMeteorSubscriptions: function () {
    Meteor.subscribe('items');
  },
  getMeteorData() {
    var handle = Meteor.subscribe('items');

    return {
      items: () => {
          return Items.find({}).fetch()
      }
    };
  }
});

function demoCtrl($meteor) {
  $meteor.subscribe('items');
  this.items = $meteor.collection(function () {
    return Items.find({});
}

class Demo {
  constructor() {
    Meteor.subscribe('items');
    this.items = Items.find({}).fetch();
  }
}

Blaze & Angular 2 can run Meteor as is, but React & AngularJS require some additional setup.

Loops & Binding

Looping over an array from the model and binding it in the view.

Model View

Template.demo.helpers({
  'numbers': function () {
    return [1, 2, 3]
  }
}); 

{{#each numbers}}
  <li>{{this}}</li>
{{/each}}


App = React.createClass({
  numbers() {
    return [1, 2, 3, 4, 5];
  },
  render() {
    return this.numbers.map((number, index) => {
      return (<li key={index}>{{number}}</li>);
    });
  }
});

function AppCtrl () {
  this.numbers = [1, 2, 3, 4, 5];
}

<li ng-repeat="number in app.numbers track by $index">
  {{number}}
</li>

class Demo {
  constructor () {
    this.numbers = [1, 2, 3, 4, 5];
  }
}

   <li *ng-for="#number of numbers">{{number}}</li>

Loops in React are handled with raw JavaScript, while the other frontend tools provide template looping sugar.

Events

A triggered event from the view that makes a change in the model.

Model View

Template.demo.created = function () {
  this.state = new ReactiveDict();
  this.state.set('model', false);
}
Template.demo.events({
  'click #target': function (e, template) {
     template.state.set('model', true);
  }
})

<button id="target">

App = React.createClass({
  getInitialState: function () {
    return {
      model: false
    };    
  },
  trigger() {
    this.setState({model: true});
  },
  render() {
    return(<p>button onClick="trigger"</p>);
});  

function DemoCtrl () {
  this.model = false;
  this.trigger = function () {
    this.model = true;
  }
}


<button ng-click="app.trigger()">

class Demo {
  constructor () {
    this.model = false;
  }
  trigger() {
    this.model = true;
  }
}

<button (click)="trigger()"> 

Blaze uses JQuery selectors to handle events. Other frameworks bind the event triggers directly to the target elements. AngularJS uses ng- directives, while Angular 2 has a special round-bracket syntax (event) for events.

Dynamic Properties

Changing a class in the view based on the trigger variable used earlier.

Model View

Template.demo.helpers({
  'getStyle': function () {
    if (Template.instance().state.get('trigger')) {
      return {class: 'triggered'};
    }
  }
})

<div {{getStyle}}>

App = React.createClass({
  render() {
      var newStyle = this.state.trigger ? 'triggered' : null;
      return (<div {className: newStyle});
    });
  }
});

<div ng-class="{'triggered': app.trigger}">

<div [class.triggered]="trigger">

React handles dynamic attributes in raw javascript, Blaze provides a way of abstracting away dynamic attributes. AngularJS uses specific ng-* directives whereas Angular 2 has a special square bracket syntax [property] for changing attributes.

Conclusion

Coding style is up to personal taste but also previous programming experience. Despite the subjectivity of rating a 'style', I'll draw a few conclusions:

  • Blaze may be the easiest to learn
  • React is the most inline with raw JavaScript
  • Despite what you may have heard, Angular & Angular 2 are coded in a very similar style

Don't be afraid of learning new frameworks, once you've picked one up you'll find they have a lot in common.

It takes a village to raise a frontend. In part 3, we'll look at another aspect to consider when choosing a framework: the community around it.

Blog Logo

Shawn McKay

Published

Image

ShMcK

JavaScript Web Dev

Back Home