From 6a0a8aa0a8860e7125fea25e4220525a829e6185 Mon Sep 17 00:00:00 2001 From: David Jensen Date: Thu, 26 Jun 2014 11:28:02 +0200 Subject: [PATCH 1/6] Basic tabs support via form definition Works just like a fieldset, so it has nothing to do with arrays. Needs documentation, test and some styling perhaps. Work in progress. --- dist/bootstrap-decorator.min.js | 2 +- dist/schema-form.min.js | 2 +- examples/bootstrap-example.html | 64 +++++++++++-------- .../bootstrap/bootstrap-decorator.js | 1 + src/directives/decorators/bootstrap/tabs.html | 20 ++++++ src/services/schema-form.js | 6 ++ 6 files changed, 68 insertions(+), 27 deletions(-) create mode 100644 src/directives/decorators/bootstrap/tabs.html diff --git a/dist/bootstrap-decorator.min.js b/dist/bootstrap-decorator.min.js index 9bdf2d41d..119bddaa3 100644 --- a/dist/bootstrap-decorator.min.js +++ b/dist/bootstrap-decorator.min.js @@ -1 +1 @@ -angular.module("schemaForm").run(["$templateCache",function(e){e.put("directives/decorators/bootstrap/actions-trcl.html",'
'),e.put("directives/decorators/bootstrap/actions.html",'
'),e.put("directives/decorators/bootstrap/checkbox.html",'
{{form.description}}
'),e.put("directives/decorators/bootstrap/checkboxes.html",'
{{form.description}}
'),e.put("directives/decorators/bootstrap/default.html",'
{{ (hasError() && errorMessage(schemaError())) || form.description}}
'),e.put("directives/decorators/bootstrap/fieldset-trcl.html",'
{{ form.title }}
'),e.put("directives/decorators/bootstrap/fieldset.html",'
{{ form.title }}
'),e.put("directives/decorators/bootstrap/radio-buttons.html",'
{{form.description}}
'),e.put("directives/decorators/bootstrap/radios.html",'
{{form.description}}
'),e.put("directives/decorators/bootstrap/readonly.html",'
{{form.description}}
'),e.put("directives/decorators/bootstrap/section.html",'
'),e.put("directives/decorators/bootstrap/select.html",'
{{ (hasError() && errorMessage(schemaError())) || form.description}}
'),e.put("directives/decorators/bootstrap/submit.html",'
'),e.put("directives/decorators/bootstrap/textarea.html",'
{{ (hasError() && errorMessage(schemaError())) || form.description}}
')}]),angular.module("schemaForm").config(["schemaFormDecoratorsProvider",function(e){var t="directives/decorators/bootstrap/";e.createDecorator("bootstrapDecorator",{textarea:t+"textarea.html",fieldset:t+"fieldset.html",section:t+"section.html",conditional:t+"section.html",actions:t+"actions.html",select:t+"select.html",checkbox:t+"checkbox.html",checkboxes:t+"checkboxes.html",number:t+"default.html",password:t+"default.html",submit:t+"submit.html",button:t+"submit.html",radios:t+"radios.html",radiobuttons:t+"radio-buttons.html","default":t+"default.html"},[function(e){return e.readonly&&e.key&&"fieldset"!==e.type?t+"readonly.html":void 0}]),e.createDirectives({textarea:t+"textarea.html",select:t+"select.html",checkbox:t+"checkbox.html",checkboxes:t+"checkboxes.html",number:t+"default.html",submit:t+"submit.html",button:t+"submit.html",text:t+"default.html",date:t+"default.html",password:t+"default.html",datepicker:t+"datepicker.html",input:t+"default.html",radios:t+"radios.html",radiobuttons:t+"radio-buttons.html"})}]).directive("sfFieldset",function(){return{transclude:!0,scope:!0,templateUrl:"directives/decorators/bootstrap/fieldset-trcl.html",link:function(e,t,s){e.title=e.$eval(s.title)}}}); \ No newline at end of file +angular.module("schemaForm").run(["$templateCache",function(e){e.put("directives/decorators/bootstrap/actions-trcl.html",'
'),e.put("directives/decorators/bootstrap/actions.html",'
'),e.put("directives/decorators/bootstrap/checkbox.html",'
{{form.description}}
'),e.put("directives/decorators/bootstrap/checkboxes.html",'
{{form.description}}
'),e.put("directives/decorators/bootstrap/default.html",'
{{ (hasError() && errorMessage(schemaError())) || form.description}}
'),e.put("directives/decorators/bootstrap/fieldset-trcl.html",'
{{ form.title }}
'),e.put("directives/decorators/bootstrap/fieldset.html",'
{{ form.title }}
'),e.put("directives/decorators/bootstrap/radio-buttons.html",'
{{form.description}}
'),e.put("directives/decorators/bootstrap/radios.html",'
{{form.description}}
'),e.put("directives/decorators/bootstrap/readonly.html",'
{{form.description}}
'),e.put("directives/decorators/bootstrap/section.html",'
'),e.put("directives/decorators/bootstrap/select.html",'
{{ (hasError() && errorMessage(schemaError())) || form.description}}
'),e.put("directives/decorators/bootstrap/submit.html",'
'),e.put("directives/decorators/bootstrap/tabs.html",'
'),e.put("directives/decorators/bootstrap/textarea.html",'
{{ (hasError() && errorMessage(schemaError())) || form.description}}
')}]),angular.module("schemaForm").config(["schemaFormDecoratorsProvider",function(e){var t="directives/decorators/bootstrap/";e.createDecorator("bootstrapDecorator",{textarea:t+"textarea.html",fieldset:t+"fieldset.html",tabs:t+"tabs.html",section:t+"section.html",conditional:t+"section.html",actions:t+"actions.html",select:t+"select.html",checkbox:t+"checkbox.html",checkboxes:t+"checkboxes.html",number:t+"default.html",password:t+"default.html",submit:t+"submit.html",button:t+"submit.html",radios:t+"radios.html",radiobuttons:t+"radio-buttons.html","default":t+"default.html"},[function(e){return e.readonly&&e.key&&"fieldset"!==e.type?t+"readonly.html":void 0}]),e.createDirectives({textarea:t+"textarea.html",select:t+"select.html",checkbox:t+"checkbox.html",checkboxes:t+"checkboxes.html",number:t+"default.html",submit:t+"submit.html",button:t+"submit.html",text:t+"default.html",date:t+"default.html",password:t+"default.html",datepicker:t+"datepicker.html",input:t+"default.html",radios:t+"radios.html",radiobuttons:t+"radio-buttons.html"})}]).directive("sfFieldset",function(){return{transclude:!0,scope:!0,templateUrl:"directives/decorators/bootstrap/fieldset-trcl.html",link:function(e,t,s){e.title=e.$eval(s.title)}}}); \ No newline at end of file diff --git a/dist/schema-form.min.js b/dist/schema-form.min.js index b3c3c34f4..a5b0a5fe6 100644 --- a/dist/schema-form.min.js +++ b/dist/schema-form.min.js @@ -1 +1 @@ -angular.module("schemaForm",[]),angular.module("schemaForm").provider("schemaFormDecorators",["$compileProvider",function(e){var r="",t={},n=function(e,n){"sfDecorator"===e&&(e=r);for(var a=t[e],i=a.rules,o=0;o',link:function(e,t,n){var a={items:"c",titleMap:"c",schema:"c"},i={type:r},o=!0;angular.forEach(n,function(r,t){if("$"!==t[0]&&0!==t.indexOf("ng")&&"sfField"!==t){var u=function(r){angular.isDefined(r)&&r!==i[t]&&(i[t]=r,o&&i.type&&(i.key||angular.isUndefined(n.key))&&(e.form=i,o=!1))};"model"===t?e.$watch(r,function(r){r&&e.model!==r&&(e.model=r)}):"c"===a[t]?e.$watchCollection(r,u):n.$observe(t,u)}})}}})};this.createDecorator=function(e,n,i){t[e]={mappings:n||{},rules:i||[]},t[r]||(r=e),a(e)},this.createDirective=i,this.createDirectives=function(e){angular.forEach(e,function(e,r){i(r,e)})},this.directive=function(e){return e=e||r,t[e]},this.addMapping=function(e,r,n){t[e]&&(t[e].mappings[r]=n)},this.$get=function(){return{directive:function(e){return t[e]},defaultDecorator:r}},a("sfDecorator")}]),angular.module("schemaForm").provider("schemaForm",[function(){var e=function(e,r,t){var n=l[r.type];if(n)for(var a,i=0;i0){f.schema=c,f.form=l;var m=r.merge(c,l,s),p=document.createDocumentFragment();i.schemaForm={form:m,schema:c},angular.forEach(m,function(e,r){var a=document.createElement(u.sfDecorator||n(t.defaultDecorator,"-"));a.setAttribute("form","schemaForm.form["+r+"]"),p.appendChild(a)}),o.children(":not(.schema-form-ignore)").remove(),o[0].appendChild(p),e(o.children())(i),a(c,function(e,r){angular.isDefined(e["default"])&&i.$eval("model."+r+" = model."+r+" || defaltValue",{defaltValue:e["default"]})})}})}}}]),angular.module("schemaForm").directive("schemaValidate",function(){return{restrict:"A",scope:!1,require:"ngModel",link:function(e,r,t,n){e.ngModel=n;var a=null,i=e.$eval(t.schemaValidate);n.$parsers.unshift(function(r){if(i||(i=e.$eval(t.schemaValidate)),!i)return r;if(angular.isUndefined(r))return void 0;var o=r;"integer"===i.type?o=parseInt(o,10):"number"===i.type?o=parseFloat(o,10):"boolean"===i.type&&"string"==typeof r&&("true"===r?o=!0:"false"===r&&(o=!1));var u=tv4.validateResult(o,i);return u.valid?(n.$setValidity("schema",!0),a=null,r):(n.$setValidity("schema",!1),void(a=u.error))}),e.hasSuccess=function(){return n.$valid&&(!n.$pristine||!n.$isEmpty(n.$modelValue))},e.hasError=function(){return n.$invalid&&!n.$pristine},e.schemaError=function(){return a}}}}); \ No newline at end of file +angular.module("schemaForm",[]),angular.module("schemaForm").provider("schemaFormDecorators",["$compileProvider",function(e){var r="",t={},n=function(e,n){"sfDecorator"===e&&(e=r);for(var a=t[e],i=a.rules,o=0;o',link:function(e,t,n){var a={items:"c",titleMap:"c",schema:"c"},i={type:r},o=!0;angular.forEach(n,function(r,t){if("$"!==t[0]&&0!==t.indexOf("ng")&&"sfField"!==t){var u=function(r){angular.isDefined(r)&&r!==i[t]&&(i[t]=r,o&&i.type&&(i.key||angular.isUndefined(n.key))&&(e.form=i,o=!1))};"model"===t?e.$watch(r,function(r){r&&e.model!==r&&(e.model=r)}):"c"===a[t]?e.$watchCollection(r,u):n.$observe(t,u)}})}}})};this.createDecorator=function(e,n,i){t[e]={mappings:n||{},rules:i||[]},t[r]||(r=e),a(e)},this.createDirective=i,this.createDirectives=function(e){angular.forEach(e,function(e,r){i(r,e)})},this.directive=function(e){return e=e||r,t[e]},this.addMapping=function(e,r,n){t[e]&&(t[e].mappings[r]=n)},this.$get=function(){return{directive:function(e){return t[e]},defaultDecorator:r}},a("sfDecorator")}]),angular.module("schemaForm").provider("schemaForm",[function(){var e=function(e,r,t){var n=l[r.type];if(n)for(var a,i=0;i0){f.schema=c,f.form=l;var m=r.merge(c,l,s),p=document.createDocumentFragment();i.schemaForm={form:m,schema:c},angular.forEach(m,function(e,r){var a=document.createElement(u.sfDecorator||n(t.defaultDecorator,"-"));a.setAttribute("form","schemaForm.form["+r+"]"),p.appendChild(a)}),o.children(":not(.schema-form-ignore)").remove(),o[0].appendChild(p),e(o.children())(i),a(c,function(e,r){angular.isDefined(e["default"])&&i.$eval("model."+r+" = model."+r+" || defaltValue",{defaltValue:e["default"]})})}})}}}]),angular.module("schemaForm").directive("schemaValidate",function(){return{restrict:"A",scope:!1,require:"ngModel",link:function(e,r,t,n){e.ngModel=n;var a=null,i=e.$eval(t.schemaValidate);n.$parsers.unshift(function(r){if(i||(i=e.$eval(t.schemaValidate)),!i)return r;if(angular.isUndefined(r))return void 0;var o=r;"integer"===i.type?o=parseInt(o,10):"number"===i.type?o=parseFloat(o,10):"boolean"===i.type&&"string"==typeof r&&("true"===r?o=!0:"false"===r&&(o=!1));var u=tv4.validateResult(o,i);return u.valid?(n.$setValidity("schema",!0),a=null,r):(n.$setValidity("schema",!1),void(a=u.error))}),e.hasSuccess=function(){return n.$valid&&(!n.$pristine||!n.$isEmpty(n.$modelValue))},e.hasError=function(){return n.$invalid&&!n.$pristine},e.schemaError=function(){return a}}}}); \ No newline at end of file diff --git a/examples/bootstrap-example.html b/examples/bootstrap-example.html index 85241393c..f8c789e47 100644 --- a/examples/bootstrap-example.html +++ b/examples/bootstrap-example.html @@ -143,32 +143,46 @@

Schema

$scope.form = [ { - key: "name", - placeholder: "Check the console", - onChange: "log(modelValue)", - feedback: "{'glyphicon': true, 'glyphicon-ok': hasSuccess(), 'glyphicon-star': !hasSuccess() }" - }, - { - key: "favorite", - feedback: false - }, - "attributes", - { - key: "shoesize", - feedback: false - }, - "things", - "soul", - { - type: "conditional", - condition: "person.soul", - items: [ - { key: "soulserial", placeholder: "ex. 666" } - ] + type: "tabs", + tabs: [ + { + name: "Simple stuff", + items: [ + { + key: "name", + placeholder: "Check the console", + onChange: "log(modelValue)", + feedback: "{'glyphicon': true, 'glyphicon-ok': hasSuccess(), 'glyphicon-star': !hasSuccess() }" + }, + { + key: "favorite", + feedback: false + } + ] + }, + { + name: "More stuff", + items: [ + "attributes", + { + key: "shoesize", + feedback: false + }, + "things", + "soul", + { + type: "conditional", + condition: "person.soul", + items: [ + { key: "soulserial", placeholder: "ex. 666" } + ] + }, + { key: "date", minDate: "2014-06-20" }, + { key: "radio", type: "radios" }, + { key: "radiobuttons", type: "radiobuttons" } + ] + }] }, - { key: "date", minDate: "2014-06-20" }, - { key: "radio", type: "radios" }, - { key: "radiobuttons", type: "radiobuttons" }, { type: 'actions', items: [ diff --git a/src/directives/decorators/bootstrap/bootstrap-decorator.js b/src/directives/decorators/bootstrap/bootstrap-decorator.js index 154216870..410d58a72 100644 --- a/src/directives/decorators/bootstrap/bootstrap-decorator.js +++ b/src/directives/decorators/bootstrap/bootstrap-decorator.js @@ -4,6 +4,7 @@ angular.module('schemaForm').config(['schemaFormDecoratorsProvider',function(dec decoratorsProvider.createDecorator('bootstrapDecorator',{ textarea: base+'textarea.html', fieldset: base+'fieldset.html', + tabs: base+'tabs.html', section: base+'section.html', conditional: base+'section.html', actions: base+'actions.html', diff --git a/src/directives/decorators/bootstrap/tabs.html b/src/directives/decorators/bootstrap/tabs.html new file mode 100644 index 000000000..16285d002 --- /dev/null +++ b/src/directives/decorators/bootstrap/tabs.html @@ -0,0 +1,20 @@ +
+ + + +
+
+ + +
+
+
diff --git a/src/services/schema-form.js b/src/services/schema-form.js index 28626e040..e457b67df 100644 --- a/src/services/schema-form.js +++ b/src/services/schema-form.js @@ -248,6 +248,12 @@ angular.module('schemaForm').provider('schemaForm',[function(){ obj.items = service.merge(schema,obj.items,ignore); } + //if its has tabs, merge them also! + if (obj.tabs) { + angular.forEach(obj.tabs,function(tab){ + tab.items = service.merge(schema,tab.items,ignore); + }); + } //extend with std form from schema. if (obj.key && lookup[obj.key]) { From 63e939cd25be2276d18fa246d48a77e4ef792fab Mon Sep 17 00:00:00 2001 From: David Jensen Date: Thu, 26 Jun 2014 12:04:42 +0200 Subject: [PATCH 2/6] Support for help form type As in jsonform. Lacks test and documentation. Needs ngSanitize included to work. --- bower.json | 3 ++- dist/bootstrap-decorator.min.js | 2 +- dist/schema-form.min.js | 2 +- examples/bootstrap-example.html | 4 ++++ .../decorators/bootstrap/bootstrap-decorator.js | 1 + src/directives/decorators/bootstrap/help.html | 1 + src/module.js | 10 +++++++++- 7 files changed, 19 insertions(+), 4 deletions(-) create mode 100644 src/directives/decorators/bootstrap/help.html diff --git a/bower.json b/bower.json index 69a5907e2..509cfa7b1 100644 --- a/bower.json +++ b/bower.json @@ -24,7 +24,8 @@ "dependencies": { "angular": "~1.2.18", "tv4": "~1.0.15", - "pickadate": "~3.5.2" + "pickadate": "~3.5.2", + "angular-sanitize": "~1.2.18" }, "devDependencies": { "angular-ui-ace": "bower" diff --git a/dist/bootstrap-decorator.min.js b/dist/bootstrap-decorator.min.js index 119bddaa3..9dddcc8ec 100644 --- a/dist/bootstrap-decorator.min.js +++ b/dist/bootstrap-decorator.min.js @@ -1 +1 @@ -angular.module("schemaForm").run(["$templateCache",function(e){e.put("directives/decorators/bootstrap/actions-trcl.html",'
'),e.put("directives/decorators/bootstrap/actions.html",'
'),e.put("directives/decorators/bootstrap/checkbox.html",'
{{form.description}}
'),e.put("directives/decorators/bootstrap/checkboxes.html",'
{{form.description}}
'),e.put("directives/decorators/bootstrap/default.html",'
{{ (hasError() && errorMessage(schemaError())) || form.description}}
'),e.put("directives/decorators/bootstrap/fieldset-trcl.html",'
{{ form.title }}
'),e.put("directives/decorators/bootstrap/fieldset.html",'
{{ form.title }}
'),e.put("directives/decorators/bootstrap/radio-buttons.html",'
{{form.description}}
'),e.put("directives/decorators/bootstrap/radios.html",'
{{form.description}}
'),e.put("directives/decorators/bootstrap/readonly.html",'
{{form.description}}
'),e.put("directives/decorators/bootstrap/section.html",'
'),e.put("directives/decorators/bootstrap/select.html",'
{{ (hasError() && errorMessage(schemaError())) || form.description}}
'),e.put("directives/decorators/bootstrap/submit.html",'
'),e.put("directives/decorators/bootstrap/tabs.html",''),e.put("directives/decorators/bootstrap/textarea.html",'
{{ (hasError() && errorMessage(schemaError())) || form.description}}
')}]),angular.module("schemaForm").config(["schemaFormDecoratorsProvider",function(e){var t="directives/decorators/bootstrap/";e.createDecorator("bootstrapDecorator",{textarea:t+"textarea.html",fieldset:t+"fieldset.html",tabs:t+"tabs.html",section:t+"section.html",conditional:t+"section.html",actions:t+"actions.html",select:t+"select.html",checkbox:t+"checkbox.html",checkboxes:t+"checkboxes.html",number:t+"default.html",password:t+"default.html",submit:t+"submit.html",button:t+"submit.html",radios:t+"radios.html",radiobuttons:t+"radio-buttons.html","default":t+"default.html"},[function(e){return e.readonly&&e.key&&"fieldset"!==e.type?t+"readonly.html":void 0}]),e.createDirectives({textarea:t+"textarea.html",select:t+"select.html",checkbox:t+"checkbox.html",checkboxes:t+"checkboxes.html",number:t+"default.html",submit:t+"submit.html",button:t+"submit.html",text:t+"default.html",date:t+"default.html",password:t+"default.html",datepicker:t+"datepicker.html",input:t+"default.html",radios:t+"radios.html",radiobuttons:t+"radio-buttons.html"})}]).directive("sfFieldset",function(){return{transclude:!0,scope:!0,templateUrl:"directives/decorators/bootstrap/fieldset-trcl.html",link:function(e,t,s){e.title=e.$eval(s.title)}}}); \ No newline at end of file +angular.module("schemaForm").run(["$templateCache",function(e){e.put("directives/decorators/bootstrap/actions-trcl.html",'
'),e.put("directives/decorators/bootstrap/actions.html",'
'),e.put("directives/decorators/bootstrap/checkbox.html",'
{{form.description}}
'),e.put("directives/decorators/bootstrap/checkboxes.html",'
{{form.description}}
'),e.put("directives/decorators/bootstrap/default.html",'
{{ (hasError() && errorMessage(schemaError())) || form.description}}
'),e.put("directives/decorators/bootstrap/fieldset-trcl.html",'
{{ form.title }}
'),e.put("directives/decorators/bootstrap/fieldset.html",'
{{ form.title }}
'),e.put("directives/decorators/bootstrap/help.html",'
'),e.put("directives/decorators/bootstrap/radio-buttons.html",'
{{form.description}}
'),e.put("directives/decorators/bootstrap/radios.html",'
{{form.description}}
'),e.put("directives/decorators/bootstrap/readonly.html",'
{{form.description}}
'),e.put("directives/decorators/bootstrap/section.html",'
'),e.put("directives/decorators/bootstrap/select.html",'
{{ (hasError() && errorMessage(schemaError())) || form.description}}
'),e.put("directives/decorators/bootstrap/submit.html",'
'),e.put("directives/decorators/bootstrap/tabs.html",''),e.put("directives/decorators/bootstrap/textarea.html",'
{{ (hasError() && errorMessage(schemaError())) || form.description}}
')}]),angular.module("schemaForm").config(["schemaFormDecoratorsProvider",function(e){var t="directives/decorators/bootstrap/";e.createDecorator("bootstrapDecorator",{textarea:t+"textarea.html",fieldset:t+"fieldset.html",tabs:t+"tabs.html",section:t+"section.html",conditional:t+"section.html",actions:t+"actions.html",select:t+"select.html",checkbox:t+"checkbox.html",checkboxes:t+"checkboxes.html",number:t+"default.html",password:t+"default.html",submit:t+"submit.html",button:t+"submit.html",radios:t+"radios.html",radiobuttons:t+"radio-buttons.html",help:t+"help.html","default":t+"default.html"},[function(e){return e.readonly&&e.key&&"fieldset"!==e.type?t+"readonly.html":void 0}]),e.createDirectives({textarea:t+"textarea.html",select:t+"select.html",checkbox:t+"checkbox.html",checkboxes:t+"checkboxes.html",number:t+"default.html",submit:t+"submit.html",button:t+"submit.html",text:t+"default.html",date:t+"default.html",password:t+"default.html",datepicker:t+"datepicker.html",input:t+"default.html",radios:t+"radios.html",radiobuttons:t+"radio-buttons.html"})}]).directive("sfFieldset",function(){return{transclude:!0,scope:!0,templateUrl:"directives/decorators/bootstrap/fieldset-trcl.html",link:function(e,t,s){e.title=e.$eval(s.title)}}}); \ No newline at end of file diff --git a/dist/schema-form.min.js b/dist/schema-form.min.js index a5b0a5fe6..7f38a0c61 100644 --- a/dist/schema-form.min.js +++ b/dist/schema-form.min.js @@ -1 +1 @@ -angular.module("schemaForm",[]),angular.module("schemaForm").provider("schemaFormDecorators",["$compileProvider",function(e){var r="",t={},n=function(e,n){"sfDecorator"===e&&(e=r);for(var a=t[e],i=a.rules,o=0;o',link:function(e,t,n){var a={items:"c",titleMap:"c",schema:"c"},i={type:r},o=!0;angular.forEach(n,function(r,t){if("$"!==t[0]&&0!==t.indexOf("ng")&&"sfField"!==t){var u=function(r){angular.isDefined(r)&&r!==i[t]&&(i[t]=r,o&&i.type&&(i.key||angular.isUndefined(n.key))&&(e.form=i,o=!1))};"model"===t?e.$watch(r,function(r){r&&e.model!==r&&(e.model=r)}):"c"===a[t]?e.$watchCollection(r,u):n.$observe(t,u)}})}}})};this.createDecorator=function(e,n,i){t[e]={mappings:n||{},rules:i||[]},t[r]||(r=e),a(e)},this.createDirective=i,this.createDirectives=function(e){angular.forEach(e,function(e,r){i(r,e)})},this.directive=function(e){return e=e||r,t[e]},this.addMapping=function(e,r,n){t[e]&&(t[e].mappings[r]=n)},this.$get=function(){return{directive:function(e){return t[e]},defaultDecorator:r}},a("sfDecorator")}]),angular.module("schemaForm").provider("schemaForm",[function(){var e=function(e,r,t){var n=l[r.type];if(n)for(var a,i=0;i0){f.schema=c,f.form=l;var m=r.merge(c,l,s),p=document.createDocumentFragment();i.schemaForm={form:m,schema:c},angular.forEach(m,function(e,r){var a=document.createElement(u.sfDecorator||n(t.defaultDecorator,"-"));a.setAttribute("form","schemaForm.form["+r+"]"),p.appendChild(a)}),o.children(":not(.schema-form-ignore)").remove(),o[0].appendChild(p),e(o.children())(i),a(c,function(e,r){angular.isDefined(e["default"])&&i.$eval("model."+r+" = model."+r+" || defaltValue",{defaltValue:e["default"]})})}})}}}]),angular.module("schemaForm").directive("schemaValidate",function(){return{restrict:"A",scope:!1,require:"ngModel",link:function(e,r,t,n){e.ngModel=n;var a=null,i=e.$eval(t.schemaValidate);n.$parsers.unshift(function(r){if(i||(i=e.$eval(t.schemaValidate)),!i)return r;if(angular.isUndefined(r))return void 0;var o=r;"integer"===i.type?o=parseInt(o,10):"number"===i.type?o=parseFloat(o,10):"boolean"===i.type&&"string"==typeof r&&("true"===r?o=!0:"false"===r&&(o=!1));var u=tv4.validateResult(o,i);return u.valid?(n.$setValidity("schema",!0),a=null,r):(n.$setValidity("schema",!1),void(a=u.error))}),e.hasSuccess=function(){return n.$valid&&(!n.$pristine||!n.$isEmpty(n.$modelValue))},e.hasError=function(){return n.$invalid&&!n.$pristine},e.schemaError=function(){return a}}}}); \ No newline at end of file +try{angular.module("ngSanitize"),angular.module("schemaForm",["ngSanitize"])}catch(e){angular.module("schemaForm",[])}angular.module("schemaForm").provider("schemaFormDecorators",["$compileProvider",function(e){var r="",t={},n=function(e,n){"sfDecorator"===e&&(e=r);for(var a=t[e],i=a.rules,o=0;o',link:function(e,t,n){var a={items:"c",titleMap:"c",schema:"c"},i={type:r},o=!0;angular.forEach(n,function(r,t){if("$"!==t[0]&&0!==t.indexOf("ng")&&"sfField"!==t){var u=function(r){angular.isDefined(r)&&r!==i[t]&&(i[t]=r,o&&i.type&&(i.key||angular.isUndefined(n.key))&&(e.form=i,o=!1))};"model"===t?e.$watch(r,function(r){r&&e.model!==r&&(e.model=r)}):"c"===a[t]?e.$watchCollection(r,u):n.$observe(t,u)}})}}})};this.createDecorator=function(e,n,i){t[e]={mappings:n||{},rules:i||[]},t[r]||(r=e),a(e)},this.createDirective=i,this.createDirectives=function(e){angular.forEach(e,function(e,r){i(r,e)})},this.directive=function(e){return e=e||r,t[e]},this.addMapping=function(e,r,n){t[e]&&(t[e].mappings[r]=n)},this.$get=function(){return{directive:function(e){return t[e]},defaultDecorator:r}},a("sfDecorator")}]),angular.module("schemaForm").provider("schemaForm",[function(){var e=function(e,r,t){var n=l[r.type];if(n)for(var a,i=0;i0){f.schema=c,f.form=l;var m=r.merge(c,l,s),p=document.createDocumentFragment();i.schemaForm={form:m,schema:c},angular.forEach(m,function(e,r){var a=document.createElement(u.sfDecorator||n(t.defaultDecorator,"-"));a.setAttribute("form","schemaForm.form["+r+"]"),p.appendChild(a)}),o.children(":not(.schema-form-ignore)").remove(),o[0].appendChild(p),e(o.children())(i),a(c,function(e,r){angular.isDefined(e["default"])&&i.$eval("model."+r+" = model."+r+" || defaltValue",{defaltValue:e["default"]})})}})}}}]),angular.module("schemaForm").directive("schemaValidate",function(){return{restrict:"A",scope:!1,require:"ngModel",link:function(e,r,t,n){e.ngModel=n;var a=null,i=e.$eval(t.schemaValidate);n.$parsers.unshift(function(r){if(i||(i=e.$eval(t.schemaValidate)),!i)return r;if(angular.isUndefined(r))return void 0;var o=r;"integer"===i.type?o=parseInt(o,10):"number"===i.type?o=parseFloat(o,10):"boolean"===i.type&&"string"==typeof r&&("true"===r?o=!0:"false"===r&&(o=!1));var u=tv4.validateResult(o,i);return u.valid?(n.$setValidity("schema",!0),a=null,r):(n.$setValidity("schema",!1),void(a=u.error))}),e.hasSuccess=function(){return n.$valid&&(!n.$pristine||!n.$isEmpty(n.$modelValue))},e.hasError=function(){return n.$invalid&&!n.$pristine},e.schemaError=function(){return a}}}}); \ No newline at end of file diff --git a/examples/bootstrap-example.html b/examples/bootstrap-example.html index f8c789e47..c467bcaa4 100644 --- a/examples/bootstrap-example.html +++ b/examples/bootstrap-example.html @@ -142,6 +142,10 @@

Schema

}; $scope.form = [ + { + type: "help", + helpvalue: "

Yo ninja!

" + }, { type: "tabs", tabs: [ diff --git a/src/directives/decorators/bootstrap/bootstrap-decorator.js b/src/directives/decorators/bootstrap/bootstrap-decorator.js index 410d58a72..5233d94f7 100644 --- a/src/directives/decorators/bootstrap/bootstrap-decorator.js +++ b/src/directives/decorators/bootstrap/bootstrap-decorator.js @@ -17,6 +17,7 @@ angular.module('schemaForm').config(['schemaFormDecoratorsProvider',function(dec button: base+'submit.html', radios: base+'radios.html', radiobuttons: base+'radio-buttons.html', + help: base+'help.html', 'default': base+'default.html' },[ function(form){ diff --git a/src/directives/decorators/bootstrap/help.html b/src/directives/decorators/bootstrap/help.html new file mode 100644 index 000000000..863a260ef --- /dev/null +++ b/src/directives/decorators/bootstrap/help.html @@ -0,0 +1 @@ +
diff --git a/src/module.js b/src/module.js index 3feb69ef3..8dc5ad7db 100644 --- a/src/module.js +++ b/src/module.js @@ -1 +1,9 @@ -angular.module('schemaForm',[]); \ No newline at end of file +//Its up to the user to use form type help or not. +try { + //This throws an expection if module does not exist. + angular.module('ngSanitize'); + + angular.module('schemaForm',['ngSanitize']); +} catch (e) { + angular.module('schemaForm',[]); +} From 3de353e73c0eeb5cc3018a17780fbb7c51b3af88 Mon Sep 17 00:00:00 2001 From: David Jensen Date: Thu, 26 Jun 2014 14:17:52 +0200 Subject: [PATCH 3/6] Documentation and tests for help type --- docs/index.md | 38 +++++++++++++++++++++++++++++++++++++ test/schema-form-test.js | 41 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+) diff --git a/docs/index.md b/docs/index.md index 91f5f1123..a2ea76e9f 100644 --- a/docs/index.md +++ b/docs/index.md @@ -16,6 +16,7 @@ Documentation 1. [actions](#actions) 1. [button](#button) 1. [radios and radiobuttons](#radios-and-radiobuttons) + 1. [help](#help) 1. [Post process function](#post-process-function) Form types @@ -38,6 +39,7 @@ Schema Form currently supports the following form field types out of the box: | button | a button | | radios | radio buttons | | radiobuttons | radio buttons with bootstrap buttons | +| help | insert arbitrary html | More field types can be added, for instance a "datepicker" type can be added by including the [datepicker addon](datepicker.md) @@ -364,6 +366,42 @@ function FormCtrl($scope) { } ``` +### help +Help fields is not really a field, but instead let's you inser arbitrary HTML +into a form, suitable for help texts with links etc. + +It uses ```ng-bind-html``` so you need to include the +[ngSanitize](https://docs.angularjs.org/api/ngSanitize) module for it to work, +or expicitly turning of strict contextual escaping with +```$sceProvider.enabled(false)``` (not recomended). It's enough to include +```angular-sanitize.min.js``` before ```angular-schema.min.js``` and Schema Form +will pick up that it's there and include it as a module dependency. + +The get a help field you need to specify the type ```help``` and have a html +snippet as a string in the option ```helpvalue``` + +Ex. +```javascript +function FormCtrl($scope) { + $scope.schema = { + type: "object", + properties: { + name: { + title: "Name", + type: "string" + } + } + }; + + $scope.form = [ + { + type: "help", + helpvalue: "

Yo Ninja!

" + }, + "name" + ]; +} +``` Post process function --------------------- diff --git a/test/schema-form-test.js b/test/schema-form-test.js index dc5298f99..2695f766a 100644 --- a/test/schema-form-test.js +++ b/test/schema-form-test.js @@ -851,6 +851,47 @@ describe('Schema form',function(){ }); }); + it('should render custom html when type "help" is specified',function(){ + + //We don't need no sanitation. We don't need no though control. + module(function($sceProvider){ + $sceProvider.enabled(false); + }); + + inject(function($compile,$rootScope){ + var scope = $rootScope.$new(); + scope.person = { partee: '2014-01-01'}; + + scope.schema = { + type: "object", + properties: { + name: { + type: "string", + } + } + }; + + + scope.form = [ + { + type: "help", + helpvalue: "

Yo Ninja!

" + }, + "name" + ]; + + var tmpl = angular.element('
'); + + $compile(tmpl)(scope); + $rootScope.$apply(); + + tmpl.children().length.should.eq(2); + tmpl.children().eq(0).is('div').should.be.true; + tmpl.children().eq(0).children().length.should.eq(1); + tmpl.children().eq(0).children().html().should.be.eq("Yo Ninja!"); + + }); + }); }); From f16c8d0431d25b6dea2d6e010223bdc1ecff6fb8 Mon Sep 17 00:00:00 2001 From: David Jensen Date: Thu, 26 Jun 2014 16:04:53 +0200 Subject: [PATCH 4/6] Tests and example for tabs --- dist/bootstrap-decorator.min.js | 2 +- examples/bootstrap-example.html | 83 ++++++++++--------- src/directives/decorators/bootstrap/tabs.html | 5 +- test/schema-form-test.js | 70 +++++++++++++++- 4 files changed, 117 insertions(+), 43 deletions(-) diff --git a/dist/bootstrap-decorator.min.js b/dist/bootstrap-decorator.min.js index 9dddcc8ec..6fdb10abf 100644 --- a/dist/bootstrap-decorator.min.js +++ b/dist/bootstrap-decorator.min.js @@ -1 +1 @@ -angular.module("schemaForm").run(["$templateCache",function(e){e.put("directives/decorators/bootstrap/actions-trcl.html",'
'),e.put("directives/decorators/bootstrap/actions.html",'
'),e.put("directives/decorators/bootstrap/checkbox.html",'
{{form.description}}
'),e.put("directives/decorators/bootstrap/checkboxes.html",'
{{form.description}}
'),e.put("directives/decorators/bootstrap/default.html",'
{{ (hasError() && errorMessage(schemaError())) || form.description}}
'),e.put("directives/decorators/bootstrap/fieldset-trcl.html",'
{{ form.title }}
'),e.put("directives/decorators/bootstrap/fieldset.html",'
{{ form.title }}
'),e.put("directives/decorators/bootstrap/help.html",'
'),e.put("directives/decorators/bootstrap/radio-buttons.html",'
{{form.description}}
'),e.put("directives/decorators/bootstrap/radios.html",'
{{form.description}}
'),e.put("directives/decorators/bootstrap/readonly.html",'
{{form.description}}
'),e.put("directives/decorators/bootstrap/section.html",'
'),e.put("directives/decorators/bootstrap/select.html",'
{{ (hasError() && errorMessage(schemaError())) || form.description}}
'),e.put("directives/decorators/bootstrap/submit.html",'
'),e.put("directives/decorators/bootstrap/tabs.html",''),e.put("directives/decorators/bootstrap/textarea.html",'
{{ (hasError() && errorMessage(schemaError())) || form.description}}
')}]),angular.module("schemaForm").config(["schemaFormDecoratorsProvider",function(e){var t="directives/decorators/bootstrap/";e.createDecorator("bootstrapDecorator",{textarea:t+"textarea.html",fieldset:t+"fieldset.html",tabs:t+"tabs.html",section:t+"section.html",conditional:t+"section.html",actions:t+"actions.html",select:t+"select.html",checkbox:t+"checkbox.html",checkboxes:t+"checkboxes.html",number:t+"default.html",password:t+"default.html",submit:t+"submit.html",button:t+"submit.html",radios:t+"radios.html",radiobuttons:t+"radio-buttons.html",help:t+"help.html","default":t+"default.html"},[function(e){return e.readonly&&e.key&&"fieldset"!==e.type?t+"readonly.html":void 0}]),e.createDirectives({textarea:t+"textarea.html",select:t+"select.html",checkbox:t+"checkbox.html",checkboxes:t+"checkboxes.html",number:t+"default.html",submit:t+"submit.html",button:t+"submit.html",text:t+"default.html",date:t+"default.html",password:t+"default.html",datepicker:t+"datepicker.html",input:t+"default.html",radios:t+"radios.html",radiobuttons:t+"radio-buttons.html"})}]).directive("sfFieldset",function(){return{transclude:!0,scope:!0,templateUrl:"directives/decorators/bootstrap/fieldset-trcl.html",link:function(e,t,s){e.title=e.$eval(s.title)}}}); \ No newline at end of file +angular.module("schemaForm").run(["$templateCache",function(e){e.put("directives/decorators/bootstrap/actions-trcl.html",'
'),e.put("directives/decorators/bootstrap/actions.html",'
'),e.put("directives/decorators/bootstrap/checkbox.html",'
{{form.description}}
'),e.put("directives/decorators/bootstrap/checkboxes.html",'
{{form.description}}
'),e.put("directives/decorators/bootstrap/default.html",'
{{ (hasError() && errorMessage(schemaError())) || form.description}}
'),e.put("directives/decorators/bootstrap/fieldset-trcl.html",'
{{ form.title }}
'),e.put("directives/decorators/bootstrap/fieldset.html",'
{{ form.title }}
'),e.put("directives/decorators/bootstrap/help.html",'
'),e.put("directives/decorators/bootstrap/radio-buttons.html",'
{{form.description}}
'),e.put("directives/decorators/bootstrap/radios.html",'
{{form.description}}
'),e.put("directives/decorators/bootstrap/readonly.html",'
{{form.description}}
'),e.put("directives/decorators/bootstrap/section.html",'
'),e.put("directives/decorators/bootstrap/select.html",'
{{ (hasError() && errorMessage(schemaError())) || form.description}}
'),e.put("directives/decorators/bootstrap/submit.html",'
'),e.put("directives/decorators/bootstrap/tabs.html",''),e.put("directives/decorators/bootstrap/textarea.html",'
{{ (hasError() && errorMessage(schemaError())) || form.description}}
')}]),angular.module("schemaForm").config(["schemaFormDecoratorsProvider",function(e){var t="directives/decorators/bootstrap/";e.createDecorator("bootstrapDecorator",{textarea:t+"textarea.html",fieldset:t+"fieldset.html",tabs:t+"tabs.html",section:t+"section.html",conditional:t+"section.html",actions:t+"actions.html",select:t+"select.html",checkbox:t+"checkbox.html",checkboxes:t+"checkboxes.html",number:t+"default.html",password:t+"default.html",submit:t+"submit.html",button:t+"submit.html",radios:t+"radios.html",radiobuttons:t+"radio-buttons.html",help:t+"help.html","default":t+"default.html"},[function(e){return e.readonly&&e.key&&"fieldset"!==e.type?t+"readonly.html":void 0}]),e.createDirectives({textarea:t+"textarea.html",select:t+"select.html",checkbox:t+"checkbox.html",checkboxes:t+"checkboxes.html",number:t+"default.html",submit:t+"submit.html",button:t+"submit.html",text:t+"default.html",date:t+"default.html",password:t+"default.html",datepicker:t+"datepicker.html",input:t+"default.html",radios:t+"radios.html",radiobuttons:t+"radio-buttons.html"})}]).directive("sfFieldset",function(){return{transclude:!0,scope:!0,templateUrl:"directives/decorators/bootstrap/fieldset-trcl.html",link:function(e,t,s){e.title=e.$eval(s.title)}}}); \ No newline at end of file diff --git a/examples/bootstrap-example.html b/examples/bootstrap-example.html index c467bcaa4..55320a68e 100644 --- a/examples/bootstrap-example.html +++ b/examples/bootstrap-example.html @@ -49,6 +49,7 @@

Schema

+ @@ -143,50 +144,56 @@

Schema

$scope.form = [ { - type: "help", - helpvalue: "

Yo ninja!

" - }, - { - type: "tabs", - tabs: [ - { - name: "Simple stuff", - items: [ - { - key: "name", - placeholder: "Check the console", - onChange: "log(modelValue)", - feedback: "{'glyphicon': true, 'glyphicon-ok': hasSuccess(), 'glyphicon-star': !hasSuccess() }" - }, - { - key: "favorite", - feedback: false - } - ] - }, - { - name: "More stuff", - items: [ - "attributes", + type: "fieldset", + title: "Stuff", + items: [ + { + type: "tabs", + tabs: [ { - key: "shoesize", - feedback: false + title: "Simple stuff", + items: [ + { + key: "name", + placeholder: "Check the console", + onChange: "log(modelValue)", + feedback: "{'glyphicon': true, 'glyphicon-ok': hasSuccess(), 'glyphicon-star': !hasSuccess() }" + }, + { + key: "favorite", + feedback: false + } + ] }, - "things", - "soul", { - type: "conditional", - condition: "person.soul", + title: "More stuff", items: [ - { key: "soulserial", placeholder: "ex. 666" } + "attributes", + { + key: "shoesize", + feedback: false + }, + "things" ] - }, - { key: "date", minDate: "2014-06-20" }, - { key: "radio", type: "radios" }, - { key: "radiobuttons", type: "radiobuttons" } - ] - }] + }] + }, + ] + }, + { + type: "help", + helpvalue: "
" + }, + "soul", + { + type: "conditional", + condition: "person.soul", + items: [ + { key: "soulserial", placeholder: "ex. 666" } + ] }, + { key: "date", minDate: "2014-06-20" }, + { key: "radio", type: "radios" }, + { key: "radiobuttons", type: "radiobuttons" }, { type: 'actions', items: [ diff --git a/src/directives/decorators/bootstrap/tabs.html b/src/directives/decorators/bootstrap/tabs.html index 16285d002..59e954b7f 100644 --- a/src/directives/decorators/bootstrap/tabs.html +++ b/src/directives/decorators/bootstrap/tabs.html @@ -1,13 +1,12 @@
-