Skip to content

Instantly share code, notes, and snippets.

@charlessolar
Last active August 29, 2015 14:08
Show Gist options
  • Save charlessolar/f51abe54570eafa679b6 to your computer and use it in GitHub Desktop.
Save charlessolar/f51abe54570eafa679b6 to your computer and use it in GitHub Desktop.
Knockoutjs Form Templating in View Model
// An easy way to create templated form inputs for large knockout projects
// Thanks to knockout 3.2 and components!
// Instead of defining control parameters on the binding or custom element like so:
<unrealistic-component
params='stringValue: "hello",
numericValue: 123,
boolValue: true,
objectValue: { a: 1, b: 2 },
dateValue: new Date(),
someModelProperty: myModelValue,
observableSubproperty: someObservable().subprop'>
</unrealistic-component>
// We are going to use this much cleaner syntax:
<text-input params="value: email"></text-input>
<password-input params="value: password"></password-input>
// Component parameters are specified via extended properties
email = ko.observable()
.extend({ required: true, email: true })
.extend({
component: {
name: 'text-input',
icon: 'fa-envelope',
hasIcon: true,
hint: 'If changed you must enter your password',
placeholder: 'Email Address',
label: 'Email'
}
});
password = ko.observable()
.extend({ required: true, minLength: 8 })
.extend({
component: {
name: 'password-input',
icon: 'fa-lock',
hasIcon: true,
placeholder: 'Password',
label: 'Password'
}
});
// Register the extender and our component models
ko.extenders['component'] = function(target, options) {
target.__component_params = options;
return target;
};
ko.components.register('text-input', { require: 'views/components/text-input' });
ko.components.register('password-input', { require: 'views/components/password-input' });
// I use AMD to load components, you can do whatever you want
// In the component view model:
define(['knockout', 'text!./text-input.html'], function(ko, htmlString) {
function viewModel(params) {
this.value = params.value;
this.params = params.__component_params;
}
return { viewModel: viewModel, template: htmlString };
});
// And for completeness, the html template
<div class="form-group" data-bind="validationElement: value">
<label class="control-label col-md-3" data-bind="text: params.label"></label>
<div class="col-md-4">
<!-- ko if: params.hasIcon -->
<div class="input-icon">
<i class="fa" data-bind="css: params.icon"></i>
<input type="text" class="form-control" data-bind="value: value, attr: { placeholder: params.placeholder }" />
</div>
<!-- /ko -->
<!-- ko if: !params.hasIcon -->
<input type="text" class="form-control" data-bind="value: value, attr: { placeholder: params.placeholder }" />
<!-- /ko -->
<span class="help-block" data-bind="validationMessage: value"></span>
<span class="help-block" data-bind="text: params.hint">
</span>
</div>
</div>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment