infor-design / enterprise-ng

Angular wrappers for IDS Enterprise components
Apache License 2.0
57 stars 84 forks source link

Datagrid: Using a custom lookup for grid lookup formatter causes cell to be disabled for user input. #1717

Open kkulick opened 3 months ago

kkulick commented 3 months ago

We have modal lookup components we use with the grid column lookup formatter to provide lookups for cell values. When the user selects a value from the modal lookup, the lookup closes and in the on close, it updates the data object property then calls grid.updateRow() to update the UI so the selected value displays. The problem is calling grid.updateRow(rowData) seems to put the cell into an uneditable state. The user cannot change the value or re-open the lookup. The browser must be refreshed to correct the issue.

We tried using updateCell() instead of updateRow() but it did not make any difference. Using commitCellEdit() did not solve the issue either.

Sample Application:

Steps:

  1. Download the sample application: \\USPOVWDEVVICKI2\Volume_C\KarlK\SohoDemos\VisualSohoSamples.zip
  2. Extract the sample application and run ../VisualSohoSamples>npm install to download and install the dependencies.
  3. Run the "VisualSohoSamples" angular application. ../VisualSohoSamples>ng serve
  4. Open the application source using VSCode and run a Chrome configuration.
  5. The browser should launch and the application main page should display.
  6. In the navigation bar click "Visual Table Demo" to load the component with the grid.
  7. With the grid displayed, click the lookup for the 'Issue Whs ID' column in the first row.
  8. The Warehouses lookup should display.
  9. Select a row for a warehouse that is different than what is in the cell currently. Ex: MMC-SEC Then click Accept.
  10. The modal lookup should close and the Issue Whs ID column cell value should change to the selected warehouse id.
  11. Notice the cell still has a focus border around it and the lookup button is half covered by the cell edge.
  12. Click in the cell. The cell will not go into edit mode for user input.
  13. Click on the lookup icon for the cell. Nothing happens. You cannot open the lookup.

Now you are stuck and have to refresh in the browser to recover.

Expected behavior We expect that the cell's value will display the value selected by the user in the lookup, the cell will be editable after the user performs the lookup and selects a value, and the user will be able to open the lookup again if they selected a wrong value. Any other cell values which were changed as the result of lookup on the same row should also be editable as mentioned above for the current cell. When a user selects a row from a lookup, it may necessitate updating other cells within the same row to remove or re-calculate a value.

Ultimately it would be great if the grid updated automatically with the changes made to the data object.

Version "ids-enterprise-ng": "^16.12.4",

Screenshots Lookup opened, select row and click apply. image Cell shows selected value, but the cell is now disabled for input. image

Platform

Additional context This is for VISUAL Shop Floor application. We need a resolution A.S.A.P. We are nearing the end of our development cycle and will be shipping product to customers within a couple months.

kkulick commented 3 months ago

The sample application was too large to attach. If you are unable to download it from the server mentioned in the defect, contact me or leave a comment and I can put it somewhere where you can download it.

AAlviar commented 2 months ago

Hi @kkulick - Can you have the sample application in StackBlitz?

kkulick commented 2 months ago

Hi @kkulick - Can you have the sample application in StackBlitz?

Is there a reason you cannot download the sample project and run it locally? Is it required to use StackBlitz? It could take a significant amount of time to port it to stackblitz which is cost prohibitive.

AAlviar commented 2 months ago

We encourage the use of StackBlitz to minimize the need to setup individual projects from multiple requestors, and isolate the issue. This will also ensure that we have a standard way to review issues across multiple teams. It also allows the team to review the issue without the need to install locally.

kkulick commented 2 months ago

I was unsuccessful porting the project to StackBlitz.

From: AAlviar @.> Sent: Thursday, July 4, 2024 2:05 AM To: infor-design/enterprise-ng @.> Cc: Karl Kulickowski @.>; Mention @.> Subject: Re: [infor-design/enterprise-ng] Datagrid: Using a custom lookup for grid lookup formatter causes cell to be disabled for user input. (Issue #1717)

Sent by an external sender. Please be cautious about clicking on links and opening attachments.

We encourage the use of StackBlitz to minimize the need to setup individual projects from multiple requestors, and isolate the issue. This will also ensure that we have a standard way to review issues across multiple teams. It also allows the team to review the issue without the need to install locally.

— Reply to this email directly, view it on GitHubhttps://github.com/infor-design/enterprise-ng/issues/1717#issuecomment-2208180331, or unsubscribehttps://github.com/notifications/unsubscribe-auth/A4SSTDBITQZVBAYMGJVTBT3ZKTQYBAVCNFSM6AAAAABJJD2JCKVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDEMBYGE4DAMZTGE. You are receiving this because you were mentioned.Message ID: @.**@.>>

tmcconechy commented 2 months ago

@yohannahbautista @AAlviar if you download the project and try to look at it does it give you what you need?

I wonder if we can change updateCell to somehow not refresh the cell if its in edit mode? Would that be what your thinking here @kkulick ?

I.E. Maybe we can simplify the problem? This is because of some custom code in the editor? Maybe if you post the code around it calling updateCell/row we can see if there is an easier way to make a test/reproduction for this.

One lookup example for it here https://main-enterprise.demo.design.infor.com/components/datagrid/test-editable-lookup.html wondering if we can use that code logic and figure out a test?

AAlviar commented 2 months ago

To access the project on MacOS

  1. You have to logged in to Infor's VPN
  2. Use Spotlight Search [CMD+Space] and enter smb://USPOVWDEVVICKI2/Volume_C/KarlK/SohoDemos
yohannahbautista commented 2 months ago

@kkulick @tmcconechy Hello, since I'm unsure what should be isolated and ignored. Is the exception happening a part of the bug or is it a result of parts of the code being commented out from what I've seen? It might take me a while to study the whole project and see how it behaves

image
tmcconechy commented 2 months ago

@yohannahbautista understood when the issue is on the whole project like that its hard to isolate and fix the issue. see what you can do.

I would focus on a) any errors in our code which might be fixable b) the updateRow or updateCell call. If we can make those work ok while the editor is both open and closed when its called

Something like that

kkulick commented 2 months ago

@yohannahbautista @AAlviar if you download the project and try to look at it does it give you what you need?

I wonder if we can change updateCell to somehow not refresh the cell if its in edit mode? Would that be what your thinking here @kkulick ?

I.E. Maybe we can simplify the problem? This is because of some custom code in the editor? Maybe if you post the code around it calling updateCell/row we can see if there is an easier way to make a test/reproduction for this.

One lookup example for it here https://main-enterprise.demo.design.infor.com/components/datagrid/test-editable-lookup.html wondering if we can use that code logic and figure out a test?

I'm not sure if the second question was for me, but I would expect the cell to be updated with the value in the bound property after the user selects the value and the modal is closed. I would not expect that process to lock up the cell for further edits.

tmcconechy commented 2 months ago

Yeah, I get it @kkulick our problem has been translating the "App" into a test case where we can work it out. Part of this is us discussing. Im going to see if i can find some time to help make a reduced test case.

kkulick commented 2 months ago

@kkulick @tmcconechy Hello, since I'm unsure what should be isolated and ignored. Is the exception happening a part of the bug or is it a result of parts of the code being commented out from what I've seen? It might take me a while to study the whole project and see how it behaves image

I just looked at the exception you are seeing here (I think). I believe all you need to do to get rid of that exception is to change the gridOptions property declaration in the visual-browse-lookup.components.ts file and initialize it to undefined instead of {}. That way the table component will not be created by angular until it is set during initialization of the table configuration. It doesn't fix the cell locking issue though. image

tmcconechy commented 2 months ago

@kkulick i pulled this down it is a simpler project than i expected but wondering a few things. FYI @yohannahbautista see updateActiveRow in that project?

a) Are you looking for a patch on 16.x as thats almost a second fix? Or is to latest OK? Did this ever work? b) I see when you click in the editor the lookup is missing? is that also problem? c) when i leave the field i get an error on if (rule.async) { is that an issue? If so you might just need to add the new options to custom rules i.e. type and id and that should fix (depending on end version)

{
        check: function (value, field, grid) {
            return false;
        },
        id: 'custom',
        type: 'error',
        message: 'Test Error - Anything you enter will be wrong'
      }

d) dont seem to be able to stop on this._gridOptions.columns.forEach((c) => { and find the stack trace but when i jump to updateActiveRow can see why this happens e) Noting that b and d issue seems fix if dont do this updateActiveRow needs the fix

    // col.EditorOptions = {
    //   editable: false,
    //   click: warehouseLookupClickFunction
    // }

It looks like the edit is stuck because it didnt exist edit mode. What if you do something more like when updating the cell after the editor is clicked i.e. commit the edit first then try update cell so the update is more minimal then setActiveCell if needed.

      click: function (event, lookup, clickArguments) {
        grid.commitCellEdit();
        // cause an error here to simulate
        // grid.updateCell(0, 1, test);

        // Attempted Fix
        grid.updateCell(0, 1, 'test');
        grid.setActiveCell(0, 1);
      },

NOTE TO SELF: Also can partly reproduce in the enterprise example so posting here (test-filter-lookup-click-function.html)


<div class="row">
  <div class="twelve columns">
    <div id="datagrid">
    </div>
  </div>
</div>

<script>
  $('body').one('initialized', function () {
    var grid,
      columns = [],
      data = [];

    var numericFilterConditions= [ 'equals', 'does-not-equal', 'is-empty', 'is-not-empty', 'less-than', 'less-equals', 'greater-than', 'greater-equals' ];

    // Define Some Sample Data
    data.push({ id: 1, productId: undefined, productName: 'Compressor', inStock: true, activity:  'Assemble Paint', quantity: 1, price: 410.99, orderDate: new Date(2014, 12, 8), action: 'Action', status: 'Error'});
    data.push({ id: 2, productId: 2241202, productName: '1 Different Compressor', inStock: true, activity:  'Inspect and Repair', quantity: 2, price: 310.99, orderDate: new Date(2015, 7, 3), action: 'On Hold', status: 'Error'});
    data.push({ id: 3, productId: 2342203, productName: 'Compressor', inStock: true, activity:  'Inspect and Repair', quantity: 1, price: 620.99, orderDate: new Date(2014, 6, 3), action: 'Action', status: 'Error'});
    data.push({ id: 4, productId: 2445204, productName: undefined, inStock: false, activity:  'Assemble Paint', quantity: 3, price: 1210.99, orderDate: new Date(2015, 3, 3), action: 'Action', status: 'Confirmed'});
    data.push({ id: 5, productId: 2542205, productName: 'I Love Compressors', inStock: true, activity:  'Inspect and Repair', quantity: 4, price: 810.99, orderDate: new Date(2015, 5, 5), action: 'On Hold', status: 'Confirmed'});
    data.push({ id: 5, productId: 2642205, productName: 'Air Compressors', inStock: false, activity:  'Inspect and Repair', quantity: 41, price: 1120.99, orderDate: new Date(2014, 6, 9), action: 'On Hold', status: 'Error'});
    data.push({ id: 6, productId: null, productName: 'Some Compressor', inStock: true, activity:  'inspect and Repair', quantity: 41, price: 123.99, orderDate: new Date(2014, 6, 9), action: 'On Hold', status: 'Confirmed'});
    data.push({ id: 7, productId: null, productName: null, activity:  '', quantity: null, price: null, orderDate: null, action: 'Blank Row', status: 'Confirmed'});
    data.push({ id: 8, productId: null, productName: null, activity:  null, quantity: null, price: null, orderDate: null, action: 'Blank Row', status: 'Confirmed'});

    var statuses = [{id: '', value: '', label:'&nbsp;'},
      {id:'Confirmed', value:'Confirmed', label:'Confirmed'},
      {id:'Error', value:'Error', label:'Error'}];

    var activities = [{id: 'Assemble Paint', value:'Assemble Paint', label: 'Assemble Paint'},
      {id: '', value: '', label: 'Default Activity'},
      {id: 'Inspect and Repair', value:'Inspect and Repair', label: 'Inspect and Repair'}];

    //lookup data
    var idLookupOptions, nameLookupOptions;

    idLookupOptions = {
      editable: false,
      click: function (event, lookup, clickArguments) {
        grid.commitCellEdit();
        // cause an error here to similate
        // grid.updateCell(0, 1, test);

        // Attempted Fix
        grid.updateCell(0, 1, 'test');
        grid.setActiveCell(0, 1);
      },

      options: {
        selectable: 'single', //multiselect or single
        toolbar: {title: 'Products', results: true, dateFilter: false ,keywordFilter: false, actions: true, views: true , rowHeight: true}
      }
    };

    nameLookupOptions = {
      // field: 'productName',
      field: function (row, field, grid) {
        return row.productName;
      },
      match: function (value, row, field, grid) {
        return (row.productName) === value;
      },
      beforeShow: function (api, response) {
        var url = '{{basepath}}api/lookupInfo';

        $.getJSON(url, function(data) {
          api.settings.options.columns = data[0].columns;
          api.settings.options.dataset = data[0].dataset;
          response();
        });
      },

      options: {
        selectable: 'single', //multiselect or single
        toolbar: {title: 'Products', results: true, dateFilter: false ,keywordFilter: false, actions: true, views: true , rowHeight: true}
      }
    };

    // Define Columns for the Grid.
    columns.push({ id: 'id', name: 'Id', field: 'id', formatter: Soho.Formatters.Readonly, filterType: 'text'});
    columns.push({ id: 'productId', name: 'Product Id', field: 'productId', formatter: Soho.Formatters.Lookup, editor: Soho.Editors.Lookup, validate: 'required', editorOptions: idLookupOptions, width: 120, filterType: 'lookup', filterConditions: numericFilterConditions });
    columns.push({ id: 'productName', name: 'Product Name', field: 'productName',  formatter: Soho.Formatters.Hyperlink, editorOptions: nameLookupOptions, width: 180, filterType: 'lookup'});
    columns.push({ id: 'activity', name: 'Activity', field: 'activity', formatter: Soho.Formatters.Dropdown, filterType: 'multiselect', options: activities, editorOptions: {showSelectAll: true}});
    columns.push({ id: 'quantity', name: 'Qty', field: 'quantity', align: 'right', filterType: 'integer'});
    columns.push({ id: 'orderDate', name: 'Order Date', field: 'orderDate', formatter: Soho.Formatters.Date, dateFormat: 'MM/dd/yyyy', filterType: 'date', width: 250});
    columns.push({ id: 'inStock', name: 'In Stock', field: 'inStock', formatter: Soho.Formatters.Checkbox, align: 'center', filterType: 'checkbox'});
    columns.push({ id: 'status', name: 'Status', align: 'center', field: 'status', formatter: Soho.Formatters.Alert, filterType: 'select', editorOptions: {clearable: true}, options: statuses, ranges: [{'value':'Confirmed', 'classes': 'success', text: 'Confirmed'}, {'value':'Error', 'classes': 'error', text: 'Error'}]});
    columns.push({ id: 'price',  name: 'Price', field: 'price', formatter: Soho.Formatters.Decimal, filterType: 'decimal', numberFormat: {minimumFractionDigits: 3, maximumFractionDigits: 3}, editor: Soho.Editors.Input, mask: '###,####.000'});

    // Init and get the api for the grid
    grid = $('#datagrid').datagrid({
      columns: columns,
      dataset: data,
      filterable: true,
      selectable: 'single',
      editable: true,
      emptyMessage: {title: Soho.Locale.translate('NoData'), info: Soho.Locale.translate('NoDataFilter'), icon: 'icon-empty-no-data-new'},
      toolbar: {title: 'Filterable Datagrid', filterRow: true, results: true, dateFilter: false ,keywordFilter: false, actions: true, views: false, rowHeight: true, collapsibleFilter: false}
    }).on('filtered', function (e, args) {
      console.log('filter ran', args);
    }).data('datagrid');
  });

</script>
kkulick commented 2 months ago

@kkulick i pulled this down it is a simpler project than i expected but wondering a few things. FYI @yohannahbautista see updateActiveRow in that project?

a) Are you looking for a patch on 16.x as thats almost a second fix? Or is to latest OK? Did this ever work? b) I see when you click in the editor the lookup is missing? is that also problem? c) when i leave the field i get an error on if (rule.async) { is that an issue? If so you might just need to add the new options to custom rules i.e. type and id and that should fix (depending on end version)

{
          check: function (value, field, grid) {
              return false;
          },
        id: 'custom',
        type: 'error',
          message: 'Test Error - Anything you enter will be wrong'
      }

d) dont seem to be able to stop on this._gridOptions.columns.forEach((c) => { and find the stack trace but when i jump to updateActiveRow can see why this happens e) Noting that b and d issue seems fix if dont do this updateActiveRow needs the fix

    // col.EditorOptions = {
    //   editable: false,
    //   click: warehouseLookupClickFunction
    // }

It looks like the edit is stuck because it didnt exist edit mode. What if you do something more like when updating the cell after the editor is clicked i.e. commit the edit first then try update cell so the update is more minimal then setActiveCell if needed.

      click: function (event, lookup, clickArguments) {
        grid.commitCellEdit();
        // cause an error here to simulate
        // grid.updateCell(0, 1, test);

        // Attempted Fix
        grid.updateCell(0, 1, 'test');
        grid.setActiveCell(0, 1);
      },

NOTE TO SELF: Also can partly reproduce in the enterprise example so posting here (test-filter-lookup-click-function.html)


<div class="row">
  <div class="twelve columns">
    <div id="datagrid">
    </div>
  </div>
</div>

<script>
  $('body').one('initialized', function () {
    var grid,
      columns = [],
      data = [];

    var numericFilterConditions= [ 'equals', 'does-not-equal', 'is-empty', 'is-not-empty', 'less-than', 'less-equals', 'greater-than', 'greater-equals' ];

    // Define Some Sample Data
    data.push({ id: 1, productId: undefined, productName: 'Compressor', inStock: true, activity:  'Assemble Paint', quantity: 1, price: 410.99, orderDate: new Date(2014, 12, 8), action: 'Action', status: 'Error'});
    data.push({ id: 2, productId: 2241202, productName: '1 Different Compressor', inStock: true, activity:  'Inspect and Repair', quantity: 2, price: 310.99, orderDate: new Date(2015, 7, 3), action: 'On Hold', status: 'Error'});
    data.push({ id: 3, productId: 2342203, productName: 'Compressor', inStock: true, activity:  'Inspect and Repair', quantity: 1, price: 620.99, orderDate: new Date(2014, 6, 3), action: 'Action', status: 'Error'});
    data.push({ id: 4, productId: 2445204, productName: undefined, inStock: false, activity:  'Assemble Paint', quantity: 3, price: 1210.99, orderDate: new Date(2015, 3, 3), action: 'Action', status: 'Confirmed'});
    data.push({ id: 5, productId: 2542205, productName: 'I Love Compressors', inStock: true, activity:  'Inspect and Repair', quantity: 4, price: 810.99, orderDate: new Date(2015, 5, 5), action: 'On Hold', status: 'Confirmed'});
    data.push({ id: 5, productId: 2642205, productName: 'Air Compressors', inStock: false, activity:  'Inspect and Repair', quantity: 41, price: 1120.99, orderDate: new Date(2014, 6, 9), action: 'On Hold', status: 'Error'});
    data.push({ id: 6, productId: null, productName: 'Some Compressor', inStock: true, activity:  'inspect and Repair', quantity: 41, price: 123.99, orderDate: new Date(2014, 6, 9), action: 'On Hold', status: 'Confirmed'});
    data.push({ id: 7, productId: null, productName: null, activity:  '', quantity: null, price: null, orderDate: null, action: 'Blank Row', status: 'Confirmed'});
    data.push({ id: 8, productId: null, productName: null, activity:  null, quantity: null, price: null, orderDate: null, action: 'Blank Row', status: 'Confirmed'});

    var statuses = [{id: '', value: '', label:'&nbsp;'},
      {id:'Confirmed', value:'Confirmed', label:'Confirmed'},
      {id:'Error', value:'Error', label:'Error'}];

    var activities = [{id: 'Assemble Paint', value:'Assemble Paint', label: 'Assemble Paint'},
      {id: '', value: '', label: 'Default Activity'},
      {id: 'Inspect and Repair', value:'Inspect and Repair', label: 'Inspect and Repair'}];

    //lookup data
    var idLookupOptions, nameLookupOptions;

    idLookupOptions = {
      editable: false,
      click: function (event, lookup, clickArguments) {
        grid.commitCellEdit();
        // cause an error here to similate
        // grid.updateCell(0, 1, test);

        // Attempted Fix
        grid.updateCell(0, 1, 'test');
        grid.setActiveCell(0, 1);
      },

      options: {
        selectable: 'single', //multiselect or single
        toolbar: {title: 'Products', results: true, dateFilter: false ,keywordFilter: false, actions: true, views: true , rowHeight: true}
      }
    };

    nameLookupOptions = {
      // field: 'productName',
      field: function (row, field, grid) {
        return row.productName;
      },
      match: function (value, row, field, grid) {
        return (row.productName) === value;
      },
      beforeShow: function (api, response) {
        var url = '{{basepath}}api/lookupInfo';

        $.getJSON(url, function(data) {
          api.settings.options.columns = data[0].columns;
          api.settings.options.dataset = data[0].dataset;
          response();
        });
      },

      options: {
        selectable: 'single', //multiselect or single
        toolbar: {title: 'Products', results: true, dateFilter: false ,keywordFilter: false, actions: true, views: true , rowHeight: true}
      }
    };

    // Define Columns for the Grid.
    columns.push({ id: 'id', name: 'Id', field: 'id', formatter: Soho.Formatters.Readonly, filterType: 'text'});
    columns.push({ id: 'productId', name: 'Product Id', field: 'productId', formatter: Soho.Formatters.Lookup, editor: Soho.Editors.Lookup, validate: 'required', editorOptions: idLookupOptions, width: 120, filterType: 'lookup', filterConditions: numericFilterConditions });
    columns.push({ id: 'productName', name: 'Product Name', field: 'productName',  formatter: Soho.Formatters.Hyperlink, editorOptions: nameLookupOptions, width: 180, filterType: 'lookup'});
    columns.push({ id: 'activity', name: 'Activity', field: 'activity', formatter: Soho.Formatters.Dropdown, filterType: 'multiselect', options: activities, editorOptions: {showSelectAll: true}});
    columns.push({ id: 'quantity', name: 'Qty', field: 'quantity', align: 'right', filterType: 'integer'});
    columns.push({ id: 'orderDate', name: 'Order Date', field: 'orderDate', formatter: Soho.Formatters.Date, dateFormat: 'MM/dd/yyyy', filterType: 'date', width: 250});
    columns.push({ id: 'inStock', name: 'In Stock', field: 'inStock', formatter: Soho.Formatters.Checkbox, align: 'center', filterType: 'checkbox'});
    columns.push({ id: 'status', name: 'Status', align: 'center', field: 'status', formatter: Soho.Formatters.Alert, filterType: 'select', editorOptions: {clearable: true}, options: statuses, ranges: [{'value':'Confirmed', 'classes': 'success', text: 'Confirmed'}, {'value':'Error', 'classes': 'error', text: 'Error'}]});
    columns.push({ id: 'price',  name: 'Price', field: 'price', formatter: Soho.Formatters.Decimal, filterType: 'decimal', numberFormat: {minimumFractionDigits: 3, maximumFractionDigits: 3}, editor: Soho.Editors.Input, mask: '###,####.000'});

    // Init and get the api for the grid
    grid = $('#datagrid').datagrid({
      columns: columns,
      dataset: data,
      filterable: true,
      selectable: 'single',
      editable: true,
      emptyMessage: {title: Soho.Locale.translate('NoData'), info: Soho.Locale.translate('NoDataFilter'), icon: 'icon-empty-no-data-new'},
      toolbar: {title: 'Filterable Datagrid', filterRow: true, results: true, dateFilter: false ,keywordFilter: false, actions: true, views: false, rowHeight: true, collapsibleFilter: false}
    }).on('filtered', function (e, args) {
      console.log('filter ran', args);
    }).data('datagrid');
  });

</script>

a) Are you looking for a patch on 16.x as thats almost a second fix? Or is to latest OK? Did this ever work? Yes, we need it fixed in 16.x. Our application is in QA test now. Upgrading to the latest may be a breaking change. I swear this was working ok in some places but not in others in a prior version of IDS NG but I can't prove that. But now it seems to be broken everywhere. I had thought it may have been something we did, but when I tried to find something that our code might have done, I couldn't see anything that should cause the field to lock up like that and there was no exception generated.

b) I see when you click in the editor the lookup is missing? is that also problem? I'm not sure what you mean by this? Can you explain?

c) when i leave the field i get an error on if (rule.async) { is that an issue? If so you might just need to add the new options to custom rules i.e. type and id and that should fix (depending on end version) No, I don't think that's an issue. It's because the validator function does not exist. This was created as a sample from our actual application code which is much more extensive. To get rid of that error just comment out the three custom validator references in the initTableConfig() method. That way it won't try to call the validators that are not implemented in the demo app. image

tmcconechy commented 2 months ago

ok got it. Regardless i cant see why it would have worked but anyways let's ignore that and fix it.

So The most important thing i found was if you try this logic to update the row in warehouseLookupClick while it's in editmode in the click event instead of calling updateActiveRow

So use updateCell but commitCellEdit first and then call setActiveCell if you need to restore the focus state on the cell?

      click: function (event, lookup, clickArguments) {
        grid.commitCellEdit();
        // cause an error here to simulate
        // grid.updateCell(0, 1, test);

        // Attempted Fix
        grid.updateCell(0, 1, 'test');
        grid.setActiveCell(0, 1);
      },

It seems to work for me in an isolated test but you would have to work it into your logic. Its really caused by whats in the updateActiveRow function instead of calling updateRow. I can attempt it myself if it doesnt work.

kkulick commented 2 months ago

updateCell() does not exist on the NG SohoDataGridComponent image I think there's some hacky way to get to it via accessing it via jquery and JavaScript. I'll see if I can figure that out.

tmcconechy commented 2 months ago

@kkulick use any i.e (this.table.dataGrid as any).updateCell() note type was added in later versions https://github.com/infor-design/enterprise-ng/blob/main/projects/ids-enterprise-typings/lib/datagrid/soho-datagrid.d.ts#L1133

kkulick commented 2 months ago

That doesn't work. It gives a runtime exception for the same error updateCell() does not exist.
image

I tried calling the function table.updateFocusRowCellById() which calls updateCell() via the hacky jquery way. That updated the cell but still locks it up and prevents further edits. image

image

kkulick commented 2 months ago

Ok, if I add the other calls before and after updateCell() like you mentioned, it seems to work. image

kkulick commented 2 months ago

FYI: If using the demo project, and you want to be able to type in the warehouse id, you will need to change the editor options for the column to editable: true. image

tmcconechy commented 2 months ago

@kkulick it seems to "worK" for me if i just uncomment this line in warehouseLookupClick

        if (resp != 'CANCEL') {
          // debugger;
          // try committing cell edit before changing value
          this.table.dataGrid.commitCellEdit(); // this does not work.  If we do this the value in the cell does not get updated.

I can hover the cell and edit the lookup more than once. But there is two errors. One in checkForComponentEditors which i could maybe add a guard on it (but seems to not matter).

And the second in validateCells. For this one can you tell me where the validation code is setup? I think you just need to add the id and type to the validation as noted above.

Aside from that what if we go backwards here a bit and do it exactly like the regular lookup example https://github.com/infor-design/enterprise-ng/blob/main/src/app/datagrid/datagrid-lookup-dialog.demo.ts

What would you be missing if you did that? Is it just loading data? If so can maybe try the before open on the lookup or some other way?

yohannahbautista commented 2 months ago

@kkulick it seems to "worK" for me if i just uncomment this line in warehouseLookupClick

        if (resp != 'CANCEL') {
          // debugger;
          // try committing cell edit before changing value
          this.table.dataGrid.commitCellEdit(); // this does not work.  If we do this the value in the cell does not get updated.

I can hover the cell and edit the lookup more than once. But there is two errors. One in checkForComponentEditors which i could maybe add a guard on it (but seems to not matter).

And the second in validateCells. For this one can you tell me where the validation code is setup? I think you just need to add the id and type to the validation as noted above.

Aside from that what if we go backwards here a bit and do it exactly like the regular lookup example https://github.com/infor-design/enterprise-ng/blob/main/src/app/datagrid/datagrid-lookup-dialog.demo.ts

What would you be missing if you did that? Is it just loading data? If so can maybe try the before open on the lookup or some other way?

@tmcconechy Hello, basing this on this example page: https://github.com/infor-design/enterprise-ng/blob/main/src/app/datagrid/datagrid-lookup-click-function.demo.ts It looks like it works (being able to edit again and also being able to update cell) if you put it in the apply method on the modal service:

(this.dlgSvc as any).activeModalRef.apply(() => {
      this.dlgSvc.onClose
      .subscribe(resp => {
        if (resp != 'CANCEL') {
          this.table.dataGrid.commitCellEdit();

          this.selectedItem.UserIssueWhsID = resp.data.Key1;
          this.selectedItem.UserIssueLocID = '';

          this.table.updateActiveRow(this.selectedItem);
        }
      });
 })
kkulick commented 2 months ago

If I change the onClose() in the demo project like above, to call commitCellEdit() then updateActiveRow(). It seems to work. The cell does not get stuck in edit mode. Would there be instructions on how to run the project file in vsCode for the above links? I get errors if I try to run it via vsCode. It can't seem to find @angular/common for starters.
image

yohannahbautista commented 2 months ago

@kkulick Hello, you can find instructions to run the IDS NG project here: https://github.com/infor-design/enterprise-ng/blob/main/docs/DEVELOPER.md

kkulick commented 2 months ago

@kkulick it seems to "worK" for me if i just uncomment this line in warehouseLookupClick

        if (resp != 'CANCEL') {
          // debugger;
          // try committing cell edit before changing value
          this.table.dataGrid.commitCellEdit(); // this does not work.  If we do this the value in the cell does not get updated.

I can hover the cell and edit the lookup more than once. But there is two errors. One in checkForComponentEditors which i could maybe add a guard on it (but seems to not matter). And the second in validateCells. For this one can you tell me where the validation code is setup? I think you just need to add the id and type to the validation as noted above. Aside from that what if we go backwards here a bit and do it exactly like the regular lookup example https://github.com/infor-design/enterprise-ng/blob/main/src/app/datagrid/datagrid-lookup-dialog.demo.ts What would you be missing if you did that? Is it just loading data? If so can maybe try the before open on the lookup or some other way?

@tmcconechy Hello, basing this on this example page: https://github.com/infor-design/enterprise-ng/blob/main/src/app/datagrid/datagrid-lookup-click-function.demo.ts It looks like it works (being able to edit again and also being able to update cell) if you put it in the apply method on the modal service:

(this.dlgSvc as any).activeModalRef.apply(() => {
      this.dlgSvc.onClose
      .subscribe(resp => {
        if (resp != 'CANCEL') {
          this.table.dataGrid.commitCellEdit();

          this.selectedItem.UserIssueWhsID = resp.data.Key1;
          this.selectedItem.UserIssueLocID = '';

          this.table.updateActiveRow(this.selectedItem);
        }
      });
 })

Regarding the validator setup. The validator for the warehouse id cell, executes an http request to select the warehouse information from the database for the warehouse id entered by the user. Ordinarily when selecting from a lookup, it doesn't seem the validator runs. But when calling the commitCellEdit() before updating the cell with the value the user selected, the commitCellEdit() causes the validator to execute. This is a problem because when the validator runs, the property value in the "item" has not changed to the value selected by the user. Even if I set the selected rows data object property, the validator still has the old value. So, the validator requests the wrong warehouse information and updates the data object property and cell with the warehouse id in the http response. Why do we do this you ask? We do it because Sql Server is installed as "case insensitive" so, although the primary key value for the WAREHOUSE.ID field in the database may be "MMC-Main", the user can type in "mmc-main" and Sql Server will return the record for "MMC-Main". So, the application corrects the foreign key value entered by the user as "mmc-main" with the primary key value of "MMC-Main". We do this so that any string comparisons being made outside of Sql Server such as in code will have the correct (same) case for the foreign key string and primary key.

I don't know why the lookup was working for me the other day and setting the value in the cell, but today, it is no longer doing it. And I know it was doing it because I tested it several times. Maybe running npm install updated something.

Anyway, the validator is configured like so: Register the validators image

image

image

image

Would it be possible to add a "cancelCellEdit()" method which could be called that would cancel the edit mode of the cell but not trigger the validator to execute? If the on close of the modal called a "cancelCellEdit()" and then updated the value then committed the change (if it needed to), would that resolve the timing issue there seems to be with the data object values being updated and validator method being called? So the validator would have the correct value as selected by the user.

kkulick commented 2 months ago

@kkulick it seems to "worK" for me if i just uncomment this line in warehouseLookupClick

        if (resp != 'CANCEL') {
          // debugger;
          // try committing cell edit before changing value
          this.table.dataGrid.commitCellEdit(); // this does not work.  If we do this the value in the cell does not get updated.

I can hover the cell and edit the lookup more than once. But there is two errors. One in checkForComponentEditors which i could maybe add a guard on it (but seems to not matter). And the second in validateCells. For this one can you tell me where the validation code is setup? I think you just need to add the id and type to the validation as noted above. Aside from that what if we go backwards here a bit and do it exactly like the regular lookup example https://github.com/infor-design/enterprise-ng/blob/main/src/app/datagrid/datagrid-lookup-dialog.demo.ts What would you be missing if you did that? Is it just loading data? If so can maybe try the before open on the lookup or some other way?

@tmcconechy Hello, basing this on this example page: https://github.com/infor-design/enterprise-ng/blob/main/src/app/datagrid/datagrid-lookup-click-function.demo.ts It looks like it works (being able to edit again and also being able to update cell) if you put it in the apply method on the modal service:

(this.dlgSvc as any).activeModalRef.apply(() => {
      this.dlgSvc.onClose
      .subscribe(resp => {
        if (resp != 'CANCEL') {
          this.table.dataGrid.commitCellEdit();

          this.selectedItem.UserIssueWhsID = resp.data.Key1;
          this.selectedItem.UserIssueLocID = '';

          this.table.updateActiveRow(this.selectedItem);
        }
      });
 })

Regarding the validator setup. The validator for the warehouse id cell, executes an http request to select the warehouse information from the database for the warehouse id entered by the user. Ordinarily when selecting from a lookup, it doesn't seem the validator runs. But when calling the commitCellEdit() before updating the cell with the value the user selected, the commitCellEdit() causes the validator to execute. This is a problem because when the validator runs, the property value in the "item" has not changed to the value selected by the user. Even if I set the selected rows data object property, the validator still has the old value. So, the validator requests the wrong warehouse information and updates the data object property and cell with the warehouse id in the http response. Why do we do this you ask? We do it because Sql Server is installed as "case insensitive" so, although the primary key value for the WAREHOUSE.ID field in the database may be "MMC-Main", the user can type in "mmc-main" and Sql Server will return the record for "MMC-Main". So, the application corrects the foreign key value entered by the user as "mmc-main" with the primary key value of "MMC-Main". We do this so that any string comparisons being made outside of Sql Server such as in code will have the correct (same) case for the foreign key string and primary key.

I don't know why the lookup was working for me the other day and setting the value in the cell, but today, it is no longer doing it. And I know it was doing it because I tested it several times. Maybe running npm install updated something.

Anyway, the validator is configured like so: Register the validators image

image

image

image

Would it be possible to add a "cancelCellEdit()" method which could be called that would cancel the edit mode of the cell but not trigger the validator to execute? If the on close of the modal called a "cancelCellEdit()" and then updated the value then committed the change (if it needed to), would that resolve the timing issue there seems to be with the data object values being updated and validator method being called? So the validator would have the correct value as selected by the user.

The problem with subscribing to the lookupSelection in the .apply() is that it is updating the parent before the user was given the option to cancel. In your example you only have a "Cancel" button. But if you added an "Apply" button also to allow the user to select a row then click Apply or Cancel, the cancel would not work because the parent was already updated by the subscription to the lookupSelection event emitter which fired on the user clicking a row.

tmcconechy commented 2 months ago

@kkulick a bit confused on the way the last few comments came up? Whats the easiest quickest way we can add something that will make this work? Seems like a hard situation we cant really find something for?

Is it just to now add cancelCellEdit for datagrid as opposed to commitCellEdit? As we can do that.