diff --git a/src/components/VnTable/VnTable.vue b/src/components/VnTable/VnTable.vue index 0a8f080f3..f1019e7ae 100644 --- a/src/components/VnTable/VnTable.vue +++ b/src/components/VnTable/VnTable.vue @@ -373,16 +373,20 @@ function handleSelection({ evt, added, rows: selectedRows }, rows) { } } -function isEditableColumn(column) { - const isEditableCol = column?.isEditable ?? true; +function isEditableColumn(column, row) { + const isEditableCol = + typeof column?.isEditable == 'function' + ? column?.isEditable(row) + : (column?.isEditable ?? true); + const isVisible = column?.visible ?? true; const hasComponent = column?.component; return $props.isEditable && isVisible && hasComponent && isEditableCol; } -function hasEditableFormat(column) { - if (isEditableColumn(column)) return 'editable-text'; +function hasEditableFormat(column, row) { + if (isEditableColumn(column, row)) return 'editable-text'; } const clickHandler = async (event) => { @@ -394,6 +398,7 @@ const clickHandler = async (event) => { if (isDateElement || isTimeElement || isQSelectDropDown) return; if (clickedElement === null) { + console.log('destroyInput 1'); await destroyInput(editingRow.value, editingField.value); return; } @@ -404,17 +409,25 @@ const clickHandler = async (event) => { if (editingRow.value !== null && editingField.value !== null) { if (editingRow.value == rowIndex && editingField.value == colField) return; + console.log('destroyInput 2'); await destroyInput(editingRow.value, editingField.value); } - if (isEditableColumn(column)) { + if ( + isEditableColumn( + column, + CrudModelRef.value.formData[rowIndex ?? editingRow.value], + ) + ) { await renderInput(Number(rowIndex), colField, clickedElement); } }; async function handleTabKey(event, rowIndex, colField) { - if (editingRow.value == rowIndex && editingField.value == colField) + if (editingRow.value == rowIndex && editingField.value == colField) { + console.log('destroyInput 3'); await destroyInput(editingRow.value, editingField.value); + } const direction = event.shiftKey ? -1 : 1; const { nextRowIndex, nextColumnName } = await handleTabNavigation( @@ -426,6 +439,7 @@ async function handleTabKey(event, rowIndex, colField) { if (nextRowIndex < 0 || nextRowIndex >= arrayData.store.data.length) return; event.preventDefault(); + console.log('nextColumnName: ', nextColumnName); await renderInput(nextRowIndex, nextColumnName, null); } @@ -467,16 +481,21 @@ async function renderInput(rowId, field, clickedElement) { await column?.cellEvent?.['update:modelValue']?.(value, oldValue, row); }, keyup: async (event) => { - if (event.key === 'Enter') + if (event.key === 'Enter') { + console.log('destroyInput 4'); await destroyInput(rowId, field, clickedElement); + } }, keydown: async (event) => { switch (event.key) { case 'Tab': + console.log('field: ', field); + console.log('target: ', event.target); await handleTabKey(event, rowId, field); event.stopPropagation(); break; case 'Escape': + console.log('destroyInput 5'); await destroyInput(rowId, field, clickedElement); break; default: @@ -511,6 +530,10 @@ async function updateSelectValue(value, column, row, oldValue) { } async function destroyInput(rowIndex, field, clickedElement) { + const column = $props.columns.find((col) => col.name === field); + if (typeof column?.beforeDestroy === 'function') + await column.beforeDestroy(CrudModelRef.value.formData[rowIndex]); + if (!clickedElement) clickedElement = document.querySelector( `[data-row-index="${rowIndex}"][data-col-field="${field}"]`, @@ -523,6 +546,7 @@ async function destroyInput(rowIndex, field, clickedElement) { child.style.position = ''; }); } + if (editingRow.value !== rowIndex || editingField.value !== field) return; editingRow.value = null; editingField.value = null; @@ -540,7 +564,13 @@ async function handleTabNavigation(rowIndex, colName, direction) { iterations++; newColumnIndex = (newColumnIndex + direction + totalColumns) % totalColumns; - if (isEditableColumn(columns[newColumnIndex])) break; + if ( + isEditableColumn( + columns[newColumnIndex], + CrudModelRef.value.formData[rowIndex], + ) + ) + break; } while (iterations < totalColumns); if (iterations >= totalColumns + 1) return; @@ -840,19 +870,19 @@ const handleHeaderSelection = (evt, data) => { : getToggleIcon(row[col?.name]) " style="color: var(--vn-text-color)" - :class="hasEditableFormat(col)" + :class="hasEditableFormat(col, row)" size="14px" /> { beforeEach(() => { - cy.login('developer'); + cy.login('buyer'); cy.visit(`/#/item/list`); }); it('should filter the items and redirect to the summary', () => { - cy.dataCy('Category_select').type('Plant'); - cy.get('.q-menu .q-item').contains('Plant').click(); - cy.dataCy('Type_select').type('Anthurium'); - cy.get('.q-menu .q-item').contains('Anthurium').click(); + cy.selectOption('[data-cy="Category_select"]', 'Plant'); + cy.selectOption('[data-cy="Type_select"]', 'Anthurium'); cy.get('.q-virtual-scroll__content > :nth-child(4) > :nth-child(4)').click(); + cy.url().should('include', '/summary'); }); it('should create an item', () => { @@ -24,8 +23,6 @@ describe('Item list', () => { cy.fillInForm(data); cy.dataCy('FormModelPopup_save').click(); cy.checkNotification('Data created'); - cy.get( - ':nth-child(2) > .q-drawer > .q-drawer__content > .q-scrollarea > .q-scrollarea__container > .q-scrollarea__content', - ).should('be.visible'); + cy.url().should('include', '/basic-data'); }); });