24 |
--------------------------------------------------------------------------------
/examples/minimal/test/tests.js:
--------------------------------------------------------------------------------
1 | /* jshint expr: true */
2 | chai.should();
3 |
4 | describe('Schema form', function() {
5 |
6 | describe('directive', function() {
7 | beforeEach(module('templates'));
8 | beforeEach(module('schemaForm'));
9 | beforeEach(
10 | //We don't need no sanitation. We don't need no though control.
11 | module(function($sceProvider) {
12 | $sceProvider.enabled(false);
13 | })
14 | );
15 |
16 | it('should return correct form type for format "camelcase"',function(){
17 | inject(function($compile,$rootScope, schemaForm){
18 | var string_schema = {
19 | type: "object",
20 | properties: {
21 | color: {
22 | type: "string",
23 | }
24 | }
25 | };
26 |
27 | var color_schema = {
28 | type: "object",
29 | properties: {
30 | color: {
31 | type: "string",
32 | format: "color"
33 | }
34 | }
35 | };
36 |
37 | schemaForm.defaults(string_schema).form[0].type.should.be.eq("text");
38 | schemaForm.defaults(color_schema).form[0].type.should.be.eq("basic");
39 | });
40 | });
41 |
42 | });
43 | });
44 |
--------------------------------------------------------------------------------
/examples/camelcase/test/tests.js:
--------------------------------------------------------------------------------
1 | /* jshint expr: true */
2 | chai.should();
3 |
4 | describe('Schema form', function() {
5 |
6 | describe('directive', function() {
7 | beforeEach(module('templates'));
8 | beforeEach(module('schemaForm'));
9 | beforeEach(
10 | //We don't need no sanitation. We don't need no though control.
11 | module(function($sceProvider) {
12 | $sceProvider.enabled(false);
13 | })
14 | );
15 |
16 | it('should return correct form type for format "camelcase"',function(){
17 | inject(function($compile,$rootScope, schemaForm){
18 | var string_schema = {
19 | type: "object",
20 | properties: {
21 | color: {
22 | type: "string",
23 | }
24 | }
25 | };
26 |
27 | var color_schema = {
28 | type: "object",
29 | properties: {
30 | color: {
31 | type: "string",
32 | format: "color"
33 | }
34 | }
35 | };
36 |
37 | schemaForm.defaults(string_schema).form[0].type.should.be.eq("text");
38 | schemaForm.defaults(color_schema).form[0].type.should.be.eq("basic");
39 | });
40 | });
41 |
42 | });
43 | });
44 |
--------------------------------------------------------------------------------
/examples/typescript/test/tests.js:
--------------------------------------------------------------------------------
1 | /* jshint expr: true */
2 | chai.should();
3 |
4 | describe('Schema form', function() {
5 |
6 | describe('directive', function() {
7 | beforeEach(module('templates'));
8 | beforeEach(module('schemaForm'));
9 | beforeEach(
10 | //We don't need no sanitation. We don't need no though control.
11 | module(function($sceProvider) {
12 | $sceProvider.enabled(false);
13 | })
14 | );
15 |
16 | it('should return correct form type for format "camelcase"',function(){
17 | inject(function($compile,$rootScope, schemaForm){
18 | var string_schema = {
19 | type: "object",
20 | properties: {
21 | color: {
22 | type: "string",
23 | }
24 | }
25 | };
26 |
27 | var color_schema = {
28 | type: "object",
29 | properties: {
30 | color: {
31 | type: "string",
32 | format: "color"
33 | }
34 | }
35 | };
36 |
37 | schemaForm.defaults(string_schema).form[0].type.should.be.eq("text");
38 | schemaForm.defaults(color_schema).form[0].type.should.be.eq("basic");
39 | });
40 | });
41 |
42 | });
43 | });
44 |
--------------------------------------------------------------------------------
/examples/README.md:
--------------------------------------------------------------------------------
1 | [](https://gitter.im/OptimalBPM/angular-schema-form-add-ons?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
2 |
3 | ## Angular schema form add-ons - Examples
4 |
5 | This folder contains examples of add-ons showcasing different aspects of the ASF add-on architecture.
6 |
7 | To play around with these, you need to clone this repository:
8 |
9 | git clone https://github.com/OptimalBPM/angular-schema-form-add-ons.git
10 |
11 | This will create a local clone in the angular-schema-form-add-ons subfolder.
12 |
13 | Both examples will look better if you install them with bootstrap(the demos have bootstrap installed).
14 |
15 | ## Minimal
16 |
17 | The [minimal example](https://github.com/OptimalBPM/angular-schema-form-add-ons/tree/master/examples/minimal) simply
18 | uses an input to edit the model. It has a short text proving that it is the actual add-on being displayed.
19 |
20 | ## camelCase
21 |
22 | The [camelCase example](https://github.com/OptimalBPM/angular-schema-form-add-ons/tree/master/examples/camelcase) uses
23 | a normal input, and a button that changes whatever string has been entered into camelCase.
24 |
25 |
--------------------------------------------------------------------------------
/examples/minimal/src/angular-schema-form-minimal.js:
--------------------------------------------------------------------------------
1 | angular.module('schemaForm').config(['schemaFormProvider',
2 | 'schemaFormDecoratorsProvider', 'sfPathProvider',
3 | function(schemaFormProvider, schemaFormDecoratorsProvider, sfPathProvider) {
4 |
5 | // First, we want this to be the default for a combination of schema parameters
6 | var minimal = function (name, schema, options) {
7 | if (schema.type === 'string' && schema.format == 'minimal') {
8 | // Initiate a form provider
9 | var f = schemaFormProvider.stdFormObj(name, schema, options);
10 | f.key = options.path;
11 | f.type = 'minimal';
12 | // Add it to the lookup dict (for internal use)
13 | options.lookup[sfPathProvider.stringify(options.path)] = f;
14 | return f;
15 | }
16 | };
17 | // Add our default to the defaults array
18 | schemaFormProvider.defaults.string.unshift(minimal);
19 |
20 | // Second, we want it to show if someone have explicitly set the form type
21 | schemaFormDecoratorsProvider.addMapping('bootstrapDecorator', 'minimal',
22 | 'directives/decorators/bootstrap/minimal/angular-schema-form-minimal.html');
23 | }]);
24 |
25 |
26 |
--------------------------------------------------------------------------------
/examples/camelcase/angular-schema-form-camelcase.min.js:
--------------------------------------------------------------------------------
1 | angular.module("schemaForm").run(["$templateCache",function(e){e.put("directives/decorators/bootstrap/camelcase/angular-schema-form-camelcase.html",'
{{ (hasError() && errorMessage(schemaError())) || form.description}} The some setting-setting is true for the model at $$value$$!
')}]),angular.module("schemaForm").config(["schemaFormProvider","schemaFormDecoratorsProvider","sfPathProvider",function(e,a,r){var o=function(a,o,t){if("string"===o.type&&"camelcase"==o.format){var s=e.stdFormObj(a,o,t);return s.key=t.path,s.type="camelcase",t.lookup[r.stringify(t.path)]=s,s}};e.defaults.string.unshift(o),a.addMapping("bootstrapDecorator","camelcase","directives/decorators/bootstrap/camelcase/angular-schema-form-camelcase.html")}]);var camelCaseControllerFunction=function(e){e.camelCase=function(e){return e.toLowerCase().replace(/[- ](.)/g,function(e,a){return a.toUpperCase()})},e.makeCamelCase=function(){var a=e.ngModel[e.ngModel.length-1];a.$modelValue&&a.$setViewValue(e.camelCase(a.$modelValue))}};angular.module("schemaForm").directive("camelCaseDirective",function(){return{require:["ngModel"],restrict:"A",scope:!1,controller:["$scope",camelCaseControllerFunction],link:function(e,a,r,o){e.ngModel=o}}});
--------------------------------------------------------------------------------
/tools/README_new_add_on.md:
--------------------------------------------------------------------------------
1 |
2 | Minimal add-on
3 | =================
4 |
5 | ### About
6 |
7 | ***This README has been automatically generated by the [create_new_add_on.py-script](https://github.com/OptimalBPM/angular-schema-form-add-ons/tree/master/tools)
8 | at [angular-schema-form-add-ons](https://github.com/OptimalBPM/angular-schema-form-add-ons), remove this row before publishing.***
9 |
10 | This add-on presents a normal input field.
11 |
12 |
13 | ### Installation
14 | To use the provided example, make sure npm is installed, enter the destination_folder folder, and run(Linux):
15 |
16 | sudo npm install bower
17 | node_modules/bower/bin/bower install
18 |
19 | This will first locally install bower, and then used that bower to install the project dependencies.
20 |
21 |
22 | ### Running
23 |
24 | You should now be able to open the example.html in the browser.
25 |
26 |
27 | ### Building
28 |
29 | First, install all build tools, in the destination_folder folder, run
30 |
31 | sudo npm install
32 |
33 |
34 | The cycle for development is change and then build.
35 | If you want to make any changes, you should make them in the /src-files and then build, otherwise your changes
36 | will not be included in the example.
37 |
38 | From the installation, gulp should be installed, so therefore, in the destination_folder folder, just run:
39 |
40 | gulp default
41 |
42 | This starts a build and generates destination_folder/angular-schema-form-minimal.js and destination_folder/angular-schema-form-minimal.min.js.
43 | To observe your changes, just refresh the example.html-page.
--------------------------------------------------------------------------------
/tools/lib/mass_replace.py:
--------------------------------------------------------------------------------
1 | # Written by Steve R. Hastings, on stack overflow: http://stackoverflow.com/a/1597755/4072379
2 |
3 | import os
4 | import re
5 | import sys
6 | import shutil
7 |
8 | # list of extensions to replace
9 | DEFAULT_REPLACE_EXTENSIONS = None
10 | # example: uncomment next line to only replace *.c, *.h, and/or *.txt
11 | # DEFAULT_REPLACE_EXTENSIONS = (".c", ".h", ".txt")
12 |
13 | def try_to_replace(fname, replace_extensions=DEFAULT_REPLACE_EXTENSIONS):
14 | if replace_extensions:
15 | return fname.lower().endswith(replace_extensions)
16 | return True
17 |
18 |
19 | def file_replace(fname, pat, s_after):
20 | # first, see if the pattern is even in the file.
21 | with open(fname) as f:
22 | if not any(re.search(pat, line) for line in f):
23 | return # pattern does not occur in file so we are done.
24 |
25 | # pattern is in the file, so perform replace operation.
26 | with open(fname) as f:
27 | out_fname = fname + ".tmp"
28 | out = open(out_fname, "w")
29 | for line in f:
30 | out.write(re.sub(pat, s_after, line))
31 | out.close()
32 | shutil.move(out_fname, fname)
33 |
34 |
35 | def mass_replace(dir_name, s_before, s_after, replace_extensions=DEFAULT_REPLACE_EXTENSIONS):
36 | pat = re.compile(s_before)
37 | for dirpath, dirnames, filenames in os.walk(dir_name):
38 | for fname in filenames:
39 | if try_to_replace(fname, replace_extensions):
40 | fullname = os.path.join(dirpath, fname)
41 | file_replace(fullname, pat, s_after)
42 |
--------------------------------------------------------------------------------
/examples/minimal/README.md:
--------------------------------------------------------------------------------
1 |
2 | Minimal add-on
3 | =================
4 |
5 | ### About
6 |
7 | This example presents a normal input field.
8 |
9 | There is a demo, basically just the published html with bootstrap installed, running at:
10 | http://demo.optimalbpm.se/angular-schema-form-add-ons/examples/minimal/example.html
11 |
12 | These might not be needed if you do not need any local logic, but are here for the example.
13 |
14 | Look at the source for more information on how it works, it is overly documented.
15 |
16 |
17 | ### Installation
18 | To use the example, enter the examples/minimal folder and run
19 |
20 | sudo npm install bower
21 | node_modules/bower/bin/bower install
22 |
23 | This will first locally install bower, and then used that bower to install the project dependencies.
24 |
25 |
26 | ### Running
27 |
28 | You should now be able to open the example.html in the browser.
29 |
30 |
31 | ### Building
32 |
33 | First, install all build tools, in the examples/minimal folder, run
34 |
35 | sudo npm install
36 |
37 |
38 | The cycle for development is change and then build.
39 | If you want to make any changes, you should make them in the /src-files and then build, otherwise your changes
40 | will not be included in the example.
41 |
42 | From the installation, gulp should be installed, so therefore, in the examples/minimal folder, just run:
43 |
44 | gulp default
45 |
46 | This starts a build and generates examples/basic/angular-schema-form-minimal.js and examples/basic/angular-schema-form-minimal.min.js.
47 | To observe your changes, just refresh the example.html-page.
--------------------------------------------------------------------------------
/examples/typescript/gulpfile.js:
--------------------------------------------------------------------------------
1 | /* global require */
2 |
3 | var gulp = require('gulp');
4 |
5 | var templateCache = require('gulp-angular-templatecache');
6 | var minifyHtml = require('gulp-minify-html');
7 | var concat = require('gulp-concat');
8 | var uglify = require('gulp-uglify');
9 | var streamqueue = require('streamqueue');
10 | var jscs = require('gulp-jscs');
11 | var tsc = require('gulp-tsc');
12 |
13 | gulp.task('build', function () {
14 | var stream = streamqueue({objectMode: true});
15 | stream.queue(
16 | gulp.src('./src/*.html')
17 | .pipe(minifyHtml({
18 | empty: true,
19 | spare: true,
20 | quotes: true
21 | }))
22 | .pipe(templateCache({
23 | module: 'schemaForm',
24 | root: 'directives/decorators/bootstrap/typescript/'
25 | }))
26 | );
27 |
28 | stream.queue(
29 | gulp.src(['src/**/*.ts'])
30 | .pipe(tsc())
31 | );
32 |
33 |
34 | stream.done()
35 | .pipe(concat('angular-schema-form-typescript.js'))
36 | .pipe(gulp.dest('.'));
37 | });
38 |
39 | gulp.task('minify', function () {
40 | var stream = streamqueue({objectMode: true});
41 | stream.queue(gulp.src('angular-schema-form-typescript.js'));
42 | stream.done()
43 | .pipe(uglify())
44 | .pipe(concat('angular-schema-form-typescript.min.js'))
45 | .pipe(gulp.dest('.'))
46 | });
47 |
48 | gulp.task('default', [
49 | 'build',
50 | 'minify'
51 | ]);
52 |
53 | gulp.task('watch', function () {
54 | gulp.watch('./src/**/*', ['default']);
55 | });
56 |
--------------------------------------------------------------------------------
/examples/typescript/angular-schema-form-typescript.min.js:
--------------------------------------------------------------------------------
1 | angular.module("schemaForm").run(["$templateCache",function(e){e.put("directives/decorators/bootstrap/typescript/angular-schema-form-typescript.html",'
{{ (hasError() && errorMessage(schemaError())) || form.description}} The some setting-setting is true for the model at $$value$$!
')}]),angular.module("schemaForm").config(["schemaFormProvider","schemaFormDecoratorsProvider","sfPathProvider",function(e,t,r){var o=function(t,o,i){if("string"===o.type&&"typescript"==o.format){var s=e.stdFormObj(t,o,i);return s.key=i.path,s.type="typescript",i.lookup[r.stringify(i.path)]=s,s}};e.defaults.string.unshift(o),t.addMapping("bootstrapDecorator","typescript","directives/decorators/bootstrap/typescript/angular-schema-form-typescript.html")}]);var typescriptController=function(){function e(e,t){var r=this;this.$scope=e,this.camelCase=function(e){return e.toLowerCase().replace(/[- ](.)/g,function(e,t){return t.toUpperCase()})},this.makeCamelCase=function(){var e=r.directiveScope.ngModel[r.directiveScope.ngModel.length-1];e.$modelValue&&e.$setViewValue(r.camelCase(e.$modelValue))},console.log("Initiating the process controller"+e.toString()),this.directiveScope=e}return e}();angular.module("schemaForm").directive("typeScriptDirective",function(){return{require:["ngModel"],restrict:"A",scope:!1,controller:["$scope",typescriptController],link:function(e,t,r,o){e.ngModel=o}}});
--------------------------------------------------------------------------------
/examples/typescript/example.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Nicklas B on 2016-01-13.
3 | */
4 |
5 | /*global angular */
6 | "use strict";
7 |
8 | /**
9 | * The main app module
10 | * @name exampleApp
11 | * @type {angular.Module}
12 | */
13 |
14 | var exampleApp = angular.module("exampleApp", ["schemaForm"]);
15 |
16 | exampleApp.controller("exampleController", ["$scope", function ($scope) {
17 |
18 |
19 | // This is the schema definition, note that the title, even though it is possible to, isn't defined here.
20 | // This to make the schema more portable, schemas are for validation and definition and can be used everywhere.
21 | $scope.schema = {
22 | type: "object",
23 | title: "Typescript camelCase",
24 | properties: {
25 | camelCaseFormat: {
26 | type: "string",
27 | format: "typescript",
28 | description: "When you edit this, the value will become automatically camelCase:d."
29 | }
30 |
31 | },
32 | required: ["camelCaseFormat"]
33 | };
34 |
35 | // Define all UI aspects of the form
36 | $scope.form = [
37 |
38 | {
39 | "key": "camelCaseFormat",
40 | "title": "Example of camelCase editor via format"
41 | },
42 | {
43 | type: "submit",
44 | style: "btn-info",
45 | title: "OK"
46 | }
47 | ];
48 | // Initiate the model
49 | $scope.model = {};
50 | // Initiate one of the inputs
51 | $scope.model.camelCaseFormat = "default value";
52 |
53 | // This is called by asf on submit, specified in example.html, ng-submit.
54 | $scope.submitted = function (form) {
55 | $scope.$broadcast("schemaFormValidate");
56 | console.log($scope.model);
57 | };
58 | }]);
59 |
60 |
--------------------------------------------------------------------------------
/examples/minimal/example.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | ASF Add-on example - Minimal
24 |
25 |
26 |
27 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/examples/camelcase/README.md:
--------------------------------------------------------------------------------
1 |
2 | camelCase add-on
3 | =================
4 | ### About
5 |
6 | This example presents a normal input field and a button that changes whatever string has been entered into camelCase.
7 |
8 | There is a demo, basically just the published html with bootstrap installed, running at:
9 | http://demo.optimalbpm.se/angular-schema-form-add-ons/examples/camelcase/example.html
10 |
11 | It uses:
12 | * a directive to access the model and expose the controller to the child elements
13 | * a controller to handle the logic of the camel-casing
14 |
15 | These might not be needed if you do not need any local logic, but are here for the example.
16 |
17 | Look at the source for more information on how it works, it is overly documented.
18 |
19 |
20 | ### Installation
21 | To use the example, enter the examples/camelcase folder and run
22 |
23 | sudo npm install bower
24 | node_modules/bower/bin/bower install
25 |
26 | This will first locally install bower, and then used that bower to install the project dependencies.
27 |
28 |
29 | ### Running
30 |
31 | You should now be able to open the example.html in the browser.
32 |
33 |
34 | ### Building
35 |
36 | First, install all build tools, in the examples/camelcase folder, run
37 |
38 | sudo npm install
39 |
40 |
41 | The cycle for development is change and then build.
42 | If you want to make any changes, you should make them in the /src-files and then build, otherwise your changes
43 | will not be included in the example.
44 |
45 | From the installation, gulp should be installed, so therefore, in the examples/camelcase folder, just run:
46 |
47 | gulp default
48 |
49 | This starts a build and generates examples/basic/angular-schema-form-camelcase.js and examples/basic/angular-schema-form-camelcase.min.js.
50 | To observe your changes, just refresh the example.html-page.
--------------------------------------------------------------------------------
/examples/typescript/README.md:
--------------------------------------------------------------------------------
1 |
2 | Typescript (ported camelCase) add-on
3 | =================
4 | ### About
5 |
6 | This example presents a normal input field and a button that changes whatever string has been entered into camelCase.
7 |
8 | There is a demo, basically just the published html with bootstrap installed, running at:
9 | http://demo.optimalbpm.se/angular-schema-form-add-ons/examples/typescript/example.html
10 |
11 | It uses:
12 | * a directive to access the model and expose the controller to the child elements
13 | * a controller to handle the logic of the camel-casing
14 |
15 | These might not be needed if you do not need any local logic, but are here for the example.
16 |
17 | Look at the source for more information on how it works, it is overly documented.
18 |
19 |
20 | ### Installation
21 | To use the example, enter the examples/camelcase folder and run
22 |
23 | sudo npm install bower
24 | node_modules/bower/bin/bower install
25 |
26 | This will first locally install bower, and then used that bower to install the project dependencies.
27 |
28 |
29 | ### Running
30 |
31 | You should now be able to open the example.html in the browser.
32 |
33 |
34 | ### Building
35 |
36 | First, install all build tools, in the examples/camelcase folder, run
37 |
38 | sudo npm install
39 |
40 |
41 | The cycle for development is change and then build.
42 | If you want to make any changes, you should make them in the /src-files and then build, otherwise your changes
43 | will not be included in the example.
44 |
45 | From the installation, gulp should be installed, so therefore, in the examples/camelcase folder, just run:
46 |
47 | gulp default
48 |
49 | This starts a build and generates examples/basic/angular-schema-form-camelcase.js and examples/basic/angular-schema-form-camelcase.min.js.
50 | To observe your changes, just refresh the example.html-page.
--------------------------------------------------------------------------------
/examples/minimal/gulpfile.js:
--------------------------------------------------------------------------------
1 | /* global require */
2 |
3 | var gulp = require('gulp');
4 |
5 | var templateCache = require('gulp-angular-templatecache');
6 | var minifyHtml = require('gulp-minify-html');
7 | var concat = require('gulp-concat');
8 | var uglify = require('gulp-uglify');
9 | var streamqueue = require('streamqueue');
10 | var jscs = require('gulp-jscs');
11 |
12 | gulp.task('minify', function() {
13 | var stream = streamqueue({objectMode: true});
14 | stream.queue(
15 | gulp.src('./src/*.html')
16 | .pipe(minifyHtml({
17 | empty: true,
18 | spare: true,
19 | quotes: true
20 | }))
21 | .pipe(templateCache({
22 | module: 'schemaForm',
23 | root: 'directives/decorators/bootstrap/minimal/'
24 | }))
25 | );
26 | stream.queue(gulp.src('./src/*.js'));
27 |
28 | stream.done()
29 | .pipe(concat('angular-schema-form-minimal.min.js'))
30 | .pipe(uglify())
31 | .pipe(gulp.dest('.'));
32 |
33 | });
34 |
35 | gulp.task('non-minified-dist', function() {
36 | var stream = streamqueue({objectMode: true});
37 | stream.queue(
38 | gulp.src('./src/*.html')
39 | .pipe(templateCache({
40 | module: 'schemaForm',
41 | root: 'directives/decorators/bootstrap/minimal/'
42 | }))
43 | );
44 | stream.queue(gulp.src('./src/*.js'));
45 |
46 | stream.done()
47 | .pipe(concat('angular-schema-form-minimal.js'))
48 | .pipe(gulp.dest('.'));
49 |
50 | });
51 |
52 | gulp.task('jscs', function() {
53 | gulp.src('./src/**/*.js')
54 | .pipe(jscs());
55 | });
56 |
57 | gulp.task('default', [
58 | 'minify',
59 | 'non-minified-dist',
60 | 'jscs'
61 | ]);
62 |
63 | gulp.task('watch', function() {
64 | gulp.watch('./src/**/*', ['default']);
65 | });
66 |
--------------------------------------------------------------------------------
/examples/camelcase/gulpfile.js:
--------------------------------------------------------------------------------
1 | /* global require */
2 |
3 | var gulp = require('gulp');
4 |
5 | var templateCache = require('gulp-angular-templatecache');
6 | var minifyHtml = require('gulp-minify-html');
7 | var concat = require('gulp-concat');
8 | var uglify = require('gulp-uglify');
9 | var streamqueue = require('streamqueue');
10 | var jscs = require('gulp-jscs');
11 |
12 | gulp.task('minify', function() {
13 | var stream = streamqueue({objectMode: true});
14 | stream.queue(
15 | gulp.src('./src/*.html')
16 | .pipe(minifyHtml({
17 | empty: true,
18 | spare: true,
19 | quotes: true
20 | }))
21 | .pipe(templateCache({
22 | module: 'schemaForm',
23 | root: 'directives/decorators/bootstrap/camelcase/'
24 | }))
25 | );
26 | stream.queue(gulp.src('./src/*.js'));
27 |
28 | stream.done()
29 | .pipe(concat('angular-schema-form-camelcase.min.js'))
30 | .pipe(uglify())
31 | .pipe(gulp.dest('.'));
32 |
33 | });
34 |
35 | gulp.task('non-minified-dist', function() {
36 | var stream = streamqueue({objectMode: true});
37 | stream.queue(
38 | gulp.src('./src/*.html')
39 | .pipe(templateCache({
40 | module: 'schemaForm',
41 | root: 'directives/decorators/bootstrap/camelcase/'
42 | }))
43 | );
44 | stream.queue(gulp.src('./src/*.js'));
45 |
46 | stream.done()
47 | .pipe(concat('angular-schema-form-camelcase.js'))
48 | .pipe(gulp.dest('.'));
49 |
50 | });
51 |
52 | gulp.task('jscs', function() {
53 | gulp.src('./src/**/*.js')
54 | .pipe(jscs());
55 | });
56 |
57 | gulp.task('default', [
58 | 'minify',
59 | 'non-minified-dist',
60 | 'jscs'
61 | ]);
62 |
63 | gulp.task('watch', function() {
64 | gulp.watch('./src/**/*', ['default']);
65 | });
66 |
--------------------------------------------------------------------------------
/examples/camelcase/src/angular-schema-form-camelcase.html:
--------------------------------------------------------------------------------
1 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
28 | {{ (hasError() && errorMessage(schemaError())) || form.description}}
29 |
30 |
31 | The some setting-setting is true for the model at $$value$$!
32 |
26 |
28 | {{ (hasError() && errorMessage(schemaError())) || form.description}}
29 |
30 |
31 | The some setting-setting is true for the model at $$value$$!
32 |
33 |
--------------------------------------------------------------------------------
/examples/minimal/example.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Nicklas B on 2015-06-21.
3 | */
4 |
5 | /*global angular */
6 | "use strict";
7 |
8 | /**
9 | * The main app module
10 | * @name exampleApp
11 | * @type {angular.Module}
12 | */
13 |
14 | var exampleApp = angular.module("exampleApp", ["schemaForm"]);
15 |
16 | exampleApp.controller("exampleController", ["$scope", function ($scope) {
17 |
18 |
19 | // This is the schema definition, note that the title, even though it is possible to, isn't defined here.
20 | // This to make the schema more portable, schemas are for validation and definition and can be used everywhere.
21 | $scope.schema = {
22 | type: "object",
23 | title: "Minimal",
24 | properties: {
25 | minimalFormat: {
26 | type: "string",
27 | format: "minimal",
28 | description: "When you edit this, it is in the add-ons input box."
29 | },
30 | minimalFormType: {
31 | type: "string",
32 | description: "When you edit this, which is required, it is equally in the add-ons input box"
33 | }
34 | },
35 | required: ["minimalFormType"]
36 | };
37 |
38 | // Define all UI aspects of the form
39 | $scope.form = [
40 |
41 | {
42 | "key": "minimalFormat",
43 | "title": "Example of minimal editor via format"
44 | },
45 | {
46 | "key": "minimalFormType",
47 | "title": "Example of minimal editor via form type",
48 | "type": "minimal",
49 | "some_setting": "true"
50 | },
51 | {
52 | type: "submit",
53 | style: "btn-info",
54 | title: "OK"
55 | }
56 | ];
57 | // Initiate the model
58 | $scope.model = {};
59 | // Initiate one of the inputs
60 | $scope.model.minimalFormat = "default value";
61 |
62 | // This is called by asf on submit, specified in example.html, ng-submit.
63 | $scope.submitted = function (form) {
64 | $scope.$broadcast("schemaFormValidate");
65 | console.log($scope.model);
66 | };
67 | }]);
68 |
69 |
--------------------------------------------------------------------------------
/examples/camelcase/example.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by Nicklas B on 2015-06-21.
3 | */
4 |
5 | /*global angular */
6 | "use strict";
7 |
8 | /**
9 | * The main app module
10 | * @name exampleApp
11 | * @type {angular.Module}
12 | */
13 |
14 | var exampleApp = angular.module("exampleApp", ["schemaForm"]);
15 |
16 | exampleApp.controller("exampleController", ["$scope", function ($scope) {
17 |
18 |
19 | // This is the schema definition, note that the title, even though it is possible to, isn't defined here.
20 | // This to make the schema more portable, schemas are for validation and definition and can be used everywhere.
21 | $scope.schema = {
22 | type: "object",
23 | title: "camelCase",
24 | properties: {
25 | camelCaseFormat: {
26 | type: "string",
27 | format: "camelcase",
28 | description: "When you edit this, the value will become automatically camelCase:d."
29 | },
30 | camelCaseFormType: {
31 | type: "string",
32 | description: "When you edit this, which is required, the value will become equally camelCase:d."
33 | }
34 | },
35 | required: ["camelCaseFormType"]
36 | };
37 |
38 | // Define all UI aspects of the form
39 | $scope.form = [
40 |
41 | {
42 | "key": "camelCaseFormat",
43 | "title": "Example of camelCase editor via format"
44 | },
45 | {
46 | "key": "camelCaseFormType",
47 | "title": "Example of camelCase editor via form type",
48 | "type": "camelcase",
49 | "some_setting": "true"
50 | },
51 | {
52 | type: "submit",
53 | style: "btn-info",
54 | title: "OK"
55 | }
56 | ];
57 | // Initiate the model
58 | $scope.model = {};
59 | // Initiate one of the inputs
60 | $scope.model.camelCaseFormat = "default value";
61 |
62 | // This is called by asf on submit, specified in example.html, ng-submit.
63 | $scope.submitted = function (form) {
64 | $scope.$broadcast("schemaFormValidate");
65 | console.log($scope.model);
66 | };
67 | }]);
68 |
69 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://gitter.im/OptimalBPM/angular-schema-form-add-ons?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
2 |
3 | # Angular schema form add-ons
4 |
5 | ***New to creating ASF add-ons? This is where to go: [Creating a new add-on](https://github.com/OptimalBPM/angular-schema-form-add-ons/wiki/Creating-a-new-add-on).***
6 |
7 | Where is everything? This is how it is organized:
8 |
9 | ### [WIKI](https://github.com/OptimalBPM/angular-schema-form-add-ons/wiki)
10 | **ASF version independent information, recommendations, guidelines, tutorials, tips & tricks**
11 |
12 | For that, please browse the articles at the [wiki](https://github.com/OptimalBPM/angular-schema-form-add-ons/wiki).
13 |
14 | ### [Gitter chat room](https://gitter.im/OptimalBPM/angular-schema-form-add-ons)
15 | **Discussions and questions about ASF plugin development in general**
16 |
17 | These are conducted in the [gitter chat room ](https://gitter.im/OptimalBPM/angular-schema-form-add-ons) [](https://gitter.im/OptimalBPM/angular-schema-form-add-ons?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge).
18 |
19 | ### [HERE in the source repository](https://github.com/OptimalBPM/angular-schema-form-add-ons)
20 | **ASF add-on [documentation](https://github.com/OptimalBPM/angular-schema-form-add-ons/tree/master/documentation), [examples](https://github.com/OptimalBPM/angular-schema-form-add-ons/tree/master/examples) and [tools](https://github.com/OptimalBPM/angular-schema-form-add-ons/tree/master/tools)**
21 |
22 | These are stored here, in this documentation and the files of this repository.
23 | For each ASF major version, the previous version gets its own branch.
24 |
25 | The original "Extending Schema Form"-article is located [here](https://github.com/OptimalBPM/angular-schema-form-add-ons/blob/master/documentation/extending.md).
26 |
27 | ### [ISSUES](https://github.com/OptimalBPM/angular-schema-form-add-ons/issues)
28 | **News, information and news relevant for ASF add-on-development**
29 |
30 | These are posted as [issues](https://github.com/OptimalBPM/angular-schema-form-add-ons/issues) for this project.
31 | Follow them to get the neccessary information.
32 |
33 | (not sure if that works well, though, we'll see)
34 |
35 |
36 |
--------------------------------------------------------------------------------
/examples/minimal/angular-schema-form-minimal.js:
--------------------------------------------------------------------------------
1 | angular.module("schemaForm").run(["$templateCache", function($templateCache) {$templateCache.put("directives/decorators/bootstrap/minimal/angular-schema-form-minimal.html","\n\n\n
\n");}]);
2 | angular.module('schemaForm').config(['schemaFormProvider',
3 | 'schemaFormDecoratorsProvider', 'sfPathProvider',
4 | function(schemaFormProvider, schemaFormDecoratorsProvider, sfPathProvider) {
5 |
6 | // First, we want this to be the default for a combination of schema parameters
7 | var minimal = function (name, schema, options) {
8 | if (schema.type === 'string' && schema.format == 'minimal') {
9 | // Initiate a form provider
10 | var f = schemaFormProvider.stdFormObj(name, schema, options);
11 | f.key = options.path;
12 | f.type = 'minimal';
13 | // Add it to the lookup dict (for internal use)
14 | options.lookup[sfPathProvider.stringify(options.path)] = f;
15 | return f;
16 | }
17 | };
18 | // Add our default to the defaults array
19 | schemaFormProvider.defaults.string.unshift(minimal);
20 |
21 | // Second, we want it to show if someone have explicitly set the form type
22 | schemaFormDecoratorsProvider.addMapping('bootstrapDecorator', 'minimal',
23 | 'directives/decorators/bootstrap/minimal/angular-schema-form-minimal.html');
24 | }]);
25 |
26 |
27 |
--------------------------------------------------------------------------------
/examples/camelcase/karma.conf.js:
--------------------------------------------------------------------------------
1 |
2 | module.exports = function(config) {
3 | config.set({
4 |
5 | // base path, that will be used to resolve files and exclude
6 | basePath: '.',
7 |
8 | // frameworks to use
9 | frameworks: ['mocha', 'chai-sinon'],
10 |
11 | // list of files / patterns to load in the browser
12 | files: [
13 | 'bower_components/jquery/dist/jquery.min.js',
14 | 'bower_components/angular/angular.js',
15 | 'bower_components/angular-mocks/angular-mocks.js',
16 | 'bower_components/angular-schema-form/dist/schema-form.js',
17 | 'bower_components/angular-schema-form/dist/bootstrap-decorator.min.js',
18 | 'bower_components/objectpath/lib/ObjectPath.js',
19 | 'src/*.js',
20 | 'src/**/*.html',
21 | 'test/tests.js'
22 | ],
23 |
24 | // list of files to exclude
25 | exclude: [
26 |
27 | ],
28 |
29 | // test results reporter to use
30 | // possible values: 'dots', 'progress', 'junit', 'growl', 'coverage'
31 | reporters: ['progress', 'coverage', 'growler'],
32 |
33 | preprocessors: {
34 | 'src/**/*.js': ['coverage'],
35 | 'src/**/*.html': ['ng-html2js']
36 | },
37 |
38 | // optionally, configure the reporter
39 | coverageReporter: {
40 | type : 'lcov',
41 | dir : 'coverage/'
42 | },
43 |
44 | ngHtml2JsPreprocessor: {
45 | cacheIdFromPath: function(filepath) {
46 | return 'directives/decorators/bootstrap/camelcase/' + filepath.substr(4);
47 | },
48 | moduleName: 'templates'
49 | },
50 |
51 | // web server port
52 | port: 9876,
53 |
54 | // enable / disable colors in the output (reporters and logs)
55 | colors: true,
56 |
57 | // level of logging
58 | // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
59 | logLevel: config.LOG_INFO,
60 |
61 |
62 | // enable / disable watching file and executing tests whenever any file changes
63 | autoWatch: true,
64 |
65 |
66 | // Start these browsers, currently available:
67 | // - Chrome
68 | // - ChromeCanary
69 | // - Firefox
70 | // - Opera (has to be installed with `npm install karma-opera-launcher`)
71 | // - Safari (only Mac; has to be installed with `npm install karma-safari-launcher`)
72 | // - PhantomJS
73 | // - IE (only Windows; has to be installed with `npm install karma-ie-launcher`)
74 | browsers: ['PhantomJS'],
75 |
76 |
77 | // If browser does not capture in given timeout [ms], kill it
78 | captureTimeout: 60000,
79 |
80 |
81 | // Continuous Integration mode
82 | // if true, it capture browsers, run tests and exit
83 | singleRun: false
84 | });
85 | };
86 |
--------------------------------------------------------------------------------
/examples/minimal/karma.conf.js:
--------------------------------------------------------------------------------
1 |
2 | module.exports = function(config) {
3 | config.set({
4 |
5 | // base path, that will be used to resolve files and exclude
6 | basePath: '.',
7 |
8 | // frameworks to use
9 | frameworks: ['mocha', 'chai-sinon'],
10 |
11 | // list of files / patterns to load in the browser
12 | files: [
13 | 'bower_components/jquery/dist/jquery.min.js',
14 | 'bower_components/angular/angular.js',
15 | 'bower_components/angular-mocks/angular-mocks.js',
16 | 'bower_components/angular-schema-form/dist/schema-form.js',
17 | 'bower_components/angular-schema-form/dist/bootstrap-decorator.min.js',
18 | 'bower_components/objectpath/lib/ObjectPath.js',
19 | 'src/*.js',
20 | 'src/**/*.html',
21 | 'test/tests.js'
22 | ],
23 |
24 | // list of files to exclude
25 | exclude: [
26 |
27 | ],
28 |
29 | // test results reporter to use
30 | // possible values: 'dots', 'progress', 'junit', 'growl', 'coverage'
31 | reporters: ['progress', 'coverage', 'growler'],
32 |
33 | preprocessors: {
34 | 'src/**/*.js': ['coverage'],
35 | 'src/**/*.html': ['ng-html2js']
36 | },
37 |
38 | // optionally, configure the reporter
39 | coverageReporter: {
40 | type : 'lcov',
41 | dir : 'coverage/'
42 | },
43 |
44 | ngHtml2JsPreprocessor: {
45 | cacheIdFromPath: function(filepath) {
46 | return 'directives/decorators/bootstrap/minimal/' + filepath.substr(4);
47 | },
48 | moduleName: 'templates'
49 | },
50 |
51 | // web server port
52 | port: 9876,
53 |
54 | // enable / disable colors in the output (reporters and logs)
55 | colors: true,
56 |
57 | // level of logging
58 | // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
59 | logLevel: config.LOG_INFO,
60 |
61 |
62 | // enable / disable watching file and executing tests whenever any file changes
63 | autoWatch: true,
64 |
65 |
66 | // Start these browsers, currently available:
67 | // - Chrome
68 | // - ChromeCanary
69 | // - Firefox
70 | // - Opera (has to be installed with `npm install karma-opera-launcher`)
71 | // - Safari (only Mac; has to be installed with `npm install karma-safari-launcher`)
72 | // - PhantomJS
73 | // - IE (only Windows; has to be installed with `npm install karma-ie-launcher`)
74 | browsers: ['PhantomJS'],
75 |
76 |
77 | // If browser does not capture in given timeout [ms], kill it
78 | captureTimeout: 60000,
79 |
80 |
81 | // Continuous Integration mode
82 | // if true, it capture browsers, run tests and exit
83 | singleRun: false
84 | });
85 | };
86 |
--------------------------------------------------------------------------------
/examples/typescript/karma.conf.js:
--------------------------------------------------------------------------------
1 |
2 | module.exports = function(config) {
3 | config.set({
4 |
5 | // base path, that will be used to resolve files and exclude
6 | basePath: '.',
7 |
8 | // frameworks to use
9 | frameworks: ['mocha', 'chai-sinon'],
10 |
11 | // list of files / patterns to load in the browser
12 | files: [
13 | 'bower_components/jquery/dist/jquery.min.js',
14 | 'bower_components/angular/angular.js',
15 | 'bower_components/angular-mocks/angular-mocks.js',
16 | 'bower_components/angular-schema-form/dist/schema-form.js',
17 | 'bower_components/angular-schema-form/dist/bootstrap-decorator.min.js',
18 | 'bower_components/objectpath/lib/ObjectPath.js',
19 | 'src/*.js',
20 | 'src/**/*.html',
21 | 'test/tests.js'
22 | ],
23 |
24 | // list of files to exclude
25 | exclude: [
26 |
27 | ],
28 |
29 | // test results reporter to use
30 | // possible values: 'dots', 'progress', 'junit', 'growl', 'coverage'
31 | reporters: ['progress', 'coverage', 'growler'],
32 |
33 | preprocessors: {
34 | 'src/**/*.js': ['coverage'],
35 | 'src/**/*.html': ['ng-html2js']
36 | },
37 |
38 | // optionally, configure the reporter
39 | coverageReporter: {
40 | type : 'lcov',
41 | dir : 'coverage/'
42 | },
43 |
44 | ngHtml2JsPreprocessor: {
45 | cacheIdFromPath: function(filepath) {
46 | return 'directives/decorators/bootstrap/camelcase/' + filepath.substr(4);
47 | },
48 | moduleName: 'templates'
49 | },
50 |
51 | // web server port
52 | port: 9876,
53 |
54 | // enable / disable colors in the output (reporters and logs)
55 | colors: true,
56 |
57 | // level of logging
58 | // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
59 | logLevel: config.LOG_INFO,
60 |
61 |
62 | // enable / disable watching file and executing tests whenever any file changes
63 | autoWatch: true,
64 |
65 |
66 | // Start these browsers, currently available:
67 | // - Chrome
68 | // - ChromeCanary
69 | // - Firefox
70 | // - Opera (has to be installed with `npm install karma-opera-launcher`)
71 | // - Safari (only Mac; has to be installed with `npm install karma-safari-launcher`)
72 | // - PhantomJS
73 | // - IE (only Windows; has to be installed with `npm install karma-ie-launcher`)
74 | browsers: ['PhantomJS'],
75 |
76 |
77 | // If browser does not capture in given timeout [ms], kill it
78 | captureTimeout: 60000,
79 |
80 |
81 | // Continuous Integration mode
82 | // if true, it capture browsers, run tests and exit
83 | singleRun: false
84 | });
85 | };
86 |
--------------------------------------------------------------------------------
/examples/camelcase/src/angular-schema-form-camelcase.js:
--------------------------------------------------------------------------------
1 | angular.module('schemaForm').config(['schemaFormProvider',
2 | 'schemaFormDecoratorsProvider', 'sfPathProvider',
3 | function(schemaFormProvider, schemaFormDecoratorsProvider, sfPathProvider) {
4 |
5 | // First, we want this to be the default for a combination of schema parameters
6 | var camelcase = function (name, schema, options) {
7 | if (schema.type === 'string' && schema.format == 'camelcase') {
8 | // Initiate a form provider
9 | var f = schemaFormProvider.stdFormObj(name, schema, options);
10 | f.key = options.path;
11 | f.type = 'camelcase';
12 | // Add it to the lookup dict (for internal use)
13 | options.lookup[sfPathProvider.stringify(options.path)] = f;
14 | return f;
15 | }
16 | };
17 | // Add our default to the defaults array
18 | schemaFormProvider.defaults.string.unshift(camelcase);
19 |
20 | // Second, we want it to show if someone have explicitly set the form type
21 | schemaFormDecoratorsProvider.addMapping('bootstrapDecorator', 'camelcase',
22 | 'directives/decorators/bootstrap/camelcase/angular-schema-form-camelcase.html');
23 | }]);
24 |
25 |
26 | // Declare a controller, this is used in the camelcaseDirective below
27 | var camelCaseControllerFunction = function($scope) {
28 |
29 | $scope.camelCase = function (input) {
30 | // Turn the input value into camelCase and return it.
31 | return input.toLowerCase().replace(/[- ](.)/g, function(match, group1) {
32 | return group1.toUpperCase();
33 | });
34 | };
35 |
36 | $scope.makeCamelCase = function () {
37 | // This is invoked by the ng-click
38 | // The ngModel in ASF is an array, we want to access the actual value
39 | var leaf_model = $scope.ngModel[$scope.ngModel.length - 1];
40 | if (leaf_model.$modelValue) {
41 | // If there is something to camelCase, do it!
42 | leaf_model.$setViewValue($scope.camelCase(leaf_model.$modelValue));
43 | };
44 | };
45 | };
46 |
47 | // Create a directive to properly access the ngModel set in the view (src/angular-schema-form-camelcase.html)
48 | angular.module('schemaForm').directive('camelCaseDirective', function() {
49 | return {
50 | // The directive needs the ng-model to be set, look at the
51 | require: ['ngModel'],
52 | restrict: 'A',
53 | // Do not create a isolate scope, makeCamelCase should be available to the button element
54 | scope: false,
55 | // Define a controller, use the function from above, inject the scope
56 | controller : ['$scope', camelCaseControllerFunction],
57 | // Use the link function to initiate the ngModel in the controller scope
58 | link: function(scope, iElement, iAttrs, ngModelCtrl) {
59 | scope.ngModel = ngModelCtrl;
60 | }
61 | };
62 | });
63 |
--------------------------------------------------------------------------------
/examples/typescript/src/angular-schema-form-typescript.ts:
--------------------------------------------------------------------------------
1 |
2 | ///
3 | ///
4 |
5 | angular.module('schemaForm').config(['schemaFormProvider',
6 | 'schemaFormDecoratorsProvider', 'sfPathProvider',
7 | function (schemaFormProvider, schemaFormDecoratorsProvider, sfPathProvider) {
8 |
9 | // First, we want this to be the default for a combination of schema parameters
10 | var typescript = function (name, schema, options) {
11 | if (schema.type === 'string' && schema.format == 'typescript') {
12 | // Initiate a form provider
13 | var f = schemaFormProvider.stdFormObj(name, schema, options);
14 | f.key = options.path;
15 | f.type = 'typescript';
16 | // Add it to the lookup dict (for internal use)
17 | options.lookup[sfPathProvider.stringify(options.path)] = f;
18 | return f;
19 | }
20 | };
21 | // Add our default to the defaults array
22 | schemaFormProvider.defaults.string.unshift(typescript);
23 |
24 | // Second, we want it to show if someone have explicitly set the form type
25 | schemaFormDecoratorsProvider.addMapping('bootstrapDecorator', 'typescript',
26 | 'directives/decorators/bootstrap/typescript/angular-schema-form-typescript.html');
27 | }]);
28 |
29 |
30 | interface DirectiveScope extends ng.IScope {
31 | ngModel : any[];
32 | controller : typescriptController;
33 | }
34 |
35 | // Declare a controller, this is used in the typescriptDirective below
36 | class typescriptController {
37 |
38 | directiveScope : DirectiveScope;
39 |
40 | camelCase = (input:string):string => {
41 | // Turn the input value into typescript and return it.
42 | return input.toLowerCase().replace(/[- ](.)/g, function(match, group1) {
43 | return group1.toUpperCase();
44 | });
45 | };
46 |
47 | makeCamelCase = () => {
48 | // This is invoked by the ng-click
49 | // The ngModel in ASF is an array, we want to access the actual value
50 | var leaf_model = this.directiveScope.ngModel[this.directiveScope.ngModel.length - 1];
51 | if (leaf_model.$modelValue) {
52 | // If there is something to camel case, do it!
53 | leaf_model.$setViewValue(this.camelCase(leaf_model.$modelValue));
54 | };
55 | };
56 |
57 | constructor(private $scope:DirectiveScope, element:JQuery) {
58 | console.log("Initiating the process controller" + $scope.toString());
59 | $scope.controller = this
60 | this.directiveScope = $scope;
61 | }
62 | };
63 |
64 | // Create a directive to properly access the ngModel set in the view (src/angular-schema-form-typescript.html)
65 | angular.module('schemaForm').directive('typeScriptDirective', ():ng.IDirective => {
66 | return {
67 | // The directive needs the ng-model to be set, look at the
68 | require: ['ngModel'],
69 | restrict: 'A',
70 | // Do not create a isolate scope, makeCamelCase should be available to the button element
71 | scope: false,
72 | // Define a controller, use the function from above, inject the scope
73 | controller : ['$scope', typescriptController],
74 | link: function(scope: DirectiveScope, iElement, iAttrs, ngModelCtrl) {
75 | scope.ngModel = ngModelCtrl;
76 | }
77 | }
78 |
79 | });
80 |
81 |
82 |
--------------------------------------------------------------------------------
/tools/create_new_add_on.py:
--------------------------------------------------------------------------------
1 | import os
2 | import shutil
3 | import argparse
4 | from shutil import ignore_patterns
5 | from lib.mass_replace import mass_replace
6 |
7 | __author__ = 'Nicklas Boerjesson'
8 |
9 | script_dir = os.path.dirname(__file__)
10 |
11 | parser = argparse.ArgumentParser(description='Creates a new add-on with the supplied name and author',
12 | epilog="")
13 | parser.add_argument('--dest', required=False, help='Destination folder')
14 | parser.add_argument('--name', required=True, help='Project name')
15 | parser.add_argument('--author', required=True, help='The name of the author')
16 |
17 | _arguments = vars(parser.parse_args())
18 |
19 | _destination = _arguments["dest"]
20 | _add_on_name = _arguments["name"]
21 | _add_on_author = _arguments["author"]
22 |
23 | if _destination is None:
24 | _destination = os.getcwd()
25 | else:
26 | _destination = os.path.expanduser(_destination)
27 |
28 | _destination = os.path.join(_destination, _add_on_name)
29 |
30 | if os.path.exists(_destination):
31 | raise Exception("The destination already exists.")
32 |
33 | _source_folder = os.path.join(script_dir, "..", "examples", "minimal")
34 |
35 |
36 |
37 | # Copy to destination
38 | shutil.copytree(src=_source_folder, dst=_destination,
39 | ignore=ignore_patterns('bower_components', 'node_modules', "README.md"))
40 |
41 | # Add README
42 | shutil.copy(src=os.path.join(script_dir, "README_new_add_on.md"), dst=os.path.join(_destination,"README.md"))
43 |
44 | # Create needed variations of the add-on name:
45 |
46 | # First, the add-on name should only be word-separated by "-".
47 | _add_on_name = _add_on_name.replace(" ", "-").replace("_", "-")
48 |
49 | # JS names should be camelCase:d and contain no "-"
50 | _cc_tmp = ''.join(x for x in _add_on_name.title() if x.isalpha())
51 | _camelCased_add_on_name = (_cc_tmp[0].lower() + _cc_tmp[1:]).replace("-", "")
52 |
53 | # References cannot contain any "-"
54 | _references_add_on_name = _add_on_name.replace("_", "").replace("-", "")
55 |
56 | # Actually replace the strings in all the files
57 |
58 | # Replace all the capitalized Minimal mentions
59 | mass_replace(_destination, "Minimal", _add_on_name.capitalize())
60 |
61 | # Replace all the minimalForm type references minimal mentions with camelCase:d _add_on_name
62 | mass_replace(_destination, "minimalForm", _camelCased_add_on_name + "Form")
63 |
64 | # Replace all the html file references with lowercase _add_on_name
65 | mass_replace(_destination, "angular-schema-form-minimal", "angular-schema-form-" + _add_on_name.lower())
66 |
67 | # Replace all the destination_folders references with lowercase _add_on_name
68 | mass_replace(_destination, "destination_folder", _add_on_name.lower())
69 |
70 |
71 | # Replace all the remaining lowercase(references) minimal mentions
72 | mass_replace(_destination, "minimal", _references_add_on_name.lower())
73 |
74 | # Replace all the Optimal BPM mentions
75 | mass_replace(_destination, "Optimal BPM", _add_on_author)
76 |
77 | # Rename all the files
78 | shutil.move(src=os.path.join(_destination, "src", "angular-schema-form-minimal.html"),
79 | dst=os.path.join(_destination, "src", "angular-schema-form-" + _add_on_name.lower() + ".html"))
80 | shutil.move(src=os.path.join(_destination, "src", "angular-schema-form-minimal.js"),
81 | dst=os.path.join(_destination, "src", "angular-schema-form-" + _add_on_name.lower() + ".js"))
82 | shutil.move(src=os.path.join(_destination, "angular-schema-form-minimal.js"),
83 | dst=os.path.join(_destination, "angular-schema-form-" + _add_on_name.lower() + ".js"))
84 | shutil.move(src=os.path.join(_destination, "angular-schema-form-minimal.min.js"),
85 | dst=os.path.join(_destination, "angular-schema-form-" + _add_on_name.lower() + ".min.js"))
86 |
87 |
88 | print("If you want to, you can initialize the add on using these commands:")
89 | print("cd " + _destination)
90 | print("sudo npm install bower")
91 | print("node_modules/bower/bin/bower install")
92 | print("\nTo install the build tools like this:")
93 | print("sudo npm install")
94 |
--------------------------------------------------------------------------------
/examples/typescript/angular-schema-form-typescript.js:
--------------------------------------------------------------------------------
1 | angular.module("schemaForm").run(["$templateCache", function($templateCache) {$templateCache.put("directives/decorators/bootstrap/typescript/angular-schema-form-typescript.html","
{{ (hasError() && errorMessage(schemaError())) || form.description}} The some setting-setting is true for the model at $$value$$!
");}]);
2 | ///
3 | ///
4 | angular.module('schemaForm').config(['schemaFormProvider',
5 | 'schemaFormDecoratorsProvider', 'sfPathProvider',
6 | function (schemaFormProvider, schemaFormDecoratorsProvider, sfPathProvider) {
7 | // First, we want this to be the default for a combination of schema parameters
8 | var typescript = function (name, schema, options) {
9 | if (schema.type === 'string' && schema.format == 'typescript') {
10 | // Initiate a form provider
11 | var f = schemaFormProvider.stdFormObj(name, schema, options);
12 | f.key = options.path;
13 | f.type = 'typescript';
14 | // Add it to the lookup dict (for internal use)
15 | options.lookup[sfPathProvider.stringify(options.path)] = f;
16 | return f;
17 | }
18 | };
19 | // Add our default to the defaults array
20 | schemaFormProvider.defaults.string.unshift(typescript);
21 | // Second, we want it to show if someone have explicitly set the form type
22 | schemaFormDecoratorsProvider.addMapping('bootstrapDecorator', 'typescript', 'directives/decorators/bootstrap/typescript/angular-schema-form-typescript.html');
23 | }]);
24 | // Declare a controller, this is used in the typescriptDirective below
25 | var typescriptController = (function () {
26 | function typescriptController($scope, element) {
27 | var _this = this;
28 | this.$scope = $scope;
29 | this.camelCase = function (input) {
30 | // Turn the input value into typescript and return it.
31 | return input.toLowerCase().replace(/[- ](.)/g, function (match, group1) {
32 | return group1.toUpperCase();
33 | });
34 | };
35 | this.makeCamelCase = function () {
36 | // This is invoked by the ng-click
37 | // The ngModel in ASF is an array, we want to access the actual value
38 | var leaf_model = _this.directiveScope.ngModel[_this.directiveScope.ngModel.length - 1];
39 | if (leaf_model.$modelValue) {
40 | // If there is something to camel case, do it!
41 | leaf_model.$setViewValue(_this.camelCase(leaf_model.$modelValue));
42 | }
43 | ;
44 | };
45 | console.log("Initiating the process controller" + $scope.toString());
46 | $scope.controller = this;
47 | this.directiveScope = $scope;
48 | }
49 | return typescriptController;
50 | })();
51 | ;
52 | // Create a directive to properly access the ngModel set in the view (src/angular-schema-form-typescript.html)
53 | angular.module('schemaForm').directive('typeScriptDirective', function () {
54 | return {
55 | // The directive needs the ng-model to be set, look at the
56 | require: ['ngModel'],
57 | restrict: 'A',
58 | // Do not create a isolate scope, makeCamelCase should be available to the button element
59 | scope: false,
60 | // Define a controller, use the function from above, inject the scope
61 | controller: ['$scope', typescriptController],
62 | link: function (scope, iElement, iAttrs, ngModelCtrl) {
63 | scope.ngModel = ngModelCtrl;
64 | }
65 | };
66 | });
67 |
--------------------------------------------------------------------------------
/examples/camelcase/angular-schema-form-camelcase.js:
--------------------------------------------------------------------------------
1 | angular.module("schemaForm").run(["$templateCache", function($templateCache) {$templateCache.put("directives/decorators/bootstrap/camelcase/angular-schema-form-camelcase.html","\n\n\n
\n \n \n\n \n
\n \n \n \n \n
\n \n {{ (hasError() && errorMessage(schemaError())) || form.description}}\n \n \n The some setting-setting is true for the model at $$value$$!\n
\n");}]);
2 | angular.module('schemaForm').config(['schemaFormProvider',
3 | 'schemaFormDecoratorsProvider', 'sfPathProvider',
4 | function(schemaFormProvider, schemaFormDecoratorsProvider, sfPathProvider) {
5 |
6 | // First, we want this to be the default for a combination of schema parameters
7 | var camelcase = function (name, schema, options) {
8 | if (schema.type === 'string' && schema.format == 'camelcase') {
9 | // Initiate a form provider
10 | var f = schemaFormProvider.stdFormObj(name, schema, options);
11 | f.key = options.path;
12 | f.type = 'camelcase';
13 | // Add it to the lookup dict (for internal use)
14 | options.lookup[sfPathProvider.stringify(options.path)] = f;
15 | return f;
16 | }
17 | };
18 | // Add our default to the defaults array
19 | schemaFormProvider.defaults.string.unshift(camelcase);
20 |
21 | // Second, we want it to show if someone have explicitly set the form type
22 | schemaFormDecoratorsProvider.addMapping('bootstrapDecorator', 'camelcase',
23 | 'directives/decorators/bootstrap/camelcase/angular-schema-form-camelcase.html');
24 | }]);
25 |
26 |
27 | // Declare a controller, this is used in the camelcaseDirective below
28 | var camelCaseControllerFunction = function($scope) {
29 |
30 | $scope.camelCase = function (input) {
31 | // Turn the input value into camelCase and return it.
32 | return input.toLowerCase().replace(/[- ](.)/g, function(match, group1) {
33 | return group1.toUpperCase();
34 | });
35 | };
36 |
37 | $scope.makeCamelCase = function () {
38 | // This is invoked by the ng-click
39 | // The ngModel in ASF is an array, we want to access the actual value
40 | var leaf_model = $scope.ngModel[$scope.ngModel.length - 1];
41 | if (leaf_model.$modelValue) {
42 | // If there is something to camelCase, do it!
43 | leaf_model.$setViewValue($scope.camelCase(leaf_model.$modelValue));
44 | };
45 | };
46 | };
47 |
48 | // Create a directive to properly access the ngModel set in the view (src/angular-schema-form-camelcase.html)
49 | angular.module('schemaForm').directive('camelCaseDirective', function() {
50 | return {
51 | // The directive needs the ng-model to be set, look at the
52 | require: ['ngModel'],
53 | restrict: 'A',
54 | // Do not create a isolate scope, makeCamelCase should be available to the button element
55 | scope: false,
56 | // Define a controller, use the function from above, inject the scope
57 | controller : ['$scope', camelCaseControllerFunction],
58 | // Use the link function to initiate the ngModel in the controller scope
59 | link: function(scope, iElement, iAttrs, ngModelCtrl) {
60 | scope.ngModel = ngModelCtrl;
61 | }
62 | };
63 | });
64 |
--------------------------------------------------------------------------------
/documentation/extending.md:
--------------------------------------------------------------------------------
1 | Extending Angular Schema Form(ASF)
2 | =====================
3 | ASF is designed to be easily extended and there are two ways to do it:
4 |
5 | 1. Add a new field type, for example, to make add-ons like the [date picker](https://github.com/Textalk/angular-schema-form-datepicker).
6 | 2. Add a new decorator, when you need to make general behavioral changes for your application(?)
7 |
8 | *In this text, an "ASF user" does not mean an end-user, but a developer using ASF.*
9 |
10 | ## Adding a field type
11 |
12 | ### What is a field type?
13 |
14 | A ASF field type consists of the following parts:
15 |
16 | 1. A HTML template that define the UI
17 | 2. An AngularJS config file that adds the extra configuration to ASF
18 | 3. Optionally: Additional controllers and directives.
19 |
20 | The minimal configuration for implementing a new field type is 1 and 2, and is represented by the
21 | [minimal example](https://github.com/OptimalBPM/angular-schema-form-add-ons/tree/master/examples/minimal).
22 |
23 | More advanced functionality is shown in the [camelCase example](https://github.com/OptimalBPM/angular-schema-form-add-ons/tree/master/examples/camelcase)
24 |
25 | ### Creating a field type/add-on
26 |
27 | *Before you embark on creating a new field type, please read the [creating a new add-on](https://github.com/OptimalBPM/angular-schema-form-add-ons/wiki/Creating-a-new-add-on) article.*
28 |
29 | #### The HTML template
30 | The HTML template defines the UI(view) of the field type, what the user sees.
31 | The ["minimal" example](https://github.com/OptimalBPM/angular-schema-form-add-ons/blob/master/examples/minimal/src/angular-schema-form-minimal.html)
32 | shows a very basic implementation.
33 |
34 | Basically, ASF shows the template instead of the built-in UI when it encounters either a specified combination of schema types, or a "type" field type setting in the form.
35 |
36 | There is more on what the template can do later on, in the [Scope and helper functions](https://github.com/OptimalBPM/angular-schema-form-add-ons/blob/New_Extending/documentation/extending.md#Scope)-section.
37 |
38 | #### Make ASF show my field type when it is supposed to
39 |
40 | Just creating a template is not enough, ASF needs to know when to use it.
41 | ASF provides two ways to decide when to show a field type, implicitly or explicitly.
42 |
43 | To configure ASF for this, module.config is used.
44 | This document will use the [configuration of the "minimal" example](https://github.com/OptimalBPM/angular-schema-form-add-ons/blob/master/examples/minimal/src/angular-schema-form-minimal.js)
45 | to demonstrate these and try to explain it. It is recommended to open the example in another tab for reference.
46 |
47 | In it, the configuration is applied to schema form as a function definition:
48 | ```javascript
49 | angular.module('schemaForm').config(['schemaFormProvider', 'schemaFormDecoratorsProvider', 'sfPathProvider',
50 | function(schemaFormProvider, schemaFormDecoratorsProvider, sfPathProvider) {
51 |
52 | // Default mappings goes in here..
53 |
54 | // Explicit type mappings also..
55 |
56 | // Register it as a directive
57 | }]);
58 | ```
59 |
60 | So first, how to show it as as per default:
61 |
62 | ##### Implicitly, default UI for a schema field
63 |
64 | Let's assume that the schema specifies a combination of data type(not to be confused with the "type" in the form) and format that
65 | should get "our" field type as default:
66 | ```javascript
67 | minimal_format: {
68 | type: "string",
69 | format: "minimal",
70 | description: "When you edit this, it is in the add-ons input box."
71 | },
72 | ```
73 | We want our field type to be use in this situation.
74 | You achieve this by adding it to the `schemaFormProvider.defaults` object. The `schemaFormProvider.defaults`
75 | is an object with a key for each type *in JSON Schema* with a array of functions as its value.
76 |
77 | ```javascript
78 | var defaults = {
79 | string: [],
80 | object: [],
81 | number: [],
82 | integer: [],
83 | boolean: [],
84 | array: []
85 | };
86 | ```
87 |
88 | When ASF traverses the JSON Schema to create default form definitions it first checks the
89 | *JSON Schema type* and then calls on each function in the corresponding list *in order* until a
90 | function actually returns something. That is then used as a default.
91 |
92 | So, to make ASF show the "minimal" field type, a callback function is registered in the defaults array:
93 |
94 | ```javascript
95 | // First, we want this to be the default for a combination of schema parameters
96 | var minimal = function (name, schema, options) {
97 | if (schema.type === 'string' && schema.format == 'minimal') {
98 | // Initiate a form provider
99 | var f = schemaFormProvider.stdFormObj(name, schema, options);
100 | f.key = options.path;
101 | f.type = 'minimal';
102 | // Add it to the lookup dict (for internal use)
103 | options.lookup[sfPathProvider.stringify(options.path)] = f;
104 | return f;
105 | }
106 | };
107 |
108 | // Add our default to the defaults array
109 | schemaFormProvider.defaults.string.unshift(minimal);
110 | ```
111 |
112 | Now, when ASF loops the defaults-array for "string", one entry will return a form instance when the type is "string" and schema.format is "minimal".
113 | ASF will the use that form, hopefully only the "minimal"-form to display the field type template.
114 |
115 | The condition for the "minimal" field type default could be any condition, for example, if the schema.format condition was removed,
116 | all "string" type fields would get the "minimal" field type UI.
117 |
118 | ##### Explicitly specified field type
119 |
120 | The there is the case where a ASF user explicitly specifies the field type in the form definition:
121 | ```javascript
122 | {
123 | "key": "minimal_form_type",
124 | "title": "Example of minimal editor via form type",
125 | "type": "minimal"
126 | }
127 | ```
128 |
129 | To show a field type when the type is specified, the field type has to be registered.
130 | That mapping is then made like this:
131 | ```javascript
132 | schemaFormDecoratorsProvider.addMapping('bootstrapDecorator', 'minimal',
133 | 'directives/decorators/bootstrap/minimal/angular-schema-form-minimal.html');
134 | ```
135 |
136 | The first argument is the name of the decorator, usually `bootstrapDecorator`. Use that unless you know what you are doing.
137 | The second argument is the name of your new form type, in this case `minimal`
138 | The third is the template we bind to it.
139 |
140 | *Note: The createDirective step has been deprecated and is no longer necessary*
141 |
142 | At this stage, we might have a working add-on. However, normally, the template needs to be developed further:
143 |
144 | ### Scope and helper functions
145 |
146 | It is up to the template to use directives, controllers and any other angular trick to implement whatever it want to implement.
147 |
148 | Each form field will be rendered inside a decorator directive, created by the
149 | `schemaFormDecorators` factory service, *do*
150 | [check the source](https://github.com/Textalk/angular-schema-form/blob/master/src/services/decorators.js#L33).
151 |
152 | This means you have several helper functions and values on scope, most important of them, `form`. The
153 | `form` variable contains the merged form definition for that field, i.e. your supplied form object +
154 | the defaults from the schema (it also has its part of the schema under *form.schema*).
155 | This is how you define and use new form field options, whatever is set on the form object is
156 | available here for you to act on.
157 |
158 | | Name | What it does |
159 | |----------|----------------|
160 | | form | Form definition object |
161 | | showTitle() | Shorthand for `form && form.notitle !== true && form.title` |
162 | | ngModel | The ngModel controller, this will be on scope if you use either the directive `schema-validate` or `sf-array` |
163 | | evalInScope(expr, locals) | Eval supplied expression, ie scope.$eval |
164 | | evalExpr(expr, locals) | Eval an expression in the parent scope of the main `sf-schema` directive. |
165 | | interp(expr, locals) | Interpolate an expression which may or may not contain expression `{{ }}` sequences |
166 | | buttonClick($event, form) | Use this with ng-click to execute form.onClick |
167 | | hasSuccess() | Shorthand for `ngModel.$valid && (!ngModel.$pristine || !ngModel.$isEmpty(ngModel.$modelValue))` |
168 | | hasError() | Shorthand for `ngModel.$invalid && !ngModel.$pristine` |
169 |
170 | ### The magic $$value$$
171 | ASF wants to play nice with the built in Angular directives for form.
172 |
173 | Especially `ng-model`, which we want to handle the two way binding against our model value. Also by using `ng-model` we
174 | get all the nice validation states from the `ngModelController` and `FormController` that we all
175 | know and love.
176 |
177 | To get that working properly we had to resort to a bit of trickery, right before we let Angular
178 | compile the field template we do a simple string replacement of `$$value$$` and replace that
179 | with the path to the current form field on the model, i.e. `form.key`.
180 |
181 | So `ng-model="$$value$$"` becomes something like `ng-model="model['person']['address']['street']"`,
182 | you can see this if you inspect the final form in the browser.
183 |
184 | *Hint: The [camelCase example demo](http://demo.optimalbpm.se/angular-schema-form-add-ons/examples/camelcase/example.html) actually prints out the value of $$value$$ in the second field.*
185 |
186 | So basically, you always have a `ng-model="$$value$$"` (Pro tip: ng-model is fine on any element, put
187 | it on the same div as your custom directive and require the ngModelController for full control).
188 |
189 | #### Deprecation warning
190 | There is still a `errorMessage` function on scope but it's been deprecated. Please use the
191 | `sf-message` directive instead.
192 |
193 | ### schema-validate directive
194 | `schema-validate` is a directive that you should put on the same element as your `ng-model`. It is
195 | responsible for validating the value against the schema using [tv4js](https://github.com/geraintluff/tv4)
196 | It takes the form definition as an argument.
197 |
198 |
199 | ### sf-message directive
200 | Error messages are nice, and the best way to get them is via the `sf-message` directive. It usually
201 | takes `form.description` as an argument so it can show that until an error occurs.
202 |
203 |
204 | ### Sharing your add-on with the world
205 |
206 | If you now have a working add-on, it is time to share it with the rest of us.
207 |
208 | The [publishing the add-on](https://github.com/OptimalBPM/angular-schema-form-add-ons/wiki/Publishing-the-add-on) article details how this is done.
209 |
210 |
211 | Decorators
212 | ----------
213 | Decorators are a second way to extend Schema Form, the thought being that you should easily be able
214 | to change *every* field. Maybe you like it old school and want to use bootstrap 2. Or maybe you like
215 | to generate a table with the data instead? Right now there are no other decorators than bootstrap 3.
216 |
217 | Basically a *decorator* sets up all the mappings between form types and their respective templates
218 | using the `schemaFormDecoratorsProvider.createDecorator()` function.
219 |
220 | ```javascript
221 | var base = 'directives/decorators/bootstrap/';
222 |
223 | schemaFormDecoratorsProvider.createDecorator('bootstrapDecorator', {
224 | textarea: base + 'textarea.html',
225 | fieldset: base + 'fieldset.html',
226 | array: base + 'array.html',
227 | tabarray: base + 'tabarray.html',
228 | tabs: base + 'tabs.html',
229 | section: base + 'section.html',
230 | conditional: base + 'section.html',
231 | actions: base + 'actions.html',
232 | select: base + 'select.html',
233 | checkbox: base + 'checkbox.html',
234 | checkboxes: base + 'checkboxes.html',
235 | number: base + 'default.html',
236 | password: base + 'default.html',
237 | submit: base + 'submit.html',
238 | button: base + 'submit.html',
239 | radios: base + 'radios.html',
240 | 'radios-inline': base + 'radios-inline.html',
241 | radiobuttons: base + 'radio-buttons.html',
242 | help: base + 'help.html',
243 | 'default': base + 'default.html'
244 | }, [
245 | function(form) {
246 | if (form.readonly && form.key && form.type !== 'fieldset') {
247 | return base + 'readonly.html';
248 | }
249 | }
250 | ]);
251 | ```
252 | `schemaFormDecoratorsProvider.createDecorator(name, mapping, rules)` takes a name argument, a mapping object
253 | (type -> template) and an optional list of rule functions.
254 |
255 | When the decorator is trying to match a form type against a tempate it first executes all the rules
256 | in order. If one returns that is used as template, otherwise it checks the mappings.
257 |
--------------------------------------------------------------------------------