Forráskód Böngészése

Documentation underway

Richard Knight 6 éve
szülő
commit
3a8787a5c0

+ 247 - 46
README.md

@@ -1,71 +1,272 @@
 # NgDynaform
 
-A Dynamic Form Builder for Angular.
-
-## Field options
-
-### Common field metadata
-
-All fields support the following metadata. The missing properties will be 'filled oin' by dynaform's field-specific models, allowing forms to specifiued tersely.
-
-| Property           	| Description                                                                   	| Default / Notes                                      	|
-|--------------------	|-------------------------------------------------------------------------------	|------------------------------------------------------	|
-| name               	| The FormControl name - DERIVED AUTOMATICALLY                                  	| Derived from the key of the control's metadata object |
-| type               	| The control's type                                                              	| Text                                                 	|
-| label              	| The controls's label                                                          	| UnCamelCased and spaced version of name              	|
-| value              	| The control's initial value                                                       | Empty string                                          |
-| checkedValue       	| Value when checked*                                                           	| Checkboxes / Checkbuttons only                       	|
-| default            	| Default value                                                                 	|                                                      	|
-| placeholder        	| Optional placeholder text                                                     	|                                                      	|
-| class              	| CSS classes to apply                                                          	| Single class (string) or array of classes (string[]) 	|
-| id                 	| CSS id to apply                                                               	|                                                      	|
-| disabled           	| Whether field is disbled                                                      	|                                                      	|
-| change             	| Name of function in host component to call when value changes                 	|                                                      	|
-| source             	| Location of data in model                                                      	| Same name and path. Used by model-mapper.            	|
-| before             	| Ordering instruction - move before <name of another control in group>         	|                                                      	|
-| after              	| Ordering instruction - move after <name of another control in group>          	|                                                      	|
-| validators         	| Array of validator functions - following Angular FormControl API              	|                                                      	|
-| asyncValidators    	| Array of async validator functions - following Angular FormControl API        	|                                                      	|
-| valFailureMessages 	| Validation failure messages - display appropriate message if validation fails 	|                                                      	|
-
-### Options metadata (selects, radios, checkbutton groups, etc)
-
-Oprions can be specified as an array of values, an array of [value, label] pairs, or an array of objects with the structure { value: 'VAL', label: 'My label' }. If you supply a a simple array of values, each value is used as both the value and label.
+![GearWithWrench](/Users/rk/play/ng-dynaform-clarity/src/assets/docs/GearWithWrench.png)
 
-#### Available types
+**A Dynamic Form Builder for Angular, with built in model mapper.**
+
+- Define forms with metadata, or build directly from models
+- Combine metadata with models to populate form values
+- Group related fields in containers, to any level of nesting
+- Use repeating containers to model complex arrays
+- Terse, with sensible defaults
+
+## Basic Usage
+
+Import the Dynaform module.
+
+```typescript
+import { NgModule } from '@angular/core';
+
+...
+
+import { DynaformModule } from './dynaform/dynaform.module';
+...
+
+@NgModule({
+	imports: [
+		...
+		DynaformModule
+		...
+	]
+    ...
+})
+export class AppModule { }
+
+```
+
+In any component where you want to generate a form, import andthen inject the DynaformService.
+
+```typescript
+import { Component } from '@angular/core';
+import { FormGroup } from '@angular/forms';
+import { DynaformService } from './dynaform'; // Paths may vary
+
+@Component({
+	selector: 'app-root',
+	templateUrl: './app.component.html',
+	styleUrls: ['./app.component.scss']
+})
+export class AppComponent implements OnInit {
+
+	form: FormGroup;
+	meta: StringMap<any>;
+
+    constructor(private dynaform: DynaformService) {
+    }
+
+
+```
+
+Build the form from your model, your metadata, or a combination of the two.
+
+```typescript
+ngOnInit() {
 
-* Text
-* Textarea
-* Select
-* Radio
-* Checkbox
-* Checkbutton
-* Password
-* Hidden
+	const model = { firstName: 'Olly', lastName: 'October', country: 'France' };
+    const meta = {
+        country: { type: 'select', options: ['France', 'Germany', 'Norway', 'Sweden'] }
+    }
+    
+    // Build FormGroup and Modeled Metadata
+	const { form, modeledMeta } = this.dynaform.build(model, meta);
 
-#### Example
+}
+```
+### Build strategies
+
+Dynaform supports two build strategies: MODELFISRT and METAFIRST (the default)
+
+MODELFIRST generates a form from the supplied model, and by default will ignore any metadata points that don't occur in the model.
+
+METAFIRST generates a form from the supplied metadata, and by default will ignore any data in the model that doesn't have a corresponding metadata entry.
+
+You can set the build strategy by calling `setBuildStrategy`
+
+```typescript
+this.dynaform.setBuildStrategy('MODELFIRST');
+```
+
+The behaviour of the MODELFIRST build strategy can be further modified by supplying `true` as the third parameter to `dynaform.build`, where true means "create extra fields from metadata, even when they don't occur ion the model". It's useful when the model might be incomplete.
+
+```typescript
+// Build FormGroup and Modeled Metadata, creating fields for any points mentioned in 
+// the metadata that don't occur in the model
+const { form, modeledMeta } = this.dynaform.build(model, meta);
 ```
+
+### Callbacks
+
+- Callbacks allow events inside a form to trigger functions in the host component.
+- Callbacks can be attached to buttons, and to the `change` handler of any field.
+- Callbacks are identified by a string, which maps them to a function in the host component.
+
+```typescript
+// Register callbacks (probably in ngOnInit)
+this.dynaform.register({
+	'SAYHELLO': this.sayHello,
+	'SAYCHEESE': this.sayCheese
+}, this);
+```
+
+*Then later in the component*...
+
+```typescript
+handleCallback(fnId) {
+	this.dynaform.call(fnId);
+}
+
+sayHello() {
+	alert('HELLO');
+}
+
+sayCheese() {
+	alert('CHEESE');
+}
+```
+
+
+
+## Field metadata
+
+### Common properties
+
+**All fields support the following metadata**. The missing properties will be 'filled oin' by dynaform's field-specific models, allowing forms to specifiued tersely.
+
+| Property             | Description                                                  | Default / *Notes*                                            |
+| -------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ |
+| `name`               | The FormControl name                                         | **Do not set.**<br />Derived automatically from the key of the metadata object. |
+| `type`               | The control's type                                           | Text                                                         |
+| `label`              | The controls's label                                         | *An unCamelCased and spaced version of name*                 |
+| `value`              | The control's initial value                                  | *Empty string. May be set from model, overriding the default* |
+| `checkedValue`       | Value when checked*                                          | *Checkboxes / Checkbuttons only*                             |
+| `default`            | The control's default value                                  |                                                              |
+| `placeholder`        | Optional placeholder text                                    |                                                              |
+| `class`              | CSS class(es) to apply                                       | *Single class (string) or array of classes (string[])*       |
+| `id`                 | CSS id to apply                                              |                                                              |
+| `disabled`           | Whether field is disbled                                     | false                                                        |
+| `change`             | Name of function in host component to call when value changes |                                                              |
+| `source`             | Location of data in model                                    | *Defaults to the same name and path. Used by model-mapper.*  |
+| `before`             | Ordering instruction - move before *name of another control in group* |                                                              |
+| `after`              | Ordering instruction - move after *name of another control in group* |                                                              |
+| `validators`         | Array of validator functions - following Angular FormControl API | []                                                           |
+| `asyncValidators`    | Array of async validator functions - following Angular FormControl API | []                                                           |
+| `valFailureMessages` | Validation failure messages - used to display appropriate message if validation fails |                                                              |
+
+#### Available types
+
+- Text
+- Textarea
+- Select
+- Radio
+- Checkbox
+- Checkbutton
+- Password
+- Hidden
+- Checkbox
+- CheckboxGroup
+- Datepicker
+- Timepicker
+- DropdownModifiedInput
+- Multiline
+
+### 'Option' field metadata
+
+ *(for selects, radios, checkbutton groups, etc)*
+
+**Options can be specified as an array of values, an array of [value, label] pairs, or an array of objects with the structure { value: 'VAL', label: 'My label' }.** If you supply a a simple array of values, each value is used as both the value and label.
+
+#### Examples
+```typescript
 {
 	firstName: {},
 	lastName: {},
 	telephoneNumber: {},
-	country: { type: 'select', options: ['France', 'Germany', 'Italy', 'Norway', 'Spain', 'UK'] }
+	country: { type: 'select', options: ['France', 'Germany', 'Italy', 'Norway'] }
 }
 ```
 
+```typescript
+{
+	cheeseLover: { type: 'checkbox', label: 'Do you like cheese?' },
+	favouriteCheese: {
+		type: 'radio',
+		label: 'What`s your favourite?',
+		options: [
+			['CHED', 'Cheddar'],
+			['WENS', 'Wensleydale'],
+			['BRIE', 'Brie'],
+			['GORG', 'Gorgonzola']
+		]
+	}
+}
+```
 
-## Grouping related controls using containers
+### Field-type specific metadata
+
+TO ADD.
 
-Related cpontrols can be grouped in containers.
+e.g. radio, horizontal.
 
-### Seeding groups with shared options
+## Containers
 
-### Repeating groups
+**Related fields can be grouped using containers.** A container has it's own `meta` property, under which the fields it contains are defined in the usual way. Containers can even contain other containers, with no hard limit on depth, although in practice you'll probably not need to use deeply nested metadata.
+
+*cheeseMakersContract and cheeseMakersAddress are both containers...*
+
+```typescript
+{
+	optIn: { label: 'Opt in?, 'type: 'checkbutton' },
+	optInConfirm: { label: 'Really?', type: 'radio', options: ['Yes', 'No', 'Maybe'] },
+	cheeseMakersContract: {
+		label: 'Contract details',
+        meta: {
+			type: { label: 'Contract type' },
+			startDate: { type: 'datepicker' }
+            cheeseMakersAddress: {
+                label: 'Address'
+                meta: {
+                    address1: {},
+                    address2: {},
+                    city: {},
+                    postcode: { class: 'short-field' }
+                }
+            }
+		}
+	}
+};
+```
+
+### Container options
+
+| Property   | Description                                                  | Default / *Notes*                                            |
+| ---------- | ------------------------------------------------------------ | ------------------------------------------------------------ |
+| `name`     | The FormGroup name                                           | **Do not set.**<br />Derived automatically from the key of the metadata object. |
+| `label`    | Optional container label                                     | *Creates a heading above the container*                      |
+| `seed`     | An object containing key-value pairs, used to seed metadata for all contained fields | *Use when all or most contained fields share certain properties, e.g. to apply the same `class` or `default`* |
+| `template` | Optional template override                                   | *This should be an Angular `TemplateRef`<br />See https://angular.io/api/core/TemplateRef* |
+
+### Seeding containers with shared options
+
+TO ADD.
+
+## Repeating Containers
+
+TO ADD.
+
+## Buttons
+
+TO ADD.
+
+## Presentational types
+
+TO ADD.
 
 ## The built-in model mapper
 
 TO ADD.
 
+## Programatically updating displayed form values
 
+TO ADD.
 
 

+ 2 - 0
src/app/dynaform/services/_formdata-utils.ts

@@ -26,6 +26,7 @@ import { FormBuilder, FormGroup, FormArray, FormControl, AbstractControlOptions
 import { cloneDeep, omit, reduce } from 'lodash/fp';
 import * as fmdModels from '../models/field.model';
 
+
 // ---------------------------------------------------------------------------------------------------------------------
 // AutoMeta: Generate Automatic Metadata from a model
 // ---------------------------------------------------------------------------------------------------------------------
@@ -223,6 +224,7 @@ const buildFieldSpecificMetaInClosure = (metaG, context) => {
 	return buildFieldSpecificMeta(metaG);
 }
 
+
 // ---------------------------------------------------------------------------------------------------------------------
 // Generate mapping from source attributes
 // (used to grab data from model when using METAFIRST form generation)

+ 0 - 1
src/app/dynaform/services/dynaform.service.ts

@@ -99,7 +99,6 @@ import {
 	autoMeta, combineModelWithMeta, combineExtraMeta, execMetaReorderingInstructions,
 	buildFieldSpecificMetaInClosure, extractFieldMappings, buildFormGroupFunctionFactory, generateNewModel
 } from './_formdata-utils';
-import { formArrayNameProvider } from '@angular/forms/src/directives/reactive_directives/form_group_name';
 
 export interface IFormAndMeta {
 	form: FormGroup;

BIN
src/assets/docs/GearWithWrench.png