Angular: Form Builder
Made a simple form-builder demo for my work. Has sorting, almost every type of input, and works pretty well. Could use a few more options for help text and drag-n-drop sorting.
by gavinfoley
HTML
<script src="http://code.angularjs.org/angular-0.10.5.js" ng:autobind></script>
<div ng:controller="FormBuilderCtrl">
<div id="jv-formbuilder">
<h2>Form Builder</h2>
<form ng:submit="saveField()">
<div class="input">
<label for="newField-name">Field Name:</label>
<input type="text" id="newField-name" ng:model="newField.name" ng:required>
</div>
<div class="input">
<label for="newField-required">Required:</label>
<input type="checkbox" id="newField-required" ng:model="newField.required">
</div>
<div class="input">
<label for="newField-order">Order Weight:</label>
<input type="number" id="newField-order" ng:model="newField.order" value="0" ng:required placeholder="0">
</div>
<div class="input">
<label for="newField-type">Field Type:</label>
<select id="newField-type" ng:model="newField.type" ng:required>
<option value="text" selected>Text</option>
<option value="radio">Radio Buttons</option>
<option value="select">Drop Menu (Select)</option>
<option value="multiple">Multi-Select</option>
<option value="checkbox">Toggle (Checkbox)</option>
<option value="checkboxes">Checkboxes</option>
<option value="textarea">Paragraph(s)</option>
<option value="number">Number</option>
<option value="url">Url</option>
<option value="phone">Phone</option>
<option value="email">Email</option>
<option value="header">Heading</option>
</select>
</div>
<ng:switch on="typeSwitch(newField.type)">
<div ng:switch-default class="input">
<label for="newField-placeholder">Instructions:</label>
<input type="text" id="newField-placeholder" ng:model="newField.placeholder">
...
CSS
h2 {
font-size: 140%;
margin: 10px 0;
font-weight: bold;
}
.input {
margin: 10px;
}
.edit {
font-weight: bold;
color: green;
}
.delete {
font-weight: bold;
color: red;
}
label {
width: 50%;
text-align: right;
display: inline-block;
}
input, select {
}
.radio fieldset label, .checkboxes fieldset label {
display: block;
text-align: left;
}
.radio fieldset label input, .checkboxes fieldset label input {
margin-right: 5px;
}
h3 {
border-top: 2px solid #ccc;
margin-top: 20px;
padding-top: 5px;
}
.required label:after {
color: #e32;
content: '*';
display:inline;
}
.order {
color: #ccc;
}
fieldset {
border: 1px solid #eee;
margin: 10px;
padding: 0 10px;
}
fieldset legend {
margin: 10px;
}
fieldset label {
width: auto;
}
fieldset div {
margin: 10px 0;
}
strong {
font-weight: bold;
}
JavaScript
function FormBuilderCtrl(){
var scope = this;
scope.newField = {};
scope.fields = [{
type: 'text',
name: 'Name',
placeholder: 'John Doe',
order: 10
}];
scope.editing = false;
scope.tokenize = function(slug1, slug2) {
var result = slug1;
result = result.replace(/[^-a-zA-Z0-9,&\s]+/ig, '');
result = result.replace(/-/gi, "_");
result = result.replace(/\s/gi, "-");
if (slug2) {
result += '-' + scope.token(slug2);
}
return result;
};
scope.saveField = function() {
if (scope.newField.type == 'checkboxes') {
scope.newField.value = {};
}
if (scope.editing !== false) {
scope.fields[scope.editing] = scope.newField;
scope.editing = false;
} else {
scope.fields.push(scope.newField);
}
scope.newField = { order: 0 };
};
scope.editField = function(field) {
scope.editing = scope.fields.indexOf(field);
scope.newField = field;
};
scope.splice = function(field, fields) {
fields.splice(fields.indexOf(field), 1);
};
scope.addOption = function() {
if (scope.newField.options === undefined) {
scope.newField.options = [];
}
scope.newField.options.push({ order: 0 });
};
scope.typeSwitch = function(type) {
if (angular.Array.indexOf(['checkboxes','select','radio'], type) === -1)
return type;
return 'multiple';
}
}