forms-angular 0.12.0-beta.263 → 0.12.0-beta.264

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.
@@ -914,11 +914,6 @@ var fng;
914
914
  }
915
915
  }
916
916
  else {
917
- // NB: Any changes to what properties we support @@-wrapped pseudonyms for here should be repeated in
918
- // PluginHelperService.extractFromAttr
919
- info.help = FormMarkupHelperService.handlePseudos(scope, info.help);
920
- info.label = FormMarkupHelperService.handlePseudos(scope, info.label);
921
- info.popup = FormMarkupHelperService.handlePseudos(scope, info.popup);
922
917
  // Handle arrays here
923
918
  var controlDivClasses = FormMarkupHelperService.controlDivClasses(options);
924
919
  if (info.array) {
@@ -1121,201 +1116,179 @@ var fng;
1121
1116
  }
1122
1117
  return result;
1123
1118
  };
1124
- scope.$on("regenerateFormMarkup", function (event, formId) {
1125
- if (!attrs.formid || attrs.formid !== formId) {
1126
- return;
1127
- }
1128
- generateForm(scope[attrs.schema]);
1129
- });
1130
1119
  var unwatch = scope.$watch(attrs.schema, function (newValue) {
1131
1120
  if (newValue) {
1132
1121
  var newArrayValue = angular.isArray(newValue) ? newValue : [newValue]; // otherwise some old tests stop working for no real reason
1133
1122
  if (newArrayValue.length > 0 && typeof unwatch === "function") {
1134
1123
  unwatch();
1135
1124
  unwatch = null;
1136
- generateForm(newArrayValue);
1137
- }
1138
- }
1139
- }, true);
1140
- var formElement;
1141
- var generateForm = function (schema) {
1142
- var elementHtml = '';
1143
- var recordAttribute = attrs.model || 'record'; // By default data comes from scope.record
1144
- var theRecord = scope[recordAttribute];
1145
- var hideableTabs = schema.filter(function (s) { return s && s.containerType === "tab" && s.hideable; });
1146
- var hiddenTabArrayProp;
1147
- var hiddenTabReintroductionMethod;
1148
- for (var _i = 0, hideableTabs_1 = hideableTabs; _i < hideableTabs_1.length; _i++) {
1149
- var tab = hideableTabs_1[_i];
1150
- if (tab.hiddenTabArrayProp) {
1151
- if (hiddenTabArrayProp && tab.hiddenTabArrayProp !== hiddenTabArrayProp) {
1152
- throw new Error("Currently, tab sets with more than one value for hiddenTabArrayProp are not supported");
1125
+ var elementHtml = '';
1126
+ var recordAttribute = attrs.model || 'record'; // By default data comes from scope.record
1127
+ var theRecord = scope[recordAttribute];
1128
+ var hideableTabs = newArrayValue.filter(function (s) { return s && s.containerType === "tab" && s.hideable; });
1129
+ var hiddenTabArrayProp = void 0;
1130
+ var hiddenTabReintroductionMethod = void 0;
1131
+ for (var _i = 0, hideableTabs_1 = hideableTabs; _i < hideableTabs_1.length; _i++) {
1132
+ var tab = hideableTabs_1[_i];
1133
+ if (tab.hiddenTabArrayProp) {
1134
+ if (hiddenTabArrayProp && tab.hiddenTabArrayProp !== hiddenTabArrayProp) {
1135
+ throw new Error("Currently, tab sets with more than one value for hiddenTabArrayProp are not supported");
1136
+ }
1137
+ hiddenTabArrayProp = tab.hiddenTabArrayProp;
1138
+ }
1139
+ if (tab.hiddenTabReintroductionMethod) {
1140
+ if (hiddenTabReintroductionMethod && tab.hiddenTabReintroductionMethod !== hiddenTabReintroductionMethod) {
1141
+ throw new Error("Currently, tab sets with more than one value for hiddenTabReintroductionMethod are not supported");
1142
+ }
1143
+ hiddenTabReintroductionMethod = tab.hiddenTabReintroductionMethod;
1144
+ }
1153
1145
  }
1154
- hiddenTabArrayProp = tab.hiddenTabArrayProp;
1155
- }
1156
- if (tab.hiddenTabReintroductionMethod) {
1157
- if (hiddenTabReintroductionMethod && tab.hiddenTabReintroductionMethod !== hiddenTabReintroductionMethod) {
1158
- throw new Error("Currently, tab sets with more than one value for hiddenTabReintroductionMethod are not supported");
1146
+ // now we have established that we don't have more than one value for hiddenTabArrayProp, apply a default if no
1147
+ // value has been provided at all...
1148
+ if (!hiddenTabArrayProp) {
1149
+ hiddenTabArrayProp = "record.hiddenTabs";
1159
1150
  }
1160
- hiddenTabReintroductionMethod = tab.hiddenTabReintroductionMethod;
1161
- }
1162
- }
1163
- // now we have established that we don't have more than one value for hiddenTabArrayProp, apply a default if no
1164
- // value has been provided at all...
1165
- if (!hiddenTabArrayProp) {
1166
- hiddenTabArrayProp = "record.hiddenTabs";
1167
- }
1168
- // ...and then replace all blanks with this value so the processInstructions() call made below can deal with
1169
- // each tab independently of the others
1170
- for (var _a = 0, hideableTabs_2 = hideableTabs; _a < hideableTabs_2.length; _a++) {
1171
- var tab = hideableTabs_2[_a];
1172
- tab.hiddenTabArrayProp = hiddenTabArrayProp;
1173
- }
1174
- if (hiddenTabReintroductionMethod === "tab") {
1175
- schema.push({
1176
- containerType: "+tab",
1177
- hiddenTabArrayProp: hiddenTabArrayProp,
1178
- content: []
1179
- });
1180
- }
1181
- theRecord = theRecord || {};
1182
- if ((attrs.subschema || attrs.model) && !attrs.forceform) {
1183
- elementHtml = '';
1184
- }
1185
- else {
1186
- scope.topLevelFormName = attrs.name || 'myForm'; // Form name defaults to myForm
1187
- // Copy attrs we don't process into form
1188
- var customAttrs = '';
1189
- for (var thisAttr in attrs) {
1190
- if (attrs.hasOwnProperty(thisAttr)) {
1191
- if (thisAttr[0] !== '$' && ['name', 'formstyle', 'schema', 'subschema', 'model', 'viewform'].indexOf(thisAttr) === -1) {
1192
- customAttrs += ' ' + attrs.$attr[thisAttr] + '="' + attrs[thisAttr] + '"';
1193
- }
1151
+ // ...and then replace all blanks with this value so the processInstructions() call made below can deal with
1152
+ // each tab independently of the others
1153
+ for (var _a = 0, hideableTabs_2 = hideableTabs; _a < hideableTabs_2.length; _a++) {
1154
+ var tab = hideableTabs_2[_a];
1155
+ tab.hiddenTabArrayProp = hiddenTabArrayProp;
1194
1156
  }
1195
- }
1196
- var tag = attrs.forceform ? 'ng-form' : 'form';
1197
- elementHtml = "<".concat(tag, " name=\"").concat(scope.topLevelFormName, "\" class=\"").concat(convertFormStyleToClass(attrs.formstyle), "\" novalidate ").concat(customAttrs, ">");
1198
- }
1199
- if (theRecord === scope.topLevelFormName) {
1200
- throw new Error('Model and Name must be distinct - they are both ' + theRecord);
1201
- }
1202
- elementHtml += processInstructions(schema, true, attrs);
1203
- if (tabsSetup === tabsSetupState.Forced) {
1204
- elementHtml += '</uib-tabset>';
1205
- }
1206
- elementHtml += attrs.subschema ? '' : '</form>';
1207
- var compiledFormElement = $compile(elementHtml)(scope);
1208
- if (formElement) {
1209
- var topLevelForm = scope[scope.topLevelFormName];
1210
- formElement.replaceWith(compiledFormElement);
1211
- // the replaceWith will cause the scope[scope.topLevelFormName] to be cleared, so we need to...:
1212
- scope[scope.topLevelFormName] = topLevelForm;
1213
- }
1214
- else {
1215
- element.replaceWith(compiledFormElement);
1216
- }
1217
- // remember the element that we're now represented by (which is no longer the value
1218
- // of element passed to our link function). This will enable us to replace the
1219
- // correct element upon receipt of a regenerateFormMarkup request.
1220
- formElement = compiledFormElement;
1221
- // If there are subkeys we need to fix up ng-model references when record is read
1222
- // If we have modelControllers we need to let them know when we have form + data
1223
- var sharedData = scope[attrs.shared || 'sharedData'];
1224
- var modelControllers = sharedData ? sharedData.modelControllers : [];
1225
- if ((subkeys.length > 0 || modelControllers.length > 0) && !scope.phaseWatcher) {
1226
- var unwatch2 = scope.$watch('phase', function (newValue) {
1227
- scope.phaseWatcher = true;
1228
- if (newValue === 'ready' && typeof unwatch2 === "function") {
1229
- unwatch2();
1230
- unwatch2 = null;
1231
- // Tell the 'model controllers' that the form and data are there
1232
- for (var i = 0; i < modelControllers.length; i++) {
1233
- if (modelControllers[i].onAllReady) {
1234
- modelControllers[i].onAllReady(scope);
1157
+ if (hiddenTabReintroductionMethod === "tab") {
1158
+ newArrayValue.push({
1159
+ containerType: "+tab",
1160
+ hiddenTabArrayProp: hiddenTabArrayProp,
1161
+ content: []
1162
+ });
1163
+ }
1164
+ theRecord = theRecord || {};
1165
+ if ((attrs.subschema || attrs.model) && !attrs.forceform) {
1166
+ elementHtml = '';
1167
+ }
1168
+ else {
1169
+ scope.topLevelFormName = attrs.name || 'myForm'; // Form name defaults to myForm
1170
+ // Copy attrs we don't process into form
1171
+ var customAttrs = '';
1172
+ for (var thisAttr in attrs) {
1173
+ if (attrs.hasOwnProperty(thisAttr)) {
1174
+ if (thisAttr[0] !== '$' && ['name', 'formstyle', 'schema', 'subschema', 'model', 'viewform'].indexOf(thisAttr) === -1) {
1175
+ customAttrs += ' ' + attrs.$attr[thisAttr] + '="' + attrs[thisAttr] + '"';
1176
+ }
1235
1177
  }
1236
1178
  }
1237
- // For each one of the subkeys sets in the form we need to fix up ng-model references
1238
- for (var subkeyCtr = 0; subkeyCtr < subkeys.length; subkeyCtr++) {
1239
- var info = subkeys[subkeyCtr];
1240
- var arrayOffset;
1241
- var matching;
1242
- var arrayToProcess = angular.isArray(info.subkey) ? info.subkey : [info.subkey];
1243
- var parts = info.name.split('.');
1244
- var dataVal = theRecord;
1245
- while (parts.length > 1) {
1246
- dataVal = dataVal[parts.shift()] || {};
1247
- }
1248
- dataVal = dataVal[parts[0]] = dataVal[parts[0]] || [];
1249
- // For each of the required subkeys of this type
1250
- for (var thisOffset = 0; thisOffset < arrayToProcess.length; thisOffset++) {
1251
- if (arrayToProcess[thisOffset].selectFunc) {
1252
- // Get the array offset from a function
1253
- if (!scope[arrayToProcess[thisOffset].selectFunc] || typeof scope[arrayToProcess[thisOffset].selectFunc] !== 'function') {
1254
- throw new Error('Subkey function ' + arrayToProcess[thisOffset].selectFunc + ' is not properly set up');
1179
+ var tag = attrs.forceform ? 'ng-form' : 'form';
1180
+ elementHtml = "<".concat(tag, " name=\"").concat(scope.topLevelFormName, "\" class=\"").concat(convertFormStyleToClass(attrs.formstyle), "\" novalidate ").concat(customAttrs, ">");
1181
+ }
1182
+ if (theRecord === scope.topLevelFormName) {
1183
+ throw new Error('Model and Name must be distinct - they are both ' + theRecord);
1184
+ }
1185
+ elementHtml += processInstructions(newArrayValue, true, attrs);
1186
+ if (tabsSetup === tabsSetupState.Forced) {
1187
+ elementHtml += '</uib-tabset>';
1188
+ }
1189
+ elementHtml += attrs.subschema ? '' : '</form>';
1190
+ //console.log(elementHtml);
1191
+ element.replaceWith($compile(elementHtml)(scope));
1192
+ // If there are subkeys we need to fix up ng-model references when record is read
1193
+ // If we have modelControllers we need to let them know when we have form + data
1194
+ var sharedData = scope[attrs.shared || 'sharedData'];
1195
+ var modelControllers_1 = sharedData ? sharedData.modelControllers : [];
1196
+ if ((subkeys.length > 0 || modelControllers_1.length > 0) && !scope.phaseWatcher) {
1197
+ var unwatch2 = scope.$watch('phase', function (newValue) {
1198
+ scope.phaseWatcher = true;
1199
+ if (newValue === 'ready' && typeof unwatch2 === "function") {
1200
+ unwatch2();
1201
+ unwatch2 = null;
1202
+ // Tell the 'model controllers' that the form and data are there
1203
+ for (var i = 0; i < modelControllers_1.length; i++) {
1204
+ if (modelControllers_1[i].onAllReady) {
1205
+ modelControllers_1[i].onAllReady(scope);
1255
1206
  }
1256
- arrayOffset = scope[arrayToProcess[thisOffset].selectFunc](theRecord, info);
1257
1207
  }
1258
- else if (arrayToProcess[thisOffset].keyList) {
1259
- // We are choosing the array element by matching one or more keys
1260
- var thisSubkeyList = arrayToProcess[thisOffset].keyList;
1261
- for (arrayOffset = 0; arrayOffset < dataVal.length; arrayOffset++) {
1262
- matching = true;
1263
- for (var keyField in thisSubkeyList) {
1264
- if (thisSubkeyList.hasOwnProperty(keyField)) {
1265
- // Not (currently) concerned with objects here - just simple types and lookups
1266
- if (dataVal[arrayOffset][keyField] !== thisSubkeyList[keyField] &&
1267
- (typeof dataVal[arrayOffset][keyField] === 'undefined' || !dataVal[arrayOffset][keyField].text || dataVal[arrayOffset][keyField].text !== thisSubkeyList[keyField])) {
1268
- matching = false;
1208
+ // For each one of the subkeys sets in the form we need to fix up ng-model references
1209
+ for (var subkeyCtr = 0; subkeyCtr < subkeys.length; subkeyCtr++) {
1210
+ var info = subkeys[subkeyCtr];
1211
+ var arrayOffset;
1212
+ var matching;
1213
+ var arrayToProcess = angular.isArray(info.subkey) ? info.subkey : [info.subkey];
1214
+ var parts = info.name.split('.');
1215
+ var dataVal = theRecord;
1216
+ while (parts.length > 1) {
1217
+ dataVal = dataVal[parts.shift()] || {};
1218
+ }
1219
+ dataVal = dataVal[parts[0]] = dataVal[parts[0]] || [];
1220
+ // For each of the required subkeys of this type
1221
+ for (var thisOffset = 0; thisOffset < arrayToProcess.length; thisOffset++) {
1222
+ if (arrayToProcess[thisOffset].selectFunc) {
1223
+ // Get the array offset from a function
1224
+ if (!scope[arrayToProcess[thisOffset].selectFunc] || typeof scope[arrayToProcess[thisOffset].selectFunc] !== 'function') {
1225
+ throw new Error('Subkey function ' + arrayToProcess[thisOffset].selectFunc + ' is not properly set up');
1226
+ }
1227
+ arrayOffset = scope[arrayToProcess[thisOffset].selectFunc](theRecord, info);
1228
+ }
1229
+ else if (arrayToProcess[thisOffset].keyList) {
1230
+ // We are choosing the array element by matching one or more keys
1231
+ var thisSubkeyList = arrayToProcess[thisOffset].keyList;
1232
+ for (arrayOffset = 0; arrayOffset < dataVal.length; arrayOffset++) {
1233
+ matching = true;
1234
+ for (var keyField in thisSubkeyList) {
1235
+ if (thisSubkeyList.hasOwnProperty(keyField)) {
1236
+ // Not (currently) concerned with objects here - just simple types and lookups
1237
+ if (dataVal[arrayOffset][keyField] !== thisSubkeyList[keyField] &&
1238
+ (typeof dataVal[arrayOffset][keyField] === 'undefined' || !dataVal[arrayOffset][keyField].text || dataVal[arrayOffset][keyField].text !== thisSubkeyList[keyField])) {
1239
+ matching = false;
1240
+ break;
1241
+ }
1242
+ }
1243
+ }
1244
+ if (matching) {
1269
1245
  break;
1270
1246
  }
1271
1247
  }
1272
- }
1273
- if (matching) {
1274
- break;
1275
- }
1276
- }
1277
- if (!matching) {
1278
- // There is no matching array element
1279
- switch (arrayToProcess[thisOffset].onNotFound) {
1280
- case 'error':
1281
- var errorMessage = 'Cannot find matching ' + (arrayToProcess[thisOffset].title || arrayToProcess[thisOffset].path);
1282
- //Have to do this async as setPristine clears it
1283
- $timeout(function () {
1284
- scope.showError(errorMessage, 'Unable to set up form correctly');
1285
- });
1286
- arrayOffset = -1;
1287
- //throw new Error(scope.errorMessage);
1288
- break;
1289
- case 'create':
1290
- default:
1291
- var nameElements = info.name.split('.');
1292
- var lastPart = nameElements.pop();
1293
- var possibleArray = nameElements.join('.');
1294
- var obj = theRecord;
1295
- // Should loop here when / if we re-introduce nesting
1296
- if (possibleArray) {
1297
- obj = obj[possibleArray];
1248
+ if (!matching) {
1249
+ // There is no matching array element
1250
+ switch (arrayToProcess[thisOffset].onNotFound) {
1251
+ case 'error':
1252
+ var errorMessage = 'Cannot find matching ' + (arrayToProcess[thisOffset].title || arrayToProcess[thisOffset].path);
1253
+ //Have to do this async as setPristine clears it
1254
+ $timeout(function () {
1255
+ scope.showError(errorMessage, 'Unable to set up form correctly');
1256
+ });
1257
+ arrayOffset = -1;
1258
+ //throw new Error(scope.errorMessage);
1259
+ break;
1260
+ case 'create':
1261
+ default:
1262
+ var nameElements = info.name.split('.');
1263
+ var lastPart = nameElements.pop();
1264
+ var possibleArray = nameElements.join('.');
1265
+ var obj = theRecord;
1266
+ // Should loop here when / if we re-introduce nesting
1267
+ if (possibleArray) {
1268
+ obj = obj[possibleArray];
1269
+ }
1270
+ arrayOffset = obj[lastPart].push(thisSubkeyList) - 1;
1271
+ break;
1298
1272
  }
1299
- arrayOffset = obj[lastPart].push(thisSubkeyList) - 1;
1300
- break;
1273
+ }
1274
+ }
1275
+ else {
1276
+ throw new Error('Invalid subkey setup for ' + info.name);
1301
1277
  }
1278
+ scope['$_arrayOffset_' + info.name.replace(/\./g, '_') + '_' + thisOffset] = arrayOffset;
1302
1279
  }
1303
1280
  }
1304
- else {
1305
- throw new Error('Invalid subkey setup for ' + info.name);
1306
- }
1307
- scope['$_arrayOffset_' + info.name.replace(/\./g, '_') + '_' + thisOffset] = arrayOffset;
1308
1281
  }
1309
- }
1282
+ });
1310
1283
  }
1311
- });
1312
- }
1313
- $rootScope.$broadcast('formInputDone', attrs.name);
1314
- if (FormGeneratorService.updateDataDependentDisplay && theRecord && Object.keys(theRecord).length > 0) {
1315
- // If this is not a test force the data dependent updates to the DOM
1316
- FormGeneratorService.updateDataDependentDisplay(theRecord, null, true, scope);
1284
+ $rootScope.$broadcast('formInputDone', attrs.name);
1285
+ if (FormGeneratorService.updateDataDependentDisplay && theRecord && Object.keys(theRecord).length > 0) {
1286
+ // If this is not a test force the data dependent updates to the DOM
1287
+ FormGeneratorService.updateDataDependentDisplay(theRecord, null, true, scope);
1288
+ }
1289
+ }
1317
1290
  }
1318
- };
1291
+ }, true);
1319
1292
  }
1320
1293
  };
1321
1294
  }
@@ -2878,78 +2851,9 @@ var fng;
2878
2851
  function isArrayElement(scope, info, options) {
2879
2852
  return scope["$index"] !== undefined || !!options.subschema;
2880
2853
  }
2881
- function performPseudoReplacements(scope, str, substitutionSrc) {
2882
- while (str.includes("@@")) {
2883
- var firstCharPos = str.indexOf("@@") + 2;
2884
- var lastCharPos = str.indexOf("@@", firstCharPos) - 1;
2885
- var token = str.substring(firstCharPos, lastCharPos + 1);
2886
- var plural = token.endsWith("s");
2887
- if (plural) {
2888
- token = token.slice(0, -1);
2889
- }
2890
- var upperStr = token[0].toUpperCase() === token[0] ? "true" : "false";
2891
- token = token.toLocaleLowerCase();
2892
- var replacement = void 0;
2893
- if (substitutionSrc === "global") {
2894
- replacement = fng.formsAngular.pseudo(token, upperStr === "true");
2895
- }
2896
- else if (substitutionSrc === "scopeStatic") {
2897
- replacement = scope.sharedData.pseudo(token, upperStr === "true");
2898
- }
2899
- else if (substitutionSrc === "scopeDynamic") {
2900
- replacement = "{{ sharedData.pseudo('".concat(token, "', ").concat(upperStr, ") }}");
2901
- }
2902
- else {
2903
- replacement = "";
2904
- }
2905
- str =
2906
- str.substring(0, firstCharPos - 2) +
2907
- replacement +
2908
- (plural ? "s" : "") +
2909
- str.substring(lastCharPos + 3);
2910
- }
2911
- return str;
2912
- }
2913
- // Text surrounded by @@ @@ is assumed to be something that can have a pseudonym:
2914
- // - If the sharedData object has been assigned a pseudo() function:
2915
- // - then if dynamicFuncName has a value, we will set up a function on scope that will call that function to perform
2916
- // the necessary substitutions. This would be useful for directives that use a template where labels, hints etc. already use {{ }}
2917
- // notation (which would prevent any additional {{ }} that we nested in our result from working as intended).
2918
- // - otherwise, we will set up the necessary dynamic calls to that sharedData.pseudo function using {{ }} notation
2919
- // - Otherwise, if a pseudo callback has been provided in the IFng options, we will use that to perform a one-off (static) replacement.
2920
- // - Otherwise (though not expected to happen), we will just remove the @@ tags, leaving the token(s) unchanged.
2921
- // If the first character of the pseudonym token is upper case, then its replacement will use
2922
- // titlecase, otherwise its replacement will be in lowercase.
2923
- // If the last character of the pseudonym token is "s", then its replacement will be pluralised.
2924
- function handlePseudos(scope, str, dynamicFuncName) {
2925
- var _a;
2926
- if (!(str === null || str === void 0 ? void 0 : str.includes("@@"))) {
2927
- return str;
2928
- }
2929
- var substitutionSrc;
2930
- if (typeof ((_a = scope === null || scope === void 0 ? void 0 : scope.sharedData) === null || _a === void 0 ? void 0 : _a.pseudo) === "function") {
2931
- if (dynamicFuncName) {
2932
- scope[dynamicFuncName] = function () {
2933
- return performPseudoReplacements(scope, str, "scopeStatic");
2934
- };
2935
- substitutionSrc = "none"; // now the dynamic function has been set up, remove the @@ @@ tags (probably not essential, but might avoid confusion)
2936
- }
2937
- else {
2938
- substitutionSrc = "scopeDynamic";
2939
- }
2940
- }
2941
- else if (typeof fng.formsAngular.pseudo === "function") {
2942
- substitutionSrc = "global";
2943
- }
2944
- else {
2945
- substitutionSrc = "none";
2946
- }
2947
- return performPseudoReplacements(scope, str, substitutionSrc);
2948
- }
2949
2854
  return {
2950
2855
  isHorizontalStyle: isHorizontalStyle,
2951
2856
  isArrayElement: isArrayElement,
2952
- handlePseudos: handlePseudos,
2953
2857
  fieldChrome: function fieldChrome(scope, info, options) {
2954
2858
  var insert = '';
2955
2859
  if (info.id && typeof info.id.replace === "function") {
@@ -3294,8 +3198,33 @@ var fng;
3294
3198
  function internalGenDisabledStr(scope, id, processedAttrs, idSuffix, params) {
3295
3199
  return internalGenDisabledAttrs(scope, id, processedAttrs, idSuffix, params).join(" ");
3296
3200
  }
3297
- function handlePseudos(scope, str, dynamicFuncName) {
3298
- return FormMarkupHelperService.handlePseudos(scope, str, dynamicFuncName);
3201
+ // Text surrounded by @@ @@ is assumed to be something that can have a pseudonym. We'll rely
3202
+ // upon the relevant controller assigning a pseudo() function to baseScope.
3203
+ // If the first character of the pseudonym token is upper case, then its replacement will use
3204
+ // titlecase, otherwise its replacement will be in lowercase.
3205
+ // If the last character of the pseudonym token is "s", then its replacement will be pluralised.
3206
+ function handlePseudos(str) {
3207
+ if (!str) {
3208
+ return str;
3209
+ }
3210
+ var result = str;
3211
+ while (result.includes("@@")) {
3212
+ var firstCharPos = result.indexOf("@@") + 2;
3213
+ var lastCharPos = result.indexOf("@@", firstCharPos) - 1;
3214
+ var token = result.substring(firstCharPos, lastCharPos + 1);
3215
+ var plural = token.endsWith("s");
3216
+ if (plural) {
3217
+ token = token.slice(0, -1);
3218
+ }
3219
+ var upperStr = token[0].toUpperCase() === token[0] ? "true" : "false";
3220
+ token = token.toLocaleLowerCase();
3221
+ result =
3222
+ result.substring(0, firstCharPos - 2) +
3223
+ "{{ baseScope.pseudo('".concat(token, "', ").concat(upperStr, ") }}") +
3224
+ (plural ? "s" : "") +
3225
+ result.substring(lastCharPos + 3);
3226
+ }
3227
+ return result;
3299
3228
  }
3300
3229
  function makeIdStringUniqueForArrayElements(scope, processedAttrs, idString) {
3301
3230
  if (FormMarkupHelperService.isArrayElement(scope, processedAttrs.info, processedAttrs.options)) {
@@ -3358,7 +3287,7 @@ var fng;
3358
3287
  // of whether or not the datetime picker is actually disabled) to indicate that it potentially could be
3359
3288
  return disabledStr + " " + rawDisabledAttrs[1];
3360
3289
  }
3361
- function extractFromAttr(attr, directiveName, scope, opts) {
3290
+ function extractFromAttr(attr, directiveName) {
3362
3291
  function deserialize(str) {
3363
3292
  var retVal = str.replace(/&quot;/g, '"');
3364
3293
  if (retVal === "true") {
@@ -3397,9 +3326,12 @@ var fng;
3397
3326
  }
3398
3327
  }
3399
3328
  var result = { info: info, options: options, directiveOptions: directiveOptions };
3400
- result.info.help = handlePseudos(scope, result.info.help, (opts === null || opts === void 0 ? void 0 : opts.setUpDynamicHelpFunc) ? "help" : undefined);
3401
- result.info.label = handlePseudos(scope, result.info.label, (opts === null || opts === void 0 ? void 0 : opts.setUpDynamicLabelFunc) ? "label" : undefined);
3402
- result.info.popup = handlePseudos(scope, result.info.popup);
3329
+ // any part of the help text or label that is surrounded by @@ @@ is assumed to be something that can have
3330
+ // a pseudonym. We'll be relying upon the parent controller assigning a pseudo() function to baseScope to
3331
+ // actually perform the translation.
3332
+ // TODO - do this better when fng is re-written!
3333
+ result.info.help = handlePseudos(result.info.help);
3334
+ result.info.label = handlePseudos(result.info.label);
3403
3335
  return result;
3404
3336
  }
3405
3337
  function genIdAndDisabledStr(scope, processedAttrs, idSuffix, params) {
@@ -3410,7 +3342,7 @@ var fng;
3410
3342
  return {
3411
3343
  extractFromAttr: extractFromAttr,
3412
3344
  buildInputMarkup: function buildInputMarkup(scope, attrs, params, generateInputControl) {
3413
- var processedAttrs = params.processedAttrs || extractFromAttr(attrs, "", scope);
3345
+ var processedAttrs = params.processedAttrs || extractFromAttr(attrs, "");
3414
3346
  var info = {};
3415
3347
  if (!params.ignoreFieldInfoFromAttrs) {
3416
3348
  Object.assign(info, processedAttrs.info);