| 
371 | 371 |     const validateInput = (input) => {  | 
372 | 372 |         const isInputEmpty = !input.value;  | 
373 | 373 |         const field = input.closest('.form-group');  | 
374 |  | -        const labelNode = field.querySelector('.ibexa-label');  | 
375 |  | -        const errorNode = field.querySelector('.ibexa-form-error');  | 
 | 374 | +        const labelNode = field?.querySelector('.ibexa-label');  | 
 | 375 | +        const errorNode = field?.querySelector('.ibexa-form-error');  | 
376 | 376 | 
 
  | 
377 | 377 |         input.classList.toggle('is-invalid', isInputEmpty);  | 
378 | 378 | 
 
  | 
 | 
390 | 390 | 
 
  | 
391 | 391 |         isEditFormValid = isEditFormValid && !isInputEmpty;  | 
392 | 392 |     };  | 
 | 393 | +    const validateMatrixColumns = (columnSettingsNode) => {  | 
 | 394 | +        const columns = columnSettingsNode.querySelectorAll('.ibexa-matrix-settings__column');  | 
 | 395 | +        const requiredInputs = columnSettingsNode.querySelectorAll('.ibexa-input[required]');  | 
 | 396 | +        const hasAddedColumns = columns.length > 0;  | 
 | 397 | +        const hasEmptyRequiredInputs = [...requiredInputs].some((input) => !input.value);  | 
 | 398 | +        const isValid = hasAddedColumns && !hasEmptyRequiredInputs;  | 
 | 399 | +        const errorNode = columnSettingsNode.querySelector('.ibexa-form-error');  | 
 | 400 | + | 
 | 401 | +        errorNode.toggleAttribute('hidden', hasAddedColumns);  | 
 | 402 | + | 
 | 403 | +        return isValid;  | 
 | 404 | +    };  | 
393 | 405 |     const validateForm = () => {  | 
394 | 406 |         const fieldDefinitionsStatuses = {};  | 
 | 407 | +        const matrixColumnsSettingsNodes = doc.querySelectorAll('.ibexa-matrix-settings__columns');  | 
395 | 408 | 
 
  | 
396 | 409 |         isEditFormValid = true;  | 
397 | 410 |         inputsToValidate = editForm.querySelectorAll(SELECTOR_INPUTS_TO_VALIDATE);  | 
 | 
413 | 426 |             validateInput(input);  | 
414 | 427 |         });  | 
415 | 428 | 
 
  | 
 | 429 | +        matrixColumnsSettingsNodes.forEach((columnSettingsNode) => {  | 
 | 430 | +            const fieldDefinition = columnSettingsNode.closest('.ibexa-collapse--field-definition');  | 
 | 431 | +            const { fieldDefinitionIdentifier } = fieldDefinition.dataset;  | 
 | 432 | +            const hasError = !validateMatrixColumns(columnSettingsNode);  | 
 | 433 | + | 
 | 434 | +            if (!fieldDefinitionsStatuses[fieldDefinitionIdentifier]) {  | 
 | 435 | +                fieldDefinitionsStatuses[fieldDefinitionIdentifier] = [];  | 
 | 436 | +            }  | 
 | 437 | + | 
 | 438 | +            fieldDefinitionsStatuses[fieldDefinitionIdentifier].push(hasError);  | 
 | 439 | +            isEditFormValid = isEditFormValid && !hasError;  | 
 | 440 | +        });  | 
 | 441 | + | 
416 | 442 |         Object.entries(fieldDefinitionsStatuses).forEach(([fieldDefinitionIdentifier, inputsStatus]) => {  | 
417 | 443 |             const isFieldDefinitionValid = inputsStatus.every((hasError) => !hasError);  | 
418 | 444 |             const fieldDefinitionNode = doc.querySelector(`[data-field-definition-identifier="${fieldDefinitionIdentifier}"]`);  | 
 | 
427 | 453 |     };  | 
428 | 454 |     const scrollToInvalidInput = () => {  | 
429 | 455 |         const firstInvalidInput = editForm.querySelector('.ibexa-input.is-invalid');  | 
430 |  | -        const fieldDefinition = firstInvalidInput.closest('.ibexa-collapse--field-definition');  | 
431 |  | -        const scrollToNode = fieldDefinition ?? firstInvalidInput;  | 
 | 456 | +        const firstInvalidFieldDefinition = editForm.querySelector('.ibexa-collapse--field-definition.is-invalid');  | 
 | 457 | +        const scrollToNode = firstInvalidFieldDefinition ?? firstInvalidInput;  | 
432 | 458 | 
 
  | 
433 | 459 |         scrollToNode.scrollIntoView({ behavior: 'smooth' });  | 
434 | 460 |     };  | 
 | 
629 | 655 |         draggableGroups.push(draggable);  | 
630 | 656 |     });  | 
631 | 657 | 
 
  | 
 | 658 | +    doc.body.addEventListener('ibexa-fieldtype-matrix:added-column', (event) => {  | 
 | 659 | +        const { columnNode } = event.detail;  | 
 | 660 | +        const inputs = columnNode.querySelectorAll('.ibexa-input[required]');  | 
 | 661 | + | 
 | 662 | +        [...inputs].forEach((input) => {  | 
 | 663 | +            attachValidateEvents(input);  | 
 | 664 | +        });  | 
 | 665 | +    });  | 
 | 666 | + | 
632 | 667 |     fieldDefinitionsGroups.forEach((group) => group.addEventListener('click', () => setActiveGroup(group), false));  | 
633 | 668 |     inputsToValidate.forEach(attachValidateEvents);  | 
634 | 669 | 
 
  | 
 | 
0 commit comments