Datagrid field with vocabulary, how to prevent 'duplicates

If I use a vocabulary for fields in DataGridField: Is there way to prevent duplicates (somehow removing entries from the vocabulary ‘on the fly’, or is the only option to ‘validate on save and show error (‘entries needs to be unique)

I think you use the vocabulary in a wrong way. for example, a keyword based vocabulary has not duplicate entries

You want to assign a value to each or part of the Vocabulary keys. The best is to have a List, and use a read only column. Example:

====Label=========Value====
| Geotechnical|    Some    |
| Voc entry 2 |            |
| Voc entry 3 |            |

The column on the left is readonly, the column on the right is made of inputs.

If the Vocabulary is too long and you just need to assign few value, DataGrid has javascript events so you can, for example, delete the selected vocab on other selects dropdown.

It is supposed to work a bit like this.

  1. We have a (kind of) Task (content type)
  2. Possible companies that are ‘related to that task’ comes from a regsitry entry (so I made it a vocabulary)
  3. Possible ‘company roles’ comes from another site (so I made that a a registry too, updated by reshapi when it changes):
  4. Company ‘Another’ should not have ‘multiple entries’ , so ‘Another’ can not have several ‘roles’

Thanks.
I did not figure out ‘how to use that’, but this seems to work:

$(document).on('focusin', '.datagridwidget-row select', function() { 
const $currentSelect = $(this);const $cell = $currentSelect.closest('.datagridwidget-cell');
// Get all classes from the cell
const classes = $cell.attr('class').split(/\s+/);
// Find the class that starts with "cell-"
const cellClass = classes.find(c => c.startsWith('cell-'));
if (!cellClass) return; // safety check

// Limit search to selects inside datagridwidget-cells with the same "cell-X" class
const selectedValues = [];

$(`.${cellClass} select`).not($currentSelect).each(function() {
  const val = $(this).val();
  if (val) selectedValues.push(val);
});

// Re-enable all options first
$currentSelect.find('option').each(function() {
  $(this).prop('disabled', false).show();
});

// Disable/hide already selected options
$currentSelect.find('option').each(function() {
  if (selectedValues.includes($(this).val())) {
    $(this).prop('disabled', true).hide(); // use .show() if you prefer visible but disabled
  }
});
  });
// Keep selects in same cell class synced on change$(document).on('change', '.datagridwidget-row select', function() {const $cell = $(this).closest('.datagridwidget-cell');const classes = $cell.attr('class').split(/\s+/);const cellClass = classes.find(c => c.startsWith('cell-'));if (!cellClass) return;
const $row = $(this).closest('.datagridwidget-row'); $row.find(`.datagridwidget-cell.${cellClass} select`).trigger('focusin');
});})(jQuery);
1 Like

I am trying to implement this same strategy in my project. However, it does not work properly in Plone 6.0.15 (ClassicUI) and DGF 3.04. My first column is set in display mode in the edit form. However, on save, I lose all values of the first column. The initial values of the DGF field is set via an event subscriber after the object is added.

Below is the code I used:

class IOrderDetails(model.Schema):

    directives.mode(IEditForm, order_category="display")
    order_category = schema.Choice(
        title="Category",
        vocabulary="app.common.OrderCategory",
        required=False,
    )

    amount = schema.Decimal(
        title="Amount",
        required=False,
    )
    
class IOrder(model.Schema):

    directives.omitted("order_items")
    directives.no_omit(IEditForm, "order_items")
    directives.no_omit(IDisplayForm, "order_items")
    directives.widget(
        "order_items",
        DataGridFieldFactory,
        ...
    )
    order_items = schema.List(
        title="Order Details",
        # defaultFactory=default_order_details,
        value_type=DictRow(
            title="Name",
            schema=IOrderDetails,
        ),
    )

Am I missing on other details? Is this a bug or an unimplemented feature?

Thanks.

I did it entirely in javascript. I think the problem with’ lost on save’ can happen ‘even without DFG’. (and also with ‘permissions’ on the field.