Permalink
Browse files

Input blocks

Closes #3
  • Loading branch information...
1 parent c51999c commit 98517d5ed038a33ca7d5111d469bbad7d1f43943 @bcardarella bcardarella committed Mar 4, 2013
View
@@ -1,5 +1,4 @@
source 'https://rubygems.org'
-gem 'debugger'
gem 'rake-pipeline', :git => 'https://github.com/livingsocial/rake-pipeline.git'
gem 'ember-dev', :git => 'https://github.com/emberjs/ember-dev.git', :branch => 'master'
View
@@ -27,14 +27,6 @@ GEM
remote: https://rubygems.org/
specs:
colored (1.2)
- columnize (0.3.6)
- debugger (1.2.4)
- columnize (>= 0.3.1)
- debugger-linecache (~> 1.1.1)
- debugger-ruby_core_source (~> 1.1.7)
- debugger-linecache (1.1.2)
- debugger-ruby_core_source (>= 1.1.1)
- debugger-ruby_core_source (1.1.7)
diff-lcs (1.2.1)
execjs (1.4.0)
multi_json (~> 1.0)
@@ -64,6 +56,5 @@ PLATFORMS
ruby
DEPENDENCIES
- debugger
ember-dev!
rake-pipeline!
View
@@ -116,6 +116,64 @@ and each key should correspond to the property in question. The value of
each key can be a string or an array. If an array the first value in the
array will be used for display.
+## Input Blocks
+
+Inputs can be used in the default inline form as already seen or they can
+be used as blocks such as:
+
+```handlebars
+{{#input firstName}}
+ {{inputField firstName}}{{labelField firstName}}
+ <br/>
+ {{erroField firstName}}
+{{/input}}
+```
+
+Inside the block you can add any markup you'd like and everything will
+be wrapped inside the container `div` that is created by the original
+`input`. You can should use the following helpers:
+
+### labelField
+
+Renders the label field used by `input`. The first paramater is the
+property, the remainder paramaters are options.
+
+#### options
+
+* `text` - the text for the label
+
+```handlebars
+{{labelField firstName text="Your first name"}}
+```
+
+### inputField
+
+Renders the input field used by `input`. The first parameter is the
+property, the remaining properties are options. The input itself will
+default a `type` of `password` if the property contains "password",
+likewise for "email".
+
+#### options
+
+* `type` - overrides the type of the input
+* `as` - accepts the following:
+ * `text` - renders a `textarea` input
+
+```handlebars
+{{inputField bio as="text"}}
+{{inputField email}}
+```
+
+### errorField
+
+Renders the error span used by `input` where the first available
+validation error message will be rendered. The first parameter will be
+the property.
+
+```handlebars
+{{errorField firstName}}
+```
+
## Authors ##
* [Brian Cardarella](http://twitter.com/bcardarella)
View
@@ -1,6 +1,5 @@
require 'bundler/setup'
require 'ember-dev/tasks'
-require 'debugger'
task :clean => 'ember:clean'
task :dist => 'ember:dist'
@@ -1,6 +1,6 @@
-require('ember-easyForm/helpers/error');
+require('ember-easyForm/helpers/errorField');
require('ember-easyForm/helpers/formFor');
require('ember-easyForm/helpers/input');
+require('ember-easyForm/helpers/inputField');
+require('ember-easyForm/helpers/labelField');
require('ember-easyForm/helpers/submit');
-require('ember-easyForm/helpers/textArea');
-require('ember-easyForm/helpers/textField');
@@ -1,4 +1,4 @@
-Ember.Handlebars.registerHelper('error', function(property, options) {
+Ember.Handlebars.registerHelper('errorField', function(property, options) {
if (this.get('errors')) {
options.hash.property = property;
return Ember.Handlebars.helpers.view.call(this, Ember.EasyForm.Error, options);
@@ -1,5 +1,6 @@
Ember.Handlebars.registerHelper('input', function(property, options) {
options.hash.inputOptions = Ember.copy(options.hash);
options.hash.property = property;
+ options.hash.isBlock = !!(options.fn);
return Ember.Handlebars.helpers.view.call(this, Ember.EasyForm.Input, options);
});
@@ -0,0 +1,31 @@
+Ember.Handlebars.registerHelper('inputField', function(property, options) {
+ var context = this,
+ propertyType = function(property) {
+ try {
+ return context.constructor.metaForProperty(property);
+ } catch(e) {
+ return null;
+ }
+ };
+
+ options.hash.valueBinding = property;
+
+ if (options.hash.as === 'text') {
+ return Ember.Handlebars.helpers.view.call(context, Ember.TextArea, options);
+ } else {
+ if (!options.hash.type) {
+ if (property.match(/password/)) {
+ options.hash.type = 'password';
+ } else if (property.match(/email/)) {
+ options.hash.type = 'email';
+ } else {
+ if (propertyType(context, property) === 'number' || typeof(context.get(property)) === 'number') {
+ options.hash.type = 'number';
+ } else if (propertyType(context, property) === 'date' || (context.get(property) !== undefined && context.get(property).constructor === Date)) {
+ options.hash.type = 'date';
+ }
+ }
+ }
+ return Ember.Handlebars.helpers.view.call(context, Ember.TextField, options);
+ }
+});
@@ -0,0 +1,4 @@
+Ember.Handlebars.registerHelper('labelField', function(property, options) {
+ options.hash.property = property;
+ return Ember.Handlebars.helpers.view.call(this, Ember.EasyForm.Label, options);
+});
@@ -1,4 +0,0 @@
-Ember.Handlebars.registerHelper('textArea', function(property, options) {
- options.hash.valueBinding = property;
- return Ember.Handlebars.helpers.view.call(this, Ember.TextArea, options);
-});
@@ -1,4 +0,0 @@
-Ember.Handlebars.registerHelper('textField', function(property, options) {
- options.hash.valueBinding = property;
- return Ember.Handlebars.helpers.view.call(this, Ember.TextField, options);
-});
@@ -1,4 +1,5 @@
require('ember-easyForm/views/error');
require('ember-easyForm/views/form');
require('ember-easyForm/views/input');
+require('ember-easyForm/views/label');
require('ember-easyForm/views/submit');
@@ -1,7 +1,9 @@
Ember.EasyForm.Input = Ember.View.extend({
init: function() {
this._super();
- this.set('template', Ember.Handlebars.compile('<label for="'+this.labelFor()+'"}}>'+this.labelText()+'</label>\n{{'+this.inputHelper()+' '+this.property+this.printInputOptions()+'}}{{error '+this.property+'}}'));
+ if (!this.isBlock) {
+ this.set('template', Ember.Handlebars.compile(this.fieldsForInput()));
+ }
if(this.get('context').get('errors') !== undefined) {
this.reopen({
error: function() {
@@ -12,58 +14,33 @@ Ember.EasyForm.Input = Ember.View.extend({
},
tagName: 'div',
classNames: ['input', 'string'],
- classNameBindings: ['error:field_with_errors'],
- labelFor: function() {
- return Ember.guidFor(this.get('context').get(this.property));
- },
- labelText: function() {
- return this.label || this.property.underscore().split('_').join(' ').capitalize();
+ classNameBindings: ['error:fieldWithErrors'],
+ fieldsForInput: function() {
+ return this.labelField()+this.inputField()+this.errorField();
},
- inputHelper: function() {
- if(this.as === 'text') {
- return 'textArea';
- } else {
- return 'textField';
- }
+ labelField: function() {
+ var options = this.label ? 'text="'+this.label+'"' : '';
+ return '{{labelField '+this.property+' '+options+'}}';
},
- printInputOptions: function() {
- var string = '', key, inputOptions;
- inputOptions = this.prepareInputOptions(this.inputOptions);
- if (inputOptions) {
- for (key in inputOptions) {
- string = string.concat('' + key + '="' + this.inputOptions[key] + '"');
+ inputField: function() {
+ var options = '', key, inputOptions = ['type'];
+ for (var i = 0; i < inputOptions.length; i++) {
+ key = inputOptions[i];
+ if (this[key]) {
+ options = options.concat(''+key+'="'+this[inputOptions[i]]+'"');
}
- string.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
- return ' ' + string;
}
+ options.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
+
+ return '{{inputField '+this.property+' '+options+'}}';
},
- prepareInputOptions: function(options) {
- var object = this.get('context').get('content');
- if (!options.type) {
- if (this.property.match(/password/)) {
- options.type = 'password';
- } else if (this.property.match(/email/)) {
- options.type = 'email';
- } else {
- if (this.propertyType(object, this.property) === 'number' || typeof(object.get(this.property)) === 'number') {
- options.type = 'number';
- } else if (this.propertyType(object, this.property) === 'date' || (object.get(this.property) !== undefined && object.get(this.property).constructor === Date)) {
- options.type = 'date';
- }
- }
- }
- return options;
+ errorField: function() {
+ var options = '';
+ return '{{errorField '+this.property+' '+options+'}}';
},
focusOut: function() {
if (this.get('context').get('content').validate) {
this.get('context').get('content').validate(this.property);
}
- },
- propertyType: function(object, property) {
- try {
- return object.constructor.metaForProperty(property);
- } catch(e) {
- return null;
- }
}
});
@@ -0,0 +1,9 @@
+Ember.EasyForm.Label = Ember.View.extend({
+ tagName: 'label',
+ init: function() {
+ this.set('template', this.renderText());
+ },
+ renderText: function() {
+ return Ember.Handlebars.compile(this.text || this.property.underscore().split('_').join(' ').capitalize());
+ }
+});
@@ -5,7 +5,7 @@ var templateFor = function(template) {
var original_lookup = Ember.lookup, lookup;
Model = Ember.Object.extend();
-module('error helpers', {
+module('errorField helpers', {
setup: function() {
container = new Ember.Container();
container.optionsForType('template', { instantiate: false });
@@ -38,7 +38,7 @@ var append = function(view) {
test('error helper should bind to first error message in array', function() {
view = Ember.View.create({
- template: templateFor('{{error firstName}}'),
+ template: templateFor('{{errorField firstName}}'),
container: container,
controller: controller
});
Oops, something went wrong.

0 comments on commit 98517d5

Please sign in to comment.