Skip to content

Commit cbdcdef

Browse files
committed
Documentation update for customisation and add-ons
1 parent 8a3088b commit cbdcdef

File tree

2 files changed

+220
-102
lines changed

2 files changed

+220
-102
lines changed

docs/extending.md

Lines changed: 132 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,38 @@
11
Extending Schema Form
22
=====================
3+
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
4+
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
5+
6+
7+
- [Overview](#overview)
8+
- [How the form is built](#how-the-form-is-built)
9+
- [The actual building](#the-actual-building)
10+
- [Creating an add-on](#creating-an-add-on)
11+
- [The Template](#the-template)
12+
- [Compile template](#compile-template)
13+
- [Builder functions](#builder-functions)
14+
- [Application of builder functions](#application-of-builder-functions)
15+
- [Defining a decorator](#defining-a-decorator)
16+
- [Setting up schema defaults](#setting-up-schema-defaults)
17+
- [Sharing your add-on with the world](#sharing-your-add-on-with-the-world)
18+
- [The builders](#the-builders)
19+
- [builders.sfField](#builderssffield)
20+
- [builders.condition](#builderscondition)
21+
- [builder.ngModel](#builderngmodel)
22+
- [sf-field-model](#sf-field-model)
23+
- [sf-field-model="attribute name"](#sf-field-modelattribute-name)
24+
- [sf-field-model="replaceAll"](#sf-field-modelreplaceall)
25+
- [builders.ngModelOptions](#buildersngmodeloptions)
26+
- [builder.simpleTransclusion](#buildersimpletransclusion)
27+
- [Useful directives](#useful-directives)
28+
- [sf-field](#sf-field)
29+
- [What's on the scope?](#whats-on-the-scope)
30+
- [Deprecation warning](#deprecation-warning)
31+
32+
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
33+
34+
Overview
35+
--------
336

437
Schema Form is designed to be easily extended. You can add your own custom fields or completely
538
change the how the entire form is rendered.
@@ -102,14 +135,55 @@ Basic template example:
102135
</div>
103136
```
104137

105-
**BIG FAT CAVEAT**
106-
Ok, so currently there is something really ugly here. The bootstrap (and material) decorator uses
138+
#### Compile template
139+
Currently there is something of a nuisance here. The bootstrap (and material) decorator use
107140
a build step (gulp-angular-templatecache) to "compile" the template into a javascript file that
108-
basically chucks the template into `$templateCache`. Currently schema form does *not* support
109-
loading the templates any other way. They need to be in `$templateCache` when rendering.
141+
adds the template into `$templateCache`. Currently schema form does *not* support
142+
loading the templates any other way. **They need to be in `$templateCache` when rendering**.
110143

111-
This is really ugly and will be fixed. But you have been warned!
144+
We strongly recommend using the yeoman generator for creating add-ons https://github.com/json-schema-form/generator-angular-schema-form-add-on
112145

146+
#### Builder functions
147+
A more detailed description of the built in builders can be found below, however this section
148+
describes how you can add your own builder to process your template as it is inserted into the
149+
schema-form output.
150+
151+
A builder function takes an `args` object containing
152+
- fieldFrag - a document fragment for manipulating prior to its insertion into the form
153+
- form - The currently processing form definition
154+
- lookup - A reference list for items added already
155+
- state - Any behaviour or defaults being passed from parents
156+
- path - The path to the form definition
157+
- build - A build function used for building child elements from a form definition
158+
159+
The below builder looks up a `textarea` element and sets a md-maxlength attribute
160+
```javascript
161+
function textareaBuilder(args) {
162+
var textareaFrag = args.fieldFrag.querySelector('textarea');
163+
var maxLength = args.form.maxlength || false;
164+
if (textareaFrag && maxLength) {
165+
textareaFrag.setAttribute('md-maxlength', maxLength);
166+
};
167+
};
168+
```
169+
170+
#### Application of builder functions
171+
To make your add-on use the builder it must be in the array of builders in the decorator definition.
172+
173+
To update the previous example to add my builder, since `sfBuilderProvider.stdBuilders` is an
174+
array I can simply add `.concat(textarea)` as below:
175+
```js
176+
angular.module('myAddOnModule', ['schemaForm']).config(function(schemaFormDecoratorsProvider, sfBuilderProvider) {
177+
178+
schemaFormDecoratorsProvider.defineAddOn(
179+
'bootstrapDecorator', // Name of the decorator you want to add to.
180+
'awesome', // Form type that should render this add-on
181+
'templates/my/addon.html', // Template name in $templateCache
182+
sfBuilderProvider.stdBuilders.concat(textarea) // List of builder functions to apply.
183+
);
184+
185+
});
186+
```
113187

114188
Defining a decorator
115189
--------------------
@@ -190,25 +264,25 @@ So [make a bower package](http://bower.io/docs/creating-packages/), add the keyw
190264

191265
The builders
192266
------------
193-
A collection of useful builders that cover most cases are in the `sfBuilder` service and is accessable
194-
both from the provider and the service on the property `builders`. There is also a list of "standard"
195-
builders, when in doubt use those.
267+
A collection of useful builders that cover most cases are in the `sfBuilder` service and is accessable
268+
both from the provider and the service on the property `builders`. There is also a list of "standard"
269+
builders, when in doubt use those.
196270

197271
```js
198272
angular.module('myMod').config(function(sfBuildersProvider) {
199273

200274
// Standard builders
201275
sfBuildersProvider.stdBuilders;
202-
203-
// All builders
276+
277+
// All builders
204278
sfBuildersProvider.builders.sfField;
205279
sfBuildersProvider.builders.condition;
206-
sfBuildersProvider.builders.ngModel;
280+
sfBuildersProvider.builders.ngModel;
207281
sfBuildersProvider.builders.ngModelOptions;
208282
sfBuildersProvider.builders.simpleTransclusion;
209283
sfBuildersProvider.builders.transclusion;
210284
sfBuildersProvider.builders.array;
211-
285+
212286
});
213287
```
214288

@@ -224,32 +298,31 @@ var stdBuilders = [
224298

225299

226300
### builders.sfField
227-
The `sfField` builder adds the `sf-field="..."` directive to *the first child element* in the template,
301+
The `sfField` builder adds the `sf-field="..."` directive to *the first child element* in the template,
228302
giving it a correct value. The value is an id number that identifies that specific form object.
229303

230-
The `sf-field` directive exports the form definition object as `form` on scope and as a lot of useful functions.
304+
The `sf-field` directive exports the form definition object as `form` on scope and as a lot of useful functions.
231305

232-
As a rule of thumb you always want this builder.
306+
As a rule of thumb you always want this builder.
233307

234308
### builders.condition
235-
The `condition` builder checks the form definition for the option `condition`. If it's present it adds a
309+
The `condition` builder checks the form definition for the option `condition`. If it's present it adds a
236310
`ng-if` to all top level elements in the template.
237311

238312
You usually want this as well.
239313

240-
### builder.ngModel
314+
### builder.ngModel
241315
The `ngModel` builder is maybe the most important builder. It makes sure you get a proper binding to
242-
your model value.
316+
your model value.
243317

244-
The `ngModel` builder queries the DOM of the template for all elements that have the attribute `sf-field-model`. Your template may have several of them. `sf-field-model` is *not* a directive,
318+
The `ngModel` builder queries the DOM of the template for all elements that have the attribute `sf-field-model`. Your template may have several of them. `sf-field-model` is *not* a directive,
245319
but depending on it's value the `ngModel` builder will take three different actions.
246320

247-
248-
#### sf-field-model
249-
Just `sf-field-model` or `sf-field-model=""` tells the builder to add a `ng-model` directive to this element.
321+
#### sf-field-model
322+
Just `sf-field-model` or `sf-field-model=""` tells the builder to add a `ng-model` directive to this element.
250323
This is a common use case.
251324

252-
Ex:
325+
Ex:
253326
DOM before `ngModel` builder:
254327
```html
255328
<div>
@@ -263,11 +336,11 @@ DOM after `ngModel` builder:
263336
</div>
264337
```
265338

266-
#### sf-field-model="<attribute name>"
267-
Given a value the `ngModel` builder will treat that value as a *attribute name* and instead of slapping
339+
#### sf-field-model="attribute name"
340+
Given a value the `ngModel` builder will treat that value as a *attribute name* and instead of slapping
268341
on a `ng-model` set the specified attributes value. It sets it to the same value as the `ng-model` would have gotten.
269342

270-
Ex:
343+
Ex:
271344
DOM before `ngModel` builder:
272345
```html
273346
<div sf-field-model="my-directive">
@@ -283,13 +356,13 @@ DOM after `ngModel` builder:
283356

284357
#### sf-field-model="replaceAll"
285358
With the special value *replaceAll* the `ngModel` builder will instead loop over every attribute on the
286-
element and do a string replacement of `"$$value$$"` with the proper model value.
359+
element and do a string replacement of `"$$value$$"` with the proper model value.
287360

288-
Ex:
361+
Ex:
289362
DOM before `ngModel` builder:
290363
```html
291364
<div>
292-
<input sf-field-model="replaceAll"
365+
<input sf-field-model="replaceAll"
293366
ng-model="$$value$$"
294367
ng-class="{'large': $$value$$.length > 10}"
295368
type="text">
@@ -298,7 +371,7 @@ DOM before `ngModel` builder:
298371
DOM after `ngModel` builder:
299372
```html
300373
<div>
301-
<input sf-field-model="replaceAll"
374+
<input sf-field-model="replaceAll"
302375
ng-model="model['name']"
303376
ng-class="{'large': model[name].length > 10}"
304377
type="text">
@@ -307,7 +380,7 @@ DOM after `ngModel` builder:
307380

308381
### builders.ngModelOptions
309382
If the form definition has a `ngModelOptions` option specified this builder will slap on a `ng-model-options`
310-
attribute to *the first child element* in the template.
383+
attribute to *the first child element* in the template.
311384

312385

313386
### builder.simpleTransclusion
@@ -317,4 +390,31 @@ is simple because it only appends children to the first child element and only c
317390

318391
Useful directives
319392
-----------------
320-
TODO: more in depth about schema-validate, sf-messages and sf-field
393+
394+
### sf-field
395+
sfField is the directive that adds scope to the template
396+
397+
#### What's on the scope?
398+
You have several helper functions and values on the scope, most important of this `form`. The
399+
`form` variable contains the merged form definition for that field, i.e. your supplied form object +
400+
the defaults from the schema (it also has its part of the schema under *form.schema*).
401+
This is how you define and use new form field options, whatever is set on the form object is
402+
available here for you to act on.
403+
404+
| Name | What it does |
405+
|----------|----------------|
406+
| form | Form definition object |
407+
| showTitle() | Shorthand for `form && form.notitle !== true && form.title` |
408+
| ngModel | The ngModel controller, this will be on scope if you use either the directive `schema-validate` or `sf-array` |
409+
| evalInScope(expr, locals) | Eval supplied expression, ie scope.$eval |
410+
| evalExpr(expr, locals) | Eval an expression in the parent scope of the main `sf-schema` directive. |
411+
| interp(expr, locals) | Interpolate an expression which may or may not contain expression `{{ }}` sequences |
412+
| buttonClick($event, form) | Use this with ng-click to execute form.onClick |
413+
| hasSuccess() | Shorthand for is valid and either not pristine or the model value is not empty |
414+
| hasError() | Shorthand for is invalid and not pristine |
415+
416+
#### Deprecation warning
417+
There is still a `errorMessage` function on scope but it's been deprecated. Please use the
418+
`sf-message` directive instead.
419+
420+
TODO: more in depth about schema-validate and sf-messages

0 commit comments

Comments
 (0)