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