| <!doctype html> | |
| <html ng-app="app"> | |
| <head> | |
| <meta charset="utf-8"> | |
| <meta http-equiv="X-UA-Compatible" content="IE=edge"> | |
| <title>Form Builder</title> | |
| <meta name="description" content=""> | |
| <script type="text/javascript" src="http://code.jquery.com/jquery-1.8.3.js"></script> | |
| <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.23/jquery-ui.min.js"></script> | |
| <script type="text/javascript" src="http://netdna.bootstrapcdn.com/bootstrap/3.0.0-rc1/js/bootstrap.min.js"></script> | |
| <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.min.js"></script> | |
| <script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui/0.4.0/angular-ui.min.js"></script> | |
| <script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.12.0.js"></script> | |
| <link rel="stylesheet" href="css/ngDialog.css"> | |
| <link rel="stylesheet" href="css/ngDialog-theme-default.css"> | |
| <link rel="stylesheet" href="css/ngDialog-theme-plain.css"> | |
| <script src="js/xeditable.js"></script> | |
| <script src="js/ngDialog.js"></script> | |
| <link rel="stylesheet" type="text/css" href="http://netdna.bootstrapcdn.com/bootstrap/3.0.0-rc1/css/bootstrap.min.css"> | |
| <link href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet"> | |
| <link href="css/xeditable.css" rel="stylesheet"> | |
| <script> | |
| // App module // | |
| var app = angular.module("app", ["xeditable", "ui", "ngDialog"]); | |
| // Elements for this form // | |
| // @TODO AJAX load with existing elements | |
| app.factory('formElements', function($http) { | |
| return [ | |
| {id: 1, elementType: 'textfield', name: 'name'}, | |
| {id: 2, elementType: 'select', name: 'select'}, | |
| {id: 3, elementType: 'checkbox', name: 'checkbox'}, | |
| {id: 3, elementType: 'radio', name: 'radio'} | |
| ]; | |
| /* return $http.post('/saveFormelement');*/ // @TODO dynamically pass the formID in the url | |
| }); | |
| // Modal configuration // | |
| app.config(['ngDialogProvider', function (ngDialogProvider) { | |
| ngDialogProvider.setDefaults({ | |
| className: 'ngdialog-theme-default', | |
| plain: false, | |
| showClose: true, | |
| closeByDocument: true, | |
| closeByEscape: true, | |
| appendTo: false, | |
| preCloseCallback: function () { | |
| console.log('default pre-close callback'); | |
| } | |
| }); | |
| }]); | |
| // Angular Controllers // | |
| // Modal controller // | |
| app.controller('ModalCtrl', function ($scope, $rootScope, ngDialog, formElements, $http) { | |
| $scope.formElements = formElements; | |
| $rootScope.theme = 'ngdialog-theme-default'; | |
| $scope.elementTypeLookup = function(formElementName) { | |
| console.log('fired element type lookup'); | |
| // @TODO determine elementType from form name | |
| // @TODO AJAX query server for lookup table | |
| // RETURN elementType | |
| } | |
| $scope.openConfirm = function () { | |
| ngDialog.openConfirm({ | |
| template: 'modalDialogId', | |
| className: 'ngdialog-theme-default' | |
| }).then(function (value) { | |
| // AJAX // | |
| // $http.post('/saveFormelement', value); | |
| $scope.inserted = { | |
| // @TODO find largest form index then add 1 to it | |
| id: $scope.formElements.length+1, | |
| name: value, | |
| elementType: value // $scope.elementTypeLookup(value) | |
| }; | |
| $scope.formElements.push($scope.inserted); | |
| console.log('Modal promise resolved. Value: ', value); | |
| }, function (reason) { | |
| console.log('Modal promise rejected. Reason: ', reason); | |
| }); | |
| }; | |
| }); | |
| // Inline row edit controller // | |
| app.controller('EditableRowCtrl', function($scope, $filter, $http, formElements) { | |
| $scope.formElements = formElements; | |
| // @TODO AJAX request to save elements | |
| $scope.saveAllFormElements = function() { | |
| //return $http.post('/saveFormelement', data); | |
| } | |
| $scope.saveFormelement = function(data, id) { | |
| //$scope.formElement not updated yet | |
| angular.extend(data, {id: id}); | |
| console.log(formElements); | |
| //return $http.post('/saveFormelement', data); | |
| }; | |
| // remove formElement | |
| $scope.removeFormelement = function(index) { | |
| $scope.formElements.splice(index, 1); | |
| }; | |
| // add formElement // add element | |
| $scope.addElement = function() { | |
| $scope.inserted = { | |
| id: $scope.formElements.length+1, | |
| name: '', | |
| status: null, | |
| //group: null | |
| }; | |
| $scope.formElements.push($scope.inserted); | |
| // @TODO write function to add new element to bottom of page | |
| }; | |
| }); | |
| // Directive // | |
| /* | |
| 'use strict'; | |
| app.directive('fieldDirective', function ($http, $compile) { | |
| var getTemplateUrl = function(field) { | |
| var type = field.field_type; | |
| var templateUrl = ''; | |
| switch(type) { | |
| case 'textfield': | |
| templateUrl = './views/directive-templates/field/textfield.html'; | |
| break; | |
| case 'email': | |
| templateUrl = './views/directive-templates/field/email.html'; | |
| break; | |
| case 'textarea': | |
| templateUrl = './views/directive-templates/field/textarea.html'; | |
| break; | |
| case 'checkbox': | |
| templateUrl = './views/directive-templates/field/checkbox.html'; | |
| break; | |
| case 'date': | |
| templateUrl = './views/directive-templates/field/date.html'; | |
| break; | |
| case 'dropdown': | |
| templateUrl = './views/directive-templates/field/dropdown.html'; | |
| break; | |
| case 'hidden': | |
| templateUrl = './views/directive-templates/field/hidden.html'; | |
| break; | |
| case 'password': | |
| templateUrl = './views/directive-templates/field/password.html'; | |
| break; | |
| case 'radio': | |
| templateUrl = './views/directive-templates/field/radio.html'; | |
| break; | |
| } | |
| return templateUrl; | |
| } | |
| var linker = function(scope, element) { | |
| // GET template content from path | |
| var templateUrl = getTemplateUrl(scope.field); | |
| $http.get(templateUrl).success(function(data) { | |
| element.html(data); | |
| $compile(element.contents())(scope); | |
| }); | |
| } | |
| return { | |
| template: '<div>{{field}}</div>', | |
| restrict: 'E', | |
| scope: { | |
| field:'=' | |
| }, | |
| link: linker | |
| }; | |
| }); | |
| */ | |
| app.directive("formbuilder", function($http, $compile) { | |
| var getTemplateUrl = function(elementType) { | |
| //var type = field.elementType; | |
| var templateUrl = ''; | |
| switch(elementType) { | |
| case 'textfield': | |
| templateUrl = './views/directive-templates/field/textfield.html'; | |
| break; | |
| case 'email': | |
| templateUrl = './views/directive-templates/field/email.html'; | |
| break; | |
| case 'textarea': | |
| templateUrl = './views/directive-templates/field/textarea.html'; | |
| break; | |
| case 'checkbox': | |
| templateUrl = './views/directive-templates/field/checkbox.html'; | |
| break; | |
| case 'date': | |
| templateUrl = './views/directive-templates/field/date.html'; | |
| break; | |
| case 'dropdown': | |
| templateUrl = './views/directive-templates/field/dropdown.html'; | |
| break; | |
| case 'hidden': | |
| templateUrl = './views/directive-templates/field/hidden.html'; | |
| break; | |
| case 'password': | |
| templateUrl = './views/directive-templates/field/password.html'; | |
| break; | |
| case 'radio': | |
| templateUrl = './views/directive-templates/field/radio.html'; | |
| break; | |
| } | |
| return templateUrl; | |
| } | |
| var linker = function(scope, element) { | |
| // GET template content from path | |
| console.log(scope.elementType); | |
| var templateUrl = getTemplateUrl(scope.elementType); | |
| $http.get(templateUrl).success(function(data) { | |
| //element.html(data); | |
| //var node = $compile(element.contents())(scope); | |
| // element.append(node); | |
| }); | |
| } | |
| return { | |
| // template: '<div>{{formElement}}</div>', | |
| restrict: "E", | |
| scope: { | |
| elementType: "=" | |
| }, | |
| link: linker | |
| } | |
| }); | |
| </script> | |
| <!-- Modal template --> | |
| <script type="text/ng-template" id="modalDialogId"> | |
| // @TODO Generate dynamically from elements table | |
| <div class="ngdialog-message"> | |
| <h3>Select form element</h3> | |
| <button type="button" ng-click="confirm('name')">Name</a> | |
| <button type="button" ng-click="confirm('radio')">Radio</a> | |
| <button type="button" ng-click="confirm('checkbox')">Checkbox</a> | |
| <button type="button" ng-click="confirm('select')">Select</a> | |
| <button type="button" ng-click="confirm('textarea')">Textarea</a> | |
| </div> | |
| </script> | |
| <script type="text/ng-template" id="withInlineController"> | |
| <div class="ngdialog-message"> | |
| <h3>Select form element</h3> | |
| <button type="button" onClick="selectElement('name')">Name</a> | |
| <button type="button" ng-click="addElement()">Radio</a> | |
| <button type="button" ng-click="pushNewElement()">Checkbox</a> | |
| <button type="button" ng-click="selectElement(select)">Select</a> | |
| <button type="button" ng-click="selectElement(textarea)">Textarea</a> | |
| </div> | |
| <div class="ngdialog-buttons"> | |
| <button type="button" class="ngdialog-button ngdialog-button-primary" ng-click="closeThisDialog()">Close</button> | |
| </div> | |
| </script> | |
| </head> | |
| <body> | |
| <h1>Form builder</h1> | |
| <div ng-controller="EditableRowCtrl"> | |
| <table class="table table-bordered table-hover table-condensed"> | |
| <thead> | |
| <tr style="font-weight: bold"> | |
| <th style="width:35%">Form element</th> | |
| <!--td style="width:20%">Status</td--> | |
| <!--td style="width:20%">Group</td--> | |
| <th style="width:25%">Edit</th> | |
| </tr> | |
| </thead> | |
| <tbody ui:sortable="" ng:model="formElements"> | |
| <tr ng-repeat="formElement in formElements" style="cursor: move;"> | |
| <td> | |
| <!-- editable formElementname (text with validation) --> | |
| <span editable-text="formElement.name" e-name="name" e-form="rowform" e-required> | |
| {{ formElement.name || 'empty' }} | |
| </span> | |
| <div class="elementDetails" ng-show="rowform.$visible" > | |
| <span editable-text="formElement.description" e-name="description" e-form="rowform"> | |
| {{formElement.description}} | |
| </span> | |
| <span ng-switch="formElement.elementType"> | |
| <div ng-switch-when="text"> | |
| <span editable-text="formElement.placeholder" e-name="placeholder" e-form="rowform"> | |
| {{formElement.placeholder}} | |
| </span> | |
| </div> | |
| <!-- @TODO place correct element tags --> | |
| <div ng-switch-when="select"> | |
| <span editable-textarea="formElement.elementOptions" value="" e-name="elementOptions" e-form="rowform"> | |
| Option 1 | |
| Option 2 | |
| Option 3 | |
| </span> | |
| </div> | |
| <div ng-switch-when="radio"> | |
| <span editable-textarea="formElement.elementOptions" value="" e-name="elementOptions" e-form="rowform"> | |
| Option 1 | |
| Option 2 | |
| Option 3 | |
| </span> | |
| </div> | |
| <div ng-switch-when="checkbox"> | |
| <span editable-textarea="formElement.elementOptions" value="" e-name="elementOptions" e-form="rowform"> | |
| Option 1 | |
| Option 2 | |
| Option 3 | |
| </span> | |
| </div> | |
| </span> | |
| <span editable-checkbox="formElement.requiredField" e-name="requiredField" e-form="rowform"> | |
| {{formElement.requiredField}} | |
| </span> | |
| </div> | |
| </td> | |
| <td style="white-space: nowrap"> | |
| <!-- form --> | |
| <form editable-form name="rowform" onbeforesave="saveFormelement($data, formElement.id)" ng-show="rowform.$visible" class="form-buttons form-inline" shown="inserted == formElement"> | |
| <button type="submit" ng-disabled="rowform.$waiting" class="btn btn-primary"> | |
| save | |
| </button> | |
| <button type="button" ng-disabled="rowform.$waiting" ng-click="rowform.$cancel()" class="btn btn-default"> | |
| cancel | |
| </button> | |
| </form> | |
| <div class="buttons" ng-show="!rowform.$visible"> | |
| <button ng-if="!formElement.expanded" class="btn btn-primary" ng-click="rowform.$show()">edit</button> | |
| <button class="btn btn-danger" ng-click="removeFormelement($index)">del</button> | |
| </div> | |
| </td> | |
| </tr> | |
| </tbody> | |
| </table> | |
| <div ng-controller="ModalCtrl"> | |
| <button class="btn btn-default" ng-click="openConfirm()">Add element</button> | |
| </div> | |
| <br /> | |
| <br /> | |
| <br /> | |
| <!-- ********************** Display Form ********************** --> | |
| {{formElements}} | |
| <br /> | |
| <br /> | |
| <br /> | |
| <formbuilder element-type="textfield"></formbuilder> | |
| <!-- ********************** Display Form ********************** --> | |
| </div> | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment