comerc:template2
MVVM for Meteor with Two-Way Binding via Model Schema.
Table of Contents generated with DocToc
- Intro
- Key features
- How to run Demo
- Installation
- Basic Usage
- API
- Two-Way Binding features
- Configuration
- TODO
- Inspired by
- License
Fork of TemplateController (what difference):
Supports the best practices of writing Blaze templates
Blaze is awesome but writing the Js part of templates always felt a bit awkward. This package just provides a very thin layer of syntactic sugar on top of the standard API, so you can follow best practices outlined in the Blaze guide more easily.
Now you can turn this:
Template.hello.onCreated(function helloOnCreated() {
// counter starts at 0
this.counter = new ReactiveVar(0);
});
Template.hello.helpers({
counter() {
return Template.instance().counter.get();
},
});
Template.hello.events({
'click button'(event, instance) {
// increment the counter when button is clicked
instance.counter.set(instance.counter.get() + 1);
},
});into that:
Template2('hello', {
states: {
counter: 0 // default value
},
events: {
'click button'() {
// increment the counter when button is clicked
this.state.counter += 1;
}
}
});Yeah i have used ViewModel before – it's also nice, and there are also Blaze Components. My only "problem" with these existing packages is that they introduce new concepts on top of the standard Blaze api. I just wanted less boilerplate and that best practices like setting up ReactiveVars, validating properties passed to a template or accessing Template.instance() become a no-brainer for the whole team.
The idea for this package came up during a Meteor training with some Devs where realized how complicated it is to explain the best practices with Blaze and that they had a ton of questions like "how can i access the template instance in helpers / event handlers" or "how does a template manage state" – which is so basic that it should be the easiest thing in the world.
- Compatible with Blaze Template - we love it.
- Minimum changes for migration your great project to Template2.
- One time declaration of variables to Model via
<input value-bind>attribute. - Validate input data and get doc for writing to Model without coding.
- Support of SimpleSchema, may be extended for support any other Model (Astronomy etc.)
- Usage of Two-Way Binding Features without Model.
$ git clone https://github.com/comerc/meteor-template2.git
$ cd meteor-template2
$ meteor
...then http://localhost:3000
In your Meteor app directory, enter:
$ meteor add comerc:template2
$ meteor add aldeed:simple-schema
$ meteor add aldeed:collection2
Posts = new Mongo.Collection('posts');
PostSchema = new SimpleSchema({
myValue: {
type: String,
min: 3,
defaultValue: '777'
}
});
Posts.attachSchema(PostSchema);Template2('hello', {
// Validate the properties passed to the template from parents
propsSchema: new SimpleSchema({
param: { type: String }
}),
// Setup Model Schema
modelSchema: Posts.simpleSchema(),
// Setup reactive template states
states: {},
// Helpers & Events work like before but <this> is always the template instance!
helpers: {}, events: {},
// Lifecycle callbacks work exactly like with standard Blaze
onCreated() {}, onRendered() {}, onDestroyed() {},
});
// events declaration by old style, but with context by Template.instance()
Template.hello.eventsByInstance({
'submit form': function(e) {
e.preventDefault();
// Get doc after clean and validation for save to model
this.viewDoc(function(error, doc) {
if (error) return;
Posts.insert(doc);
});
}
});
// onRendered declaration by old style may also be used
Template.hello.onRendered(function() {
var self = this;
this.autorun(function() {
var doc = Posts.findOne();
if (doc) {
// Set doc from model to view
self.modelDoc(doc);
}
});
});Work exactly the same as with standard Blaze.
Work exactly the same as normal but this inside the handlers is always
a reference to the Template.instance(). In most cases that's what you want
and would expect. You can still access the data context via this.data.
Any data passed to your component should be validated to avoid UI bugs
that are hard to find. You can pass any object to the propsSchema option, which
provides a clean and validate function. clean is called first and can
be used to cleanup the data context before validating it (e.g: adding default
properties, transforming values etc.). validate is called directly after
and should throw validation errors if something does not conform the schema.
This api is compatible but not limited to
SimpleSchema.
This is a best practice outlined in the
Blaze guide - validate data context
section. Template2 does provide a bit more functionality though:
any property you define in the schema is turned into a template helper
that can be used as a reactive getter, also in the html template:
Template2('hello', {
propsSchema: new SimpleSchema({
messageCount: {
type: Number, // allows only integers!
defaultValue: 0
}
})
});… and you can access the value of messageCount anywhere in helpers etc. with
this.props.messageCount
a parent template can provide the messageCount prop with standard Blaze:
If the parent passes down anything else than an integer value for messageCount
our component will throw a nice validation error.
You can pass any object to the modelSchema option, which provides a schema and newContext function.
This api is compatible but not limited to SimpleSchema.
Each state property you define is turned into a ReactiveVar and you can get
the value with this.state.myProperty and set it like a normal property
this.state.myProperty = newValue. The reason why we are not using
ReactiveVar directly is simple: we need a template helper to render it in
our html template! So Template2 actually adds a state template
helper which returns this.state and thus you can render any state var in
your templates like this:
But you can also modify the state var easily in your Js code like this:
events: {
'click button'() {
this.state.counter += 1;
}
}Since each state var is turned into a separate reactive var you do not run into any reactivity issues with re-rendering too much portions of your template.
Get doc via callback after clean and validation for save to model.
var t = Template.instance();
t.viewDoc(function(error, doc) {
if (error) return;
Posts.insert(doc);
});Set doc from model to view.
var t = Template.instance();
var doc = Posts.findOne();
t.modelDoc(doc);Described here.
Enables you to configure the props cleaning operation of libs like SimpleSchema. Checkout SimpleSchema clean docs to see your options.
Here is one example why removeEmptyStrings: true is the default config:
i18n might initially return an empty string for your translation.
This would cause an validation error because SimpleSchema removes empty strings by default when cleaning the data.
The same as previos, but for model.
- AstronomySchema (for compatible with SimpleSchema)
- Add
originalanderror* helpers, like useful:forms - Wait for throttle & debounce before form submit
- Demo with meteor7
- Actions, like blaze-magic-events
- Remove underscore dependence
- Demo with Material Design Lite
- Remove helpers
propsOfandstateOf, we may use{{state.[field-name]}} - Dependencies
- Conditional formatting and disabling
Template2.mixin()rename toTemplate2()Template2.setPropsCleanConfiguration(Object)rename toTemplate2Config.propsCleanTemplate2.setModelCleanConfiguration(Object)rename toTemplate2Config.modelClean
- jQuery.my
- Aurelia
- Vue
- ReactLink
- Blaze
- aldeed:autoform
- manuel:viewmodel
- nov1n:reactive-bind
- space:template-controller
- themeteorites:blaze-magic-events
- moberegger:validated-template
- voidale:helpers-everywhere
- useful:blaze-state
- useful:forms
- ouk:template-destruct
- mpowaga:template-schema
- peerlibrary:blaze-components
- aldeed:template-extension
- meteorhacks:flow-components
- kadira:blaze-plus
- templates:forms
MIT