forms-angular 0.12.0-beta.21 → 0.12.0-beta.211

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,15 +1,57 @@
1
1
  declare module fng {
2
- var formsAngular: angular.IModule;
2
+ export interface IFng extends angular.IModule {
3
+ beforeProcess?: (scope: IFormScope, cb: (err?: Error) => void) => void;
4
+ title?: { prefix?: string; suffix?: string };
5
+ // when provided, the named function (assumed to be present on $rootscope) will be used to determine the visibility
6
+ // of menu items and control groups
7
+ hiddenSecurityFuncName?: string;
8
+ // when provided, the named function (assumed to be present on $rootscope) will be used to determine the disabled
9
+ // state of menu items and individual form input controls
10
+ disabledSecurityFuncName?: string;
11
+ // when provided, the named function (assumed to be present on $rootscope) will be called each time a new page
12
+ // or popup is accessed, providing the host app with the opportunity to confirm whether there are ANY hidden elements
13
+ // at all on that page. where there are not, we can optimise by skipping logic relating to DOM element visibility.
14
+ skipHiddenSecurityFuncName?: string;
15
+ // when provided, the named function (assumed to be present on $rootscope) will be called each time a new page
16
+ // or popup is accessed, providing the host app with the opportunity to confirm whether there are ANY disabled elements
17
+ // at all on that page. where there are not, we can optimise by skipping logic relating to disabling DOM elements.
18
+ skipDisabledSecurityFuncName?: string;
19
+ // when provided, the named function (assumed to be present on $rootscope) will be called each time a new page
20
+ // or popup is accessed, providing the host app with the opportunity to confirm whether there are ANY elements on that
21
+ // page that require their child elements to be disabled. where there are not, we can optimise by skipping
22
+ // disabled ancestor checks.
23
+ skipDisabledAncestorSecurityFuncName?: string;
24
+ // how the function identified by elemSecurityFuncName should be bound. "instant" means that it will be called
25
+ // as the markup is being constructed, with 'hidden' elements not included in the markup at all, and disable elements
26
+ // given a simple DISABLED attribute. this is the most efficient approach. "one-time" will add ng-hide and
27
+ // ng-disabled directives to the relevant elements, with one-time binding to the security function. this is
28
+ // also reasonably efficient (but not as efficient as "instant" due to the need for watches). "normal" will not use
29
+ // one-time binding, which has the potential to be highly resource-intensive on large forms. which
30
+ // option is chosen will depend upon when the function identified by elemSecurityFuncName will be ready to
31
+ // make the necessary determination.
32
+ elemSecurityFuncBinding?: "instant" | "one-time" | "normal";
33
+ hideableAttr?: string; // an attribute to mark all elements that can be hidden using security
34
+ disableableAttr?: string; // an attribute to mark all elements that can be disabled using security
35
+ disableableAncestorAttr?: string; // an attribute to mark all elements whose children can all be disabled using "disabled + children" security
36
+ // if an element's id is a partial match on any of this array's contents, it will never be marked with hideableAttr/disableableAttr
37
+ ignoreIdsForHideableOrDisableableAttrs?: string[];
38
+ }
39
+ var formsAngular: IFng;
3
40
 
4
41
  /*
5
42
  Type definitions for types that are used on both the client and the server
6
43
  */
44
+ type formStyle = "inline" | "vertical" | "horizontal" | "horizontalCompact" | "stacked";
7
45
 
8
- export interface IFngLookupReference {
9
- type: 'lookup';
10
- collection: string
46
+ export interface IBaseArrayLookupReference {
47
+ property: string;
48
+ value: string;
11
49
  }
12
50
 
51
+ interface ILookupItem {
52
+ id: string;
53
+ text: string;
54
+ }
13
55
  /*
14
56
  IInternalLookupreference makes it possible to look up from a list (of key / value pairs) in the current record. For example
15
57
 
@@ -20,13 +62,11 @@ declare module fng {
20
62
  var ESchema = new Schema({
21
63
  warehouse_name: {type: String, list: {}},
22
64
  shelves: {type: [ShelfSchema]},
23
- favouriteShelf: {type: Schema.Types.ObjectId, ref: {type: 'internal', property: 'shelves', value:'location'};
65
+ favouriteShelf: {type: Schema.Types.ObjectId, internalRef: {property: 'shelves', value:'location'};
24
66
  });
25
67
  */
26
- export interface IFngInternalLookupReference {
27
- type: 'internal';
28
- property: string;
29
- value: string;
68
+ export interface IFngInternalLookupReference extends IBaseArrayLookupReference {
69
+ noConvert?: boolean; // can be used by a tricksy hack to get around nesting limitations
30
70
  }
31
71
 
32
72
  /*
@@ -36,18 +76,15 @@ declare module fng {
36
76
  const LSchemaDef : IFngSchemaDefinition = {
37
77
  descriptin: {type: String, required: true, list: {}},
38
78
  warehouse: {type: Schema.Types.ObjectId, ref:'k_referencing_self_collection', form: {directive: 'fng-ui-select', fngUiSelect: {fngAjax: true}}},
39
- shelf: {type: Schema.Types.ObjectId, ref: {type: 'lookupList', collection:'k_referencing_self_collection', id:'$warehouse', property: 'shelves', value:'location'}},
79
+ shelf: {type: Schema.Types.ObjectId, lookupListRef: {collection:'k_referencing_self_collection', id:'$warehouse', property: 'shelves', value:'location'}},
40
80
  };
41
81
  */
42
- export interface IFngLookupListReference {
43
- type: 'lookupList';
44
- collection: string; // collection that contains the list
82
+ export interface IFngLookupListReference extends IBaseArrayLookupReference {
83
+ collection: string; // collection that contains the list
45
84
  /*
46
85
  Some means of calculating _id in collection. If it starts with $ then it is property in record
47
86
  */
48
87
  id: string;
49
- property: string;
50
- value: string;
51
88
  }
52
89
 
53
90
  /*
@@ -66,7 +103,7 @@ declare module fng {
66
103
  */
67
104
  export interface IFngShowWhen {
68
105
  lhs: any;
69
- comp: 'eq' | 'ne' | 'gt' | 'gte' | 'lt' | 'lte';
106
+ comp: "eq" | "ne" | "gt" | "gte" | "lt" | "lte";
70
107
  rhs: any;
71
108
  }
72
109
 
@@ -74,11 +111,15 @@ declare module fng {
74
111
  link allows the setting up of hyperlinks for lookup reference fields
75
112
  */
76
113
  export interface IFngLinkSetup {
77
- linkOnly?: boolean; // if true (which at the time of writing is the only option supported) then the input element is not generated.
78
- form?: string; // can be used to generate a link to a custom schema
79
- text?: string; // the literal value used for the link. If this property is omitted then text is generated from the field values of the document referred to by the link.
114
+ linkOnly?: boolean; // if true then the input element is not generated (this overrides label)
115
+ label?: boolean; // Make a link out of the label (causes text to be overridden) (this overrides text)
116
+ form?: string; // can be used to generate a link to a custom schema
117
+ linktab?: string; // can be used to generate a link to a tab on a form
118
+ text?: string; // the literal value used for the link. If this property is omitted then text is generated from the field values of the document referred to by the link.
80
119
  }
81
120
 
121
+ export type FieldSizeString = "mini" | "small" | "medium" | "large" | "xlarge" | "xxlarge" | "block-level"; // sets control width. Default is 'medium''
122
+
82
123
  export interface IFngSchemaTypeFormOpts {
83
124
  /*
84
125
  The input type to be generated - which must be compatible with the Mongoose type.
@@ -97,33 +138,36 @@ declare module fng {
97
138
  */
98
139
  type?: string;
99
140
 
100
- hidden?: boolean; // inhibits this schema key from appearing on the generated form.
101
- label?: string | null; // overrides the default input label. label:null suppresses the label altogether.
102
- ref?: IFngLookupReference | IFngInternalLookupReference;
103
-
141
+ hidden?: boolean; // inhibits this schema key from appearing on the generated form.
142
+ label?: string | null; // overrides the default input label. label:null suppresses the label altogether.
143
+ ref?: string; // reference to another collection
144
+ internalRef?: IFngInternalLookupReference;
145
+ lookupListRef?: IFngLookupListReference;
104
146
  id?: string; // specifies the id of the input field (which defaults to f_name)
105
147
 
106
- placeHolder?: string // adds placeholder text to the input (depending on data type).
107
- help?: string; // adds help text under the input.
108
- helpInline?: string; // adds help to the right of the input.
109
- popup?: string; // adds popup help as specified.
110
- order?: number; // allows user to specify the order / tab order of this field in the form. This overrides the position in the Mongoose schema.
111
- size?: 'mini' | 'small' | 'medium' | 'large' | 'xlarge' | 'xxlarge' | 'block-level'; // sets control width. Default is 'medium''
112
- readonly?: boolean; // adds the readonly attribute to the generated input (currently doesn't work with date - and perhaps other types).
113
- rows?: number | 'auto'; // sets the number of rows in inputs (such as textarea) that support this. Setting rows to "auto" makes the textarea expand to fit the content, rather than create a scrollbar.
114
- tab?: string; // Used to divide a large form up into a tabset with multiple tabs
115
- showWhen?: IFngShowWhen | string; // allows conditional display of fields based on values elsewhere. string must be an abular expression.
148
+ placeHolder?: string; // adds placeholder text to the input (depending on data type).
149
+ help?: string; // adds help text under the input.
150
+ helpInline?: string; // adds help to the right of the input.
151
+ popup?: string; // adds title (popup help) as specified.
152
+ ariaLabel?: string; // adds aria-label as specified.
153
+ order?: number; // allows user to specify the order / tab order of this field in the form. This overrides the position in the Mongoose schema.
154
+ size?: FieldSizeString;
155
+ readonly?: boolean | string; // adds the readonly or ng-readonly attribute to the generated input (currently doesn't work with date - and perhaps other types).
156
+ rows?: number | "auto"; // sets the number of rows in inputs (such as textarea) that support this. Setting rows to "auto" makes the textarea expand to fit the content, rather than create a scrollbar.
157
+ tab?: string; // Used to divide a large form up into a tabset with multiple tabs
158
+ showWhen?: IFngShowWhen | string; // allows conditional display of fields based on values elsewhere. string must be an abular expression.
116
159
 
117
160
  /*
118
161
  add: 'class="myClass"' allows custom styling of a specific input
119
162
  Angular model options can be used - for example add: 'ng-model-options="{updateOn: \'default blur\', debounce: { \'default\': 500, \'blur\': 0 }}" '
120
163
  custom validation directives, such as the timezone validation in this schema
121
164
  */
122
- add?: string; // allows arbitrary attributes to be added to the input tag.
165
+ add?: string; // allows arbitrary attributes to be added to the input tag.
123
166
 
124
- class?: string; // allows arbitrary classes to be added to the input tag.
125
- inlineRadio?: boolean; // (only valid when type is radio) should be set to true to present all radio button options in a single line
126
- link?: IFngLinkSetup; // handles displaying links for IFngLookupReference lookups
167
+ class?: string; // allows arbitrary classes to be added to the input tag.
168
+ inlineRadio?: boolean; // (only valid when type is radio) should be set to true to present all radio button options in a single line
169
+ link?: IFngLinkSetup; // handles displaying links for ref lookups
170
+ asText?: boolean; // (only valid when type is ObjectId) should be set to true to force a simple text input rather than a select. presumed for advanced cases where the objectid is going to be pasted in.
127
171
 
128
172
  /*
129
173
  With a select / radio type you can specify the options.
@@ -146,17 +190,35 @@ declare module fng {
146
190
  /*
147
191
  The next few options relate to the handling and display of arrays (including arrays of subdocuments)
148
192
  */
149
- noAdd?: boolean; // inhibits an Add button being generated for arrays.
193
+ noAdd?: boolean | string; // inhibits an Add button being generated for arrays.
194
+ noneIndicator?: boolean; // show "None" where there's no add button and no array items
150
195
  unshift?: boolean; // (for arrays of sub documents) puts an add button in the sub schema header which allows insertion of new sub documents at the beginning of the array.
151
- noRemove?: boolean; // inhibits a Remove button being generated for array elements.
152
- formstyle?: 'inline' | 'vertical' | 'horizontal' | 'horizontalCompact'; // (only valid on a sub schema) sets style of sub form.
153
- sortable? : boolean; // Allows drag and drop sorting of arrays - requires angular-ui-sortable
196
+ noRemove?: boolean | string; // inhibits a Remove button being generated for array elements.
197
+ formstyle?: formStyle; // (only valid on a sub schema) sets style of sub form.
198
+ sortable?: boolean | string; // Allows drag and drop sorting of arrays - requires angular-ui-sortable
199
+ ngClass?: string; // Allows for conditional per-item styling through the addition of an ng-class expression to the class list of li elements created for each item in the array
200
+ filterable?: boolean; // Add a data-ng-hide to all array elements, referring to subDoc._hidden. Does not actually (yet) provide a UI for managing this property, however (which needs to be done via an external directive)
201
+ subDocContainerType?:
202
+ | "fieldset"
203
+ | "well"
204
+ | "well-large"
205
+ | "well-small"
206
+ | string
207
+ | ((info) => { before: ""; after: "" }); // allows each element in the array to be nested in a container
208
+ subDocContainerProps?: any; // the parameters that will be passed if subDocContainerType is a function
154
209
 
155
210
  /*
156
211
  The next section relates to the display of sub documents
157
212
  */
158
213
  customSubDoc?: string; // Allows you to specify custom HTML (which may include directives) for the sub doc
214
+ customHeader?: string; // Allows you to specify custom HTML (which may include directives) for the header of a group of sub docs
159
215
  customFooter?: string; // Allows you to specify custom HTML (which may include directives) for the footer of a group of sub docs
216
+
217
+ /*
218
+ Suppresses warnings about attenpting deep nesting which would be logged to console in some circumstances when a
219
+ directive fakes deep nesting
220
+ */
221
+ suppressNestingWarning?: boolean;
160
222
  }
161
223
 
162
224
  // Schema passed from server - derived from Mongoose schema
@@ -164,83 +226,155 @@ declare module fng {
164
226
  name: string;
165
227
  schema?: Array<IFieldViewInfo>;
166
228
  array?: boolean;
167
- showIf? : any;
229
+ showIf?: any;
168
230
  required?: boolean;
169
- step? : number;
231
+ step?: number;
170
232
  }
171
233
 
234
+ export type fieldType =
235
+ | "string"
236
+ | "text"
237
+ | "textarea"
238
+ | "number"
239
+ | "select"
240
+ | "link"
241
+ | "date"
242
+ | "checkbox"
243
+ | "password"
244
+ | "radio";
245
+
172
246
  // Schema used internally on client - often derived from IFieldViewInfo passed from server
173
247
  export interface IFormInstruction extends IFieldViewInfo {
174
- id? : string; // id of generated DOM element
175
- type?: 'string' | 'text' | 'textarea' | 'number' | 'select' | 'link' | 'date' | 'checkbox' | 'password';
176
- rows? : number
177
- label: string;
248
+ id?: string; // id of generated DOM element
249
+ nonUniqueId?: string; // where this field is part of a sub-sub-schema, id is likely to include $index from the sub-schema, to ensure uniqueness. provide it here without reference to $parent.$index for use in security evaluations.
250
+ type?: fieldType;
251
+ defaultValue?: any;
252
+ rows?: number;
253
+ label?: string;
178
254
  options?: any;
179
255
  ids?: any;
180
256
  hidden?: boolean;
181
257
  tab?: string;
182
- add? : string;
183
- ref? : any;
184
- link? : any;
185
- linkText?: string;
186
- form?: string; // the form that is linked to
187
- select2? : any; // deprecated
258
+ add?: string;
259
+ ref?: any;
260
+ link?: any;
261
+ linktext?: string;
262
+ linklabel?: boolean;
263
+ form?: string; // the form that is linked to
264
+ select2?: any; // deprecated
265
+ schema?: IFormInstruction[]; // If the field is an array of fields
266
+ intType?: "date";
267
+ [directiveOptions: string]: any;
268
+ }
269
+
270
+ interface IContainerInstructions {
271
+ before?: string;
272
+ after?: string;
273
+ omit?: boolean;
188
274
  }
189
275
 
276
+ export interface IContainer {
277
+ /*
278
+ Type of container, which determines markup. This is currently only available when the schema is generated by
279
+ the client for use independent of the BaseController
280
+ In the case of a string which does not match one of the predefined options
281
+ the generated container div is given the class of the name
282
+ */
283
+ containerType: "fieldset" | "well" | "tabset" | "tab" | "well-large" | "well-small" | string | ((info: IContainer) => IContainerInstructions);
284
+ title?: string;
285
+
286
+ /*
287
+ h1...h6 will use a header style
288
+ anything else will be used as a paragraph stype
289
+ */
290
+ titleTagOrClass?: string;
291
+ content: IFormInstruction[];
292
+ }
293
+
294
+ export type IFormSchemaElement = IFormInstruction | IContainer;
295
+
296
+ export type IFormSchema = IFormSchemaElement[];
297
+ export type IControlledFormSchema = IFormInstruction[];
298
+
190
299
  export interface IEnumInstruction {
191
300
  repeat: string;
192
301
  value: string;
193
- label? : string;
302
+ label?: string;
194
303
  }
195
304
 
196
305
  export interface IFngCtrlState {
197
306
  master: any;
198
- allowLocationChange: boolean; // Do we allow location change or prompt for permission
307
+ allowLocationChange: boolean; // Do we allow location change or prompt for permission
199
308
  }
200
309
  export interface IRecordHandler {
201
- convertToMongoModel(schema: Array<IFieldViewInfo>, anObject: any, prefixLength: number, scope: IFormScope): any;
202
- createNew(dataToSave: any, options: any, scope: IFormScope): void;
203
- deleteRecord(model: any, id: any, scope: IFormScope, ctrlState: any): void;
204
- updateDocument(dataToSave : any, options: any, scope: IFormScope, ctrlState: any) : void;
310
+ convertToMongoModel(schema: IControlledFormSchema, anObject: any, prefixLength: number, scope: IFormScope): any;
311
+ createNew(dataToSave: any, options: any, scope: IFormScope, ctrlState: IFngCtrlState): void;
312
+ deleteRecord(id: string, scope: IFormScope, ctrlState: IFngCtrlState): void;
313
+ updateDocument(dataToSave: any, options: any, scope: IFormScope, ctrlState: IFngCtrlState): void;
205
314
  readRecord($scope: IFormScope, ctrlState);
206
315
  scrollTheList($scope: IFormScope);
207
- getListData($scope: IFormScope, record, fieldName, listSchema);
316
+ getListData(record, fieldName, listSchema?, $scope?: IFormScope);
208
317
  suffixCleanId(inst, suffix);
209
- setData(object, fieldname, element, value);
318
+ setData(object, fieldname: string, element, value);
319
+ getData(object, fieldname: string, element?: any);
210
320
  setUpLookupOptions(lookupCollection, schemaElement, $scope: IFormScope, ctrlState, handleSchema);
211
- setUpLookupListOptions: (ref: IFngLookupListReference, formInstructions: IFormInstruction, $scope: IFormScope, ctrlState: IFngCtrlState) => void;
321
+ setUpLookupListOptions: (
322
+ ref: IFngLookupListReference,
323
+ formInstructions: IFormInstruction,
324
+ $scope: IFormScope,
325
+ ctrlState: IFngCtrlState
326
+ ) => void;
212
327
  handleInternalLookup($scope: IFormScope, formInstructions, ref): void;
213
328
  preservePristine(element, fn): void;
214
329
  convertIdToListValue(id, idsArray, valuesArray, fname);
215
- decorateScope($scope:IFormScope, $uibModal, recordHandlerInstance : IRecordHandler, ctrlState);
216
- fillFormFromBackendCustomSchema(schema, $scope:IFormScope, formGeneratorInstance, recordHandlerInstance, ctrlState);
330
+ decorateScope($scope: IFormScope, $uibModal, recordHandlerInstance: IRecordHandler, ctrlState);
331
+ fillFormFromBackendCustomSchema(
332
+ schema,
333
+ $scope: IFormScope,
334
+ formGeneratorInstance,
335
+ recordHandlerInstance,
336
+ ctrlState
337
+ );
217
338
  fillFormWithBackendSchema($scope: IFormScope, formGeneratorInstance, recordHandlerInstance, ctrlState);
218
339
  handleError($scope: IFormScope);
219
340
  }
220
341
 
221
342
  export interface IFormGenerator {
222
- generateEditUrl(obj, $scope:IFormScope): string;
343
+ generateEditUrl(obj, $scope: IFormScope): string;
344
+ generateViewUrl(obj, $scope: IFormScope): string;
223
345
  generateNewUrl($scope: IFormScope): string;
224
346
  handleFieldType(formInstructions, mongooseType, mongooseOptions, $scope: IFormScope, ctrlState);
225
- handleSchema(description: string, source, destForm, destList, prefix, doRecursion: boolean, $scope: IFormScope, ctrlState);
347
+ handleSchema(
348
+ description: string,
349
+ source,
350
+ destForm,
351
+ destList,
352
+ prefix,
353
+ doRecursion: boolean,
354
+ $scope: IFormScope,
355
+ ctrlState
356
+ );
226
357
  updateDataDependentDisplay(curValue, oldValue, force, $scope: IFormScope);
227
- add(fieldName, $event, $scope: IFormScope);
228
- unshift(fieldName, $event, $scope: IFormScope);
229
- remove(fieldName, value, $event, $scope: IFormScope);
358
+ add(fieldName: string, $event, $scope: IFormScope, modelOverride?: any);
359
+ unshift(fieldName: string, $event, $scope: IFormScope, modelOverride?: any);
360
+ remove(fieldName: string, value, $event, $scope: IFormScope, modelOverride?: any);
230
361
  hasError(formName, name, index, $scope: IFormScope);
231
- decorateScope($scope: IFormScope, formGeneratorInstance, recordHandlerInstance: IRecordHandler, sharedStuff);
362
+ decorateScope($scope: IFormScope, formGeneratorInstance, recordHandlerInstance: IRecordHandler, sharedStuff, pseudoUrl?: string);
232
363
  }
233
364
 
234
365
  export interface IFngSingleLookupHandler {
235
366
  formInstructions: IFormInstruction;
236
367
  lastPart: string;
237
368
  possibleArray: string;
369
+ // If the looked-up record changes, we use these fields to see if the old lookup value also exists in the new lookup record
370
+ oldValue?: string | string[];
371
+ oldId?: string | string[];
238
372
  }
239
373
 
240
374
  export interface IFngLookupHandler {
241
375
  lookupOptions: string[];
242
376
  lookupIds: string[];
243
- handlers: IFngSingleLookupHandler[]
377
+ handlers: IFngSingleLookupHandler[];
244
378
  }
245
379
 
246
380
  export interface IFngInternalLookupHandlerInfo extends IFngLookupHandler {
@@ -251,16 +385,32 @@ declare module fng {
251
385
  ref: IFngLookupListReference;
252
386
  }
253
387
 
388
+ // we cannot use an enum here, so this will have to do. these are the values expected to be returned by the
389
+ // function on $rootScope with the name formsAngular.disabledSecurityFuncName.
390
+ // false = not disabled,
391
+ // true = disabled,
392
+ // "+" = this and all child elements disabled
393
+ export type DisabledOutcome = boolean | "+";
394
+
395
+ export interface ISecurableScope extends angular.IScope {
396
+ // added by ISecurityService
397
+ isSecurelyHidden: (elemId: string) => boolean;
398
+ isSecurelyDisabled: (elemId: string) => boolean;
399
+ requiresDisabledChildren: (elemId: string) => boolean;
400
+ }
401
+
254
402
  /*
255
403
  The scope which contains form data
256
404
  */
257
- export interface IFormScope extends angular.IScope {
405
+ export interface IFormScope extends ISecurableScope {
258
406
  sharedData: any;
259
- modelNameDisplay : string;
407
+ modelNameDisplay: string;
260
408
  modelName: string;
261
409
  formName: string;
262
410
  alertTitle: any;
411
+ errorVisible: boolean;
263
412
  errorMessage: any;
413
+ errorHideTimer: number;
264
414
  save: any;
265
415
  newRecord: boolean;
266
416
  initialiseNewRecord?: any;
@@ -271,17 +421,16 @@ declare module fng {
271
421
  isCancelDisabled: any;
272
422
  isNewDisabled: any;
273
423
  isSaveDisabled: any;
274
- disabledText: any;
424
+ whyDisabled: string;
275
425
  unconfirmedDelete: boolean;
276
426
  getVal: any;
277
427
  sortableOptions: any;
278
- tabDeselect: any;
279
- tabs?: Array<any>; // In the case of forms that contain a tab set
280
- tab?: string; // title of the active tab - from the route
428
+ tabs?: Array<any>; // In the case of forms that contain a tab set
429
+ tab?: string; // title of the active tab - from the route
281
430
  activeTabNo?: number;
282
- topLevelFormName: string; // The name of the form
431
+ topLevelFormName: string; // The name of the form
283
432
  record: any;
284
- originalData: any; // the unconverted data read from the server
433
+ originalData: any; // the unconverted data read from the server
285
434
  phase: any;
286
435
  disableFunctions: any;
287
436
  dataEventFunctions: any;
@@ -293,10 +442,12 @@ declare module fng {
293
442
  conversions: any;
294
443
  pageSize: any;
295
444
  pagesLoaded: any;
445
+ redirectOptions?: { redirect?: string; allowChange?: boolean };
296
446
  cancel: () => any;
297
- showError: (error: any, alertTitle? : string) => void;
447
+ showError: (error: any, alertTitle?: string) => void;
298
448
  prepareForSave: (cb: (error: string, dataToSave?: any) => void) => void;
299
- formSchema: IFormInstruction[];
449
+ setDefaults: (formSchema: IFormSchema, base?: string) => any;
450
+ formSchema: IControlledFormSchema;
300
451
  baseSchema: () => Array<any>;
301
452
  setFormDirty: any;
302
453
  add: any;
@@ -308,24 +459,46 @@ declare module fng {
308
459
  skipCols: any;
309
460
  setPristine: any;
310
461
  generateEditUrl: any;
462
+ generateViewUrl: any;
311
463
  generateNewUrl: any;
312
464
  scrollTheList: any;
313
465
  getListData: any;
314
- dismissError: any;
466
+ phaseWatcher: any;
467
+ dismissError: () => void;
468
+ stickError: () => void;
469
+ clearTimeout: () => void;
315
470
  handleHttpError: (response: any) => void;
316
471
  dropConversionWatcher: () => void;
472
+ readingRecord?: Promise<any>;
473
+ onSchemaFetch?: (description: string, source: IFieldViewInfo[]) => void;
474
+ onSchemaProcessed?: (description: string, formSchema: IFormInstruction[]) => void;
475
+ updateQueryForTab?: (tab: string) => void;
476
+ showLoading? : boolean;
477
+ tabDeselect?: ($event: any, $selectedIndex: number) => void;
478
+ setUpCustomLookupOptions?: (
479
+ schemaElement: IFormInstruction,
480
+ ids: string[],
481
+ options: string[],
482
+ baseScope: any
483
+ ) => void;
317
484
  }
318
485
 
319
486
  export interface IContextMenuDivider {
320
487
  divider: boolean;
321
488
  }
322
489
  export interface IContextMenuOption {
323
- // For it to make any sense, a menu option needs one of the next two properties
490
+ // For it to make any sense, a menu option needs one of the next three properties
324
491
  url?: string;
325
492
  fn?: () => void;
493
+ urlFunc?: () => string;
326
494
 
327
- text: string;
495
+ // provided to the security hook (see elemSecurityFuncName) - optional where that is not being used
496
+ id?: string;
497
+
498
+ text?: string;
499
+ textFunc?: () => string;
328
500
  isDisabled?: () => boolean;
501
+ isHidden?: () => boolean;
329
502
 
330
503
  // Does the option appear in the following contexts?
331
504
  listing: boolean;
@@ -334,9 +507,10 @@ declare module fng {
334
507
  }
335
508
 
336
509
  export interface IModelController extends IFormScope {
337
- onBaseCtrlReady? : (baseScope: IFormScope) => void; // Optional callback after form is instantiated
338
- onAllReady? : (baseScope: IFormScope) => void; // Optional callback after form is instantiated and populated
339
- contextMenu? : Array<IContextMenuOption | IContextMenuDivider>
510
+ onBaseCtrlReady?: (baseScope: IFormScope) => void; // Optional callback after form is instantiated
511
+ onAllReady?: (baseScope: IFormScope) => void; // Optional callback after form is instantiated and populated
512
+ contextMenu?: Array<IContextMenuOption | IContextMenuDivider>;
513
+ contextMenuPromise?: Promise<Array<IContextMenuOption | IContextMenuDivider>>;
340
514
  }
341
515
 
342
516
  export interface IBaseFormOptions {
@@ -344,13 +518,13 @@ declare module fng {
344
518
  * The style of the form layout. Supported values are horizontalcompact, horizontal, vertical, inline
345
519
  */
346
520
  //TODO supported values should be in an enum
347
- formstyle?: string;
521
+ formstyle?: formStyle;
348
522
  /**
349
523
  * Model on form scope (defaults to record).
350
524
  * <li><strong>model</strong> the object in the scope to be bound to the model controller. Specifying
351
525
  * the model inhibits the generation of the <strong>form</strong> tag unless the <strong>forceform</strong> attribute is set to true</li>
352
526
  */
353
- model? : string;
527
+ model?: string;
354
528
  /**
355
529
  * The name to be given to the form - defaults to myForm
356
530
  */
@@ -359,60 +533,163 @@ declare module fng {
359
533
  * Normally first field in a form gets autofocus set. Use this to prevent this
360
534
  */
361
535
  noautofocus?: string;
536
+ /*
537
+ Suppress the generation of element ids
538
+ (sometimes required when using nested form-inputs in a directive)
539
+ */
540
+ noid?: boolean;
362
541
  }
363
542
 
364
543
  export interface IFormAttrs extends IFormOptions, angular.IAttributes {
365
544
  /**
366
545
  * Schema used by the form
367
546
  */
368
- schema : string;
369
- forceform?: string; // Must be true or omitted. Forces generation of the <strong>form</strong> tag when model is specified
547
+ schema: string;
548
+ forceform?: string; // Must be true or omitted. Forces generation of the <strong>form</strong> tag when model is specified
549
+ noid?: boolean;
370
550
  }
371
551
 
372
552
  export interface IFormOptions extends IBaseFormOptions {
373
- schema? : string;
553
+ schema?: string;
374
554
  subkey?: string;
375
555
  subkeyno?: number;
376
- subschema? : string;
377
- subschemaroot? : string;
556
+ subschema?: string;
557
+ subschemaroot?: string;
558
+ viewform?: boolean;
559
+ suppressNestingWarning?: boolean;
378
560
  }
379
561
 
380
562
  export interface IBuiltInRoute {
381
563
  route: string;
382
564
  state: string;
383
565
  templateUrl: string;
384
- options? : any;
566
+ options?: any;
385
567
  }
386
568
 
387
569
  export interface IRoutingConfig {
388
570
  hashPrefix: string;
389
571
  html5Mode: boolean;
390
- routing: string; // What sort of routing do we want? ngroute or uirouter.
391
- // TODO Should be enum
392
- prefix: string; // How do we want to prefix out routes? If not empty string then first character must be slash (which is added if not)
393
- // for example '/db' that gets prepended to all the generated routes. This can be used to
394
- // prevent generated routes (which have a lot of parameters) from clashing with other routes in
395
- // the web app that have nothing to do with CRUD forms
572
+ routing: string; // What sort of routing do we want? ngroute or uirouter.
573
+ // TODO Should be enum
574
+ prefix: string; // How do we want to prefix out routes? If not empty string then first character must be slash (which is added if not)
575
+ // for example '/db' that gets prepended to all the generated routes. This can be used to
576
+ // prevent generated routes (which have a lot of parameters) from clashing with other routes in
577
+ // the web app that have nothing to do with CRUD forms
396
578
  fixedRoutes?: Array<IBuiltInRoute>;
397
- templateFolder?: string; // The folder where the templates for base-list, base-edit and base-analysis live. Internal templates used by default. For pre 0.7.0 behaviour use 'partials/'
398
- add2fngRoutes?: any; // An object to add to the generated routes. One use case would be to add {authenticate: true}
399
- // so that the client authenticates for certain routes
579
+ templateFolder?: string; // The folder where the templates for base-list, base-edit and base-analysis live. Internal templates used by default. For pre 0.7.0 behaviour use 'partials/'
580
+ add2fngRoutes?: any; // An object to add to the generated routes. One use case would be to add {authenticate: true}
581
+ // so that the client authenticates for certain routes
400
582
 
401
- variantsForDemoWebsite? : any; // Just for demo website
402
- variants?: any; // Just for demo website
583
+ variantsForDemoWebsite?: any; // Just for demo website
584
+ variants?: any; // Just for demo website
585
+ onDelete?: string; // Supports literal (such as '/') or 'new' (which will go to a /new of the model) default is to go to the list view
403
586
  }
404
587
 
405
588
  export interface IFngRoute {
406
- newRecord?: boolean;
407
- analyse?: boolean;
408
- modelName?: string;
409
- reportSchemaName? : string;
410
- id? : string;
411
- formName? : string;
412
- tab? : string;
413
- variant? : string; // TODO should be enum of supported frameworks
589
+ newRecord?: boolean;
590
+ analyse?: boolean;
591
+ modelName?: string;
592
+ reportSchemaName?: string;
593
+ id?: string;
594
+ formName?: string;
595
+ tab?: string;
596
+ variant?: string; // TODO should be enum of supported frameworks
414
597
  }
415
598
 
599
+ interface IBuildingBlocks {
600
+ common: string;
601
+ sizeClassBS3: string;
602
+ sizeClassBS2: string;
603
+ compactClass: string;
604
+ formControl: string;
605
+ modelString: string;
606
+ disableableAncestorStr: string;
607
+ }
608
+
609
+ interface IProcessedAttrs {
610
+ info: IFormInstruction;
611
+ options: IFormOptions;
612
+ directiveOptions: any;
613
+ }
614
+
615
+ interface IGenDisableStrParams {
616
+ forceNg?: boolean;
617
+ nonUniqueIdSuffix?: string;
618
+ }
619
+
620
+
621
+ interface IPluginHelper {
622
+ extractFromAttr: (
623
+ attr: any,
624
+ directiveName: string
625
+ ) => { info: IFormInstruction; options: IFormOptions; directiveOptions: any };
626
+ buildInputMarkup: (
627
+ scope: angular.IScope,
628
+ attrs: any,
629
+ params: {
630
+ processedAttrs?: IProcessedAttrs;
631
+ fieldInfoOverrides?: Partial<IFormInstruction>;
632
+ optionOverrides?: Partial<IFormOptions>;
633
+ addButtons?: boolean;
634
+ needsX?: boolean;
635
+ },
636
+ generateInputControl: (buildingBlocks: IBuildingBlocks) => string
637
+ ) => string;
638
+ genIdString: (scope: angular.IScope, processedAttrs: IProcessedAttrs, idSuffix: string) => string;
639
+ genDisabledStr: (
640
+ scope: angular.IScope,
641
+ processedAttrs: IProcessedAttrs,
642
+ idSuffix: string,
643
+ params?: fng.IGenDisableStrParams
644
+ ) => string;
645
+ genIdAndDisabledStr: (
646
+ scope: angular.IScope,
647
+ processedAttrs: IProcessedAttrs,
648
+ idSuffix: string,
649
+ params?: fng.IGenDisableStrParams
650
+ ) => string;
651
+ genDateTimePickerDisabledStr: (scope: angular.IScope, processedAttrs: IProcessedAttrs, idSuffix: string) => string;
652
+ genDateTimePickerIdAndDisabledStr: (
653
+ scope: angular.IScope,
654
+ processedAttrs: IProcessedAttrs,
655
+ idSuffix: string
656
+ ) => string;
657
+ genUiSelectIdAndDisabledStr: (
658
+ scope: angular.IScope,
659
+ processedAttrs: IProcessedAttrs,
660
+ idSuffix: string
661
+ ) => string;
662
+ handlePseudos: (str: string) => string;
663
+ genDisableableAncestorStr: (processedAttrs: IProcessedAttrs) => string;
664
+ }
665
+
666
+ interface ISecurityVisibility {
667
+ omit?: boolean;
668
+ visibilityAttr?: string;
669
+ }
670
+
671
+ interface IGenerateDisableAttrParams {
672
+ attr?: string;
673
+ attrRequiresValue?: boolean;
674
+ forceNg?: boolean;
675
+ }
676
+
677
+ type SecurityType = "hidden" | "disabled";
678
+
679
+ interface ISecurityService {
680
+ canDoSecurity: (type: SecurityType) => boolean;
681
+ canDoSecurityNow: (scope: fng.ISecurableScope, type: SecurityType) => boolean;
682
+ isSecurelyHidden: (elemId: string, pseudoUrl?: string) => boolean;
683
+ isSecurelyDisabled: (elemId: string, pseudoUrl?: string) => boolean;
684
+ decorateSecurableScope: (securableScope: ISecurableScope, params?: { pseudoUrl?: string, overrideSkipping?: boolean }) => void;
685
+ doSecurityWhenReady: (cb: () => void) => void;
686
+ considerVisibility: (id: string, scope: fng.ISecurableScope) => ISecurityVisibility;
687
+ considerContainerVisibility: (contentIds: string[], scope: fng.ISecurableScope) => fng.ISecurityVisibility;
688
+ getDisableableAttrs: (id: string) => string;
689
+ getHideableAttrs: (id: string) => string;
690
+ getDisableableAncestorAttrs: (id: string) => string;
691
+ generateDisabledAttr: (id: string, scope: fng.ISecurableScope, params?: IGenerateDisableAttrParams) => string;
692
+ }
416
693
  }
417
694
 
418
- declare var formsAngular: angular.IModule;
695
+ declare var formsAngular: fng.IFng;