df-ae-forms-package 1.0.96 → 1.0.97

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.
package/dist/index.esm.js CHANGED
@@ -4710,8 +4710,6 @@ formTemplateId, onThresholdActionCompletion, onThresholdIssueRaised, onNotesChan
4710
4710
  const DfFormDataGrid = ({ id, properties, mode = 'edit', formData = {}, onValueChange, onSelect, isSelected = false, className = '', onDataGridSelect, onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, selectedComponent, renderFormComponent, onEntryAdd, onEntryRemove, formTemplateId, onThresholdActionCompletion, onThresholdIssueRaised, onNotesChange, onAttachmentChange, shouldShowComponent }) => {
4711
4711
  const [isCollapsed, setIsCollapsed] = useState(false);
4712
4712
  const hasInitialized = useRef(false);
4713
- // Track local form values for entry components to prevent value loss during parent round-trip
4714
- const localFormValuesRef = useRef({});
4715
4713
  // Get all components in the grid and sanitize them to ensure no data leaks into templates
4716
4714
  let gridComponents = (properties.templateComponents || []).map(comp => ({
4717
4715
  ...comp,
@@ -4789,6 +4787,87 @@ const DfFormDataGrid = ({ id, properties, mode = 'edit', formData = {}, onValueC
4789
4787
  }
4790
4788
  }
4791
4789
  }
4790
+ else {
4791
+ // Update existing entries to include all template components and sync their properties
4792
+ const needsUpdate = dataEntries.some(entry => {
4793
+ // Check if entry is missing any template components or if existing components need updates
4794
+ return gridComponents.some((templateComp, componentIndex) => {
4795
+ const existingComponent = entry.components?.[componentIndex];
4796
+ if (!existingComponent) {
4797
+ return true; // Missing component at this index
4798
+ }
4799
+ // We don't check for ID matches here anymore
4800
+ // const expectedId = `${templateComp.id}-entry-${entry.index}-${componentIndex}`
4801
+ // const hasProperId = existingComponent.id === expectedId
4802
+ // Check if existing component needs to be updated with new template properties
4803
+ // Compare key properties that should be synced
4804
+ const needsPropertyUpdate = JSON.stringify(existingComponent.basic?.options) !== JSON.stringify(templateComp.basic?.options) ||
4805
+ existingComponent.basic?.placeholder !== templateComp.basic?.placeholder ||
4806
+ existingComponent.basic?.defaultValue !== templateComp.basic?.defaultValue ||
4807
+ existingComponent.basic?.label !== templateComp.basic?.label ||
4808
+ existingComponent.validation?.required !== templateComp.validation?.required;
4809
+ // We do not check for ID mismatch anymore as we want to preserve unique IDs
4810
+ return needsPropertyUpdate;
4811
+ });
4812
+ });
4813
+ if (needsUpdate && onValueChange) {
4814
+ const updatedEntries = dataEntries.map(entry => {
4815
+ // Use index-based matching to ensure each template component maps to the correct entry component
4816
+ const updatedComponents = gridComponents.map((templateComp, componentIndex) => {
4817
+ // Find existing component by index first
4818
+ let existingComponent = entry.components?.[componentIndex];
4819
+ // If no component at this index, try to find by name+label (for backward compatibility)
4820
+ if (!existingComponent) {
4821
+ existingComponent = entry.components?.find((comp) => comp.name === templateComp.name &&
4822
+ comp.basic?.label === templateComp.basic?.label);
4823
+ }
4824
+ // Always ensure a valid ID exists, but respect existing one if possible
4825
+ // const uniqueId = `${templateComp.id}-entry-${entry.index}-${componentIndex}`
4826
+ if (existingComponent) {
4827
+ // Update existing component with new template properties while ensuring unique ID and preserving form values
4828
+ const updatedComponent = {
4829
+ ...templateComp,
4830
+ id: existingComponent.id, // Preserve existing ID !!
4831
+ basic: {
4832
+ ...templateComp.basic,
4833
+ showLabel: false, // Hide label in datagrid cells
4834
+ // Preserve any user-entered values
4835
+ value: existingComponent.basic?.value || templateComp.basic?.defaultValue || ''
4836
+ }
4837
+ };
4838
+ return updatedComponent;
4839
+ }
4840
+ else {
4841
+ // Create new component based on template
4842
+ // Only for NEW components in existing entries (e.g. column added) do we generate a new ID
4843
+ const uniqueSuffix = `${Date.now()}-${Math.random().toString(36).substr(2, 5)}`;
4844
+ const newId = `${templateComp.id}-${uniqueSuffix}-${componentIndex}`;
4845
+ const newComponent = {
4846
+ ...templateComp,
4847
+ id: newId,
4848
+ basic: {
4849
+ ...templateComp.basic,
4850
+ showLabel: false // Hide label in datagrid cells
4851
+ }
4852
+ };
4853
+ return newComponent;
4854
+ }
4855
+ });
4856
+ return {
4857
+ ...entry,
4858
+ components: updatedComponents
4859
+ };
4860
+ });
4861
+ const newValue = { ...properties, entries: updatedEntries };
4862
+ // Only call onValueChange if the data actually changed
4863
+ if (JSON.stringify(newValue) !== JSON.stringify(properties)) {
4864
+ onValueChange({
4865
+ id,
4866
+ value: newValue
4867
+ });
4868
+ }
4869
+ }
4870
+ }
4792
4871
  }
4793
4872
  }, [gridComponents, dataEntries, id, onValueChange, properties, mode, properties.templateComponents]);
4794
4873
  const handleDataGridClick = useCallback((event) => {
@@ -4845,9 +4924,8 @@ const DfFormDataGrid = ({ id, properties, mode = 'edit', formData = {}, onValueC
4845
4924
  // Handle component value change for form data updates (test mode)
4846
4925
  const handleComponentValueChange = useCallback((change) => {
4847
4926
  if (mode === 'test') {
4848
- // CRITICAL: Store value locally to prevent loss during parent round-trip
4849
- localFormValuesRef.current[change.id] = change.value;
4850
- // Also propagate up to parent for persistence
4927
+ // In test mode, update form data through the parent's onValueChange
4928
+ // This allows the form data to be updated for interactive components
4851
4929
  if (onValueChange) {
4852
4930
  onValueChange({
4853
4931
  id: change.id,
@@ -4911,11 +4989,7 @@ const DfFormDataGrid = ({ id, properties, mode = 'edit', formData = {}, onValueC
4911
4989
  }, [properties, onValueChange, id, onEntryRemove]);
4912
4990
  // Use our own render function to ensure proper onComponentUpdate handling
4913
4991
  const renderComponent = useCallback((field, hideLabel = false) => {
4914
- // CRITICAL: Use local values first, then fall back to formData prop, then defaults
4915
- // This ensures typed values in entry 2+ persist immediately
4916
- const formValue = mode === 'test'
4917
- ? (localFormValuesRef.current[field.id] ?? formData[field.id] ?? field.basic?.value ?? ('defaultValue' in field.basic ? field.basic.defaultValue || '' : ''))
4918
- : ('defaultValue' in field.basic ? field.basic.defaultValue || '' : '');
4992
+ const formValue = mode === 'test' ? (formData[field.id] || ('defaultValue' in field.basic ? field.basic.defaultValue || '' : '')) : ('defaultValue' in field.basic ? field.basic.defaultValue || '' : '');
4919
4993
  const commonProps = {
4920
4994
  id: field.id,
4921
4995
  properties: field,
@@ -6419,9 +6493,12 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
6419
6493
  onFormDataChange?.(updatedComponents);
6420
6494
  } }) }));
6421
6495
  case 'datagrid':
6496
+ // Align package datagrid wiring with main app behaviour:
6497
+ // - Let DfFormDataGrid manage entry structure via onValueChange
6498
+ // - Use the shared onFormValueChange handler for nested field values
6499
+ // - Keep notes/attachments wiring as before
6422
6500
  return (jsx(DfFormDataGrid, { ...commonProps, properties: component, formData: formValues, formTemplateId: formTemplateId, mode: commonProps.mode, onThresholdActionCompletion: handleThresholdActionCompletion, onThresholdIssueRaised: handleThresholdIssueRaised, onNotesChange: (componentId, notes) => {
6423
6501
  handleComponentNotesChange(componentId, notes);
6424
- // Handle notes change for datagrid entry components
6425
6502
  const updatedComponents = localFormComponents.map(comp => {
6426
6503
  if (comp.id === component.id && comp.entries) {
6427
6504
  const updatedEntries = comp.entries.map((entry) => {
@@ -6449,7 +6526,6 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
6449
6526
  onFormDataChange?.(updatedComponents);
6450
6527
  }, onAttachmentChange: (componentId, attachments) => {
6451
6528
  handleComponentAttachmentChange(componentId, attachments);
6452
- // Handle attachment change for datagrid entry components
6453
6529
  const updatedComponents = localFormComponents.map(comp => {
6454
6530
  if (comp.id === component.id && comp.entries) {
6455
6531
  const updatedEntries = comp.entries.map((entry) => {
@@ -6475,116 +6551,7 @@ onComponentSelect, onComponentDelete, onComponentEdit, onComponentUpdate, select
6475
6551
  return comp;
6476
6552
  });
6477
6553
  onFormDataChange?.(updatedComponents);
6478
- }, onValueChange: (change) => {
6479
- console.log('[DfFormPreview] datagrid onValueChange received:', change.id, 'hasEntries:', change.value && typeof change.value === 'object' && 'entries' in change.value);
6480
- // Handle datagrid value changes (entries updates)
6481
- if (change.id === component.id && change.value && typeof change.value === 'object' && 'entries' in change.value) {
6482
- console.log('[DfFormPreview] datagrid entries update - entries count:', change.value.entries?.length);
6483
- // Update localFormComponents with new entries structure
6484
- const updatedComponents = localFormComponents.map(comp => {
6485
- if (comp.id === component.id) {
6486
- return {
6487
- ...comp,
6488
- ...change.value
6489
- };
6490
- }
6491
- return comp;
6492
- });
6493
- // CRITICAL: Update local state immediately so new entries render without Angular round-trip
6494
- setLocalFormComponents(updatedComponents);
6495
- onFormDataChange?.(updatedComponents);
6496
- // Also update formValues for nested components
6497
- if (change.value.entries && Array.isArray(change.value.entries)) {
6498
- change.value.entries.forEach((entry) => {
6499
- if (entry.components && Array.isArray(entry.components)) {
6500
- entry.components.forEach((nestedComp) => {
6501
- const nestedValue = formValues[nestedComp.id];
6502
- if (nestedValue !== undefined) ;
6503
- else {
6504
- // Initialize with defaultValue if available
6505
- const defaultValue = nestedComp.basic?.defaultValue;
6506
- if (defaultValue !== undefined) {
6507
- setFormValues(prev => ({
6508
- ...prev,
6509
- [nestedComp.id]: defaultValue
6510
- }));
6511
- }
6512
- }
6513
- });
6514
- }
6515
- });
6516
- }
6517
- }
6518
- else {
6519
- // For nested component value changes, use the regular handler
6520
- onFormValueChange(change);
6521
- }
6522
- }, onEntryAdd: () => {
6523
- // CRITICAL: Entry has already been added via onValueChange in DfFormDataGrid
6524
- // Get the updated component from localFormComponents (which should have been updated by onValueChange)
6525
- const currentComponent = localFormComponents.find(comp => comp.id === component.id);
6526
- if (currentComponent && currentComponent.entries) {
6527
- // Entry should already be in the component via onValueChange
6528
- // Just ensure localFormComponents is in sync (no-op if already synced)
6529
- const updatedComponents = localFormComponents.map(comp => {
6530
- if (comp.id === component.id) {
6531
- // Ensure entries are properly structured
6532
- return {
6533
- ...comp,
6534
- entries: comp.entries || []
6535
- };
6536
- }
6537
- return comp;
6538
- });
6539
- onFormDataChange?.(updatedComponents);
6540
- }
6541
- else {
6542
- // Fallback: If component doesn't have entries yet, try to get from formValues
6543
- setTimeout(() => {
6544
- const datagridValue = formValues[component.id];
6545
- if (datagridValue && typeof datagridValue === 'object' && 'entries' in datagridValue) {
6546
- const updatedComponents = localFormComponents.map(comp => {
6547
- if (comp.id === component.id) {
6548
- return {
6549
- ...comp,
6550
- entries: datagridValue.entries
6551
- };
6552
- }
6553
- return comp;
6554
- });
6555
- onFormDataChange?.(updatedComponents);
6556
- }
6557
- }, 100);
6558
- }
6559
- }, onEntryRemove: (entryIndex) => {
6560
- // Handle entry remove - update form components
6561
- const updatedComponents = localFormComponents.map(comp => {
6562
- if (comp.id === component.id && comp.entries) {
6563
- const currentEntries = comp.entries || [];
6564
- const updatedEntries = currentEntries
6565
- .filter((_, index) => index !== entryIndex)
6566
- .map((entry, index) => ({
6567
- ...entry,
6568
- index,
6569
- id: `entry-${comp.id}-${index}`,
6570
- components: entry.components?.map((comp, compIndex) => {
6571
- const templateComp = (comp.templateComponents || [])[compIndex];
6572
- return {
6573
- ...comp,
6574
- id: templateComp ? `${templateComp.id}-entry-${index}-${compIndex}` : comp.id
6575
- };
6576
- }) || []
6577
- }));
6578
- return {
6579
- ...comp,
6580
- entries: updatedEntries
6581
- };
6582
- }
6583
- return comp;
6584
- });
6585
- onFormDataChange?.(updatedComponents);
6586
- }, renderFormComponent: (field) => {
6587
- // Ensure the nested component gets the proper form value
6554
+ }, onValueChange: onFormValueChange, renderFormComponent: (field) => {
6588
6555
  return renderFormComponent(field);
6589
6556
  } }));
6590
6557
  case 'file':