Skip to content

Instantly share code, notes, and snippets.

@jfairbank
Last active September 15, 2016 09:34
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save jfairbank/3b857598c2f7b1e12747 to your computer and use it in GitHub Desktop.
Save jfairbank/3b857598c2f7b1e12747 to your computer and use it in GitHub Desktop.
Polymer components with Marionette.js
/**
* Copyright 2014 Jeremy Fairbank <elpapapollo@gmail.com>
* License: https://github.com/jfairbank/marionette.polymerview/blob/master/LICENSE
*/
Marionette.PolymerView = Marionette.View.extend({
constructor: function(options) {
Marionette.View.prototype.constructor.apply(this, arguments);
this._setPublishedKeys();
this._initAttrsFromModel();
this._initModelEvents();
this._initPolymerEvents();
},
_setPublishedKeys: function() {
this._publishedKeys = _.keys(this.el.publish);
},
_initAttrsFromModel: function() {
this._setElAttrs(this.model.attributes);
},
_initModelEvents: function() {
this.listenTo(this.model, 'change', this._updateElAttrsFromModel);
},
_initPolymerEvents: function() {
if (!this.events) {
this.events = {};
}
_.each(this._publishedKeys, function(key) {
this.events['change:' + key] = _.bind(this._updateAttrFromEl, this, key);
}, this);
this.delegateEvents();
},
_updateAttrFromEl: function(attributeName) {
var value = this.el[attributeName];
this.model.set(attributeName, value);
},
_updateElAttrsFromModel: function() {
this._setElAttrs(this.model.changed);
},
_setElAttrs: function(attributes) {
var attributeNames = _.intersection(_.keys(attributes), this._publishedKeys);
_.each(attributeNames, this._setElAttr, this);
},
_setElAttr: function(attributeName) {
this.el[attributeName] = this.model.get(attributeName);
}
});
<link rel="import" href="../bower_components/polymer/polymer.html">
<polymer-element name="name-tag" attributes="name job">
<template>
<div>Hello, my name is {{name}}</div>
<div>My job is {{job}}</div><br>
<div>Name: <input type="text" value="{{name}}"></div>
<div>Job: <input type="text" value="{{job}}"></div>
</template>
<script>
Polymer({
name: 'Joe Schmoe',
job: 'Plumber'
});
</script>
</polymer-element>
<link rel="import" href="../bower_components/polymer/polymer.html">
<polymer-element name="name-tag" attributes="name job">
<template>
<div>Hello, my name is {{name}}</div>
<div>My job is {{job}}</div><br>
<div>Name: <input type="text" value="{{name}}"></div>
<div>Job: <input type="text" value="{{job}}"></div>
</template>
<script>
Polymer({
name: 'Joe Schmoe',
job: 'Plumber',
nameChanged: function() {
this.fire('change:name');
},
jobChanged: function() {
this.fire('change:job');
}
});
</script>
</polymer-element>
<!-- Load js lib -->
<script src="bower_components/webcomponentsjs/webcomponents.min.js"></script>
<!-- Import name tag element -->
<link rel="import" href="name-tag-1.html">
<!-- Default Usage -->
<name-tag></name-tag>
<!-- Supply Attributes -->
<name-tag name="Jeremy" job="Web Developer"></name-tag>
var NameTag = Marionette.PolymerView.extend({
tagName: 'name-tag'
});
// Assuming we have a DOM element with id 'main'
var mainRegion = new Marionette.Region({
el: '#main'
});
var person = new Backbone.Model({
name: 'Jeremy Fairbank',
job: 'Web Developer'
});
var nameTag = new NameTag({
model: person
});
mainRegion.show(nameTag);
var Person = Backbone.Model.extend();
var person = new Person({
name: 'Jeremy Fairbank',
job: 'Web Developer'
});
var nameTag = new NameTag({
model: person
});
var personView = new PersonView({
model: person
});
var personFormView = new PersonFormView({
model: person
});
var layout = new Layout();
layout.render();
layout.getRegion('nameTag').show(nameTag);
layout.getRegion('personView').show(personView);
layout.getRegion('personForm').show(personFormView);
<script id="layout-template" type="text/html">
<div class="column">
<h2>Name Tag PolymerView</h2>
<div id="name-tag-container"></div>
</div>
<div class="column">
<h2>Person View</h2>
<div id="person-view-container"></div>
</div>
<div class="column">
<h2>Person Form View</h2>
<div id="person-form-container"></div>
</div>
</script>
<script id="person-view-template" type="text/html">
<h2>Person View</h2>
<h3>Name: <%= name %></h3>
<h3>Job: <%= job %></h3>
</script>
<script id="person-form-template" type="text/html">
<div>Name: <input type="text" name="name" value="<%= name %>"></div>
<div>Job: <input type="text" name="job" value="<%= job %>"></div>
</script>
var Layout = Marionette.LayoutView.extend({
el: '#main',
template: '#layout-template',
regions: {
nameTag: '#name-tag-container',
personView: '#person-view-container',
personForm: '#person-form-container'
}
});
var NameTag = Marionette.PolymerView.extend({
tagName: 'name-tag'
});
var PersonFormView = Marionette.ItemView.extend({
template: '#person-form-template',
ui: {
name: 'input[name=name]',
job: 'input[name=job]'
},
modelEvents: {
'change': 'updateUI'
},
events: {
'keyup input': 'updateModel'
},
updateUI: function() {
var ui = this.ui;
var changed = this.model.changed;
_.each(changed, function(value, key) {
if (ui[key].val() != value) {
ui[key].val(value);
}
});
},
updateModel: function(e) {
var key = e.target.name;
var value = e.target.value;
this.model.set(key, value);
}
});
var PersonView = Marionette.ItemView.extend({
template: '#person-view-template',
modelEvents: {
change: 'render'
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment