infor-design / enterprise

Enterprise-grade component library for the Infor Design System
https://design.infor.com
Apache License 2.0
130 stars 80 forks source link

Datagrid selectRows() crashes when passing a single number grid.selectRows(1); #756

Closed pwpatton closed 5 years ago

pwpatton commented 5 years ago

Describe the bug datagrid.js used to allow a single number to be passed to selectRows() but it now fails assuming it's an html element object rather than checking for a number type. If you pass in a single number value this error is thrown.

datagrid.js:5996 Uncaught TypeError: row.index is not a function
    at Datagrid.selectRows (datagrid.js:5996)
    at HTMLDivElement.<anonymous> (test-contextmenu-custom.html:2057)
    at HTMLDivElement.dispatch (jquery-3.3.1.js:5183)
    at HTMLDivElement.elemData.handle (jquery-3.3.1.js:4991)
    at Object.trigger (jquery-3.3.1.js:8249)
    at HTMLDivElement.<anonymous> (jquery-3.3.1.js:8327)
    at Function.each (jquery-3.3.1.js:354)
    at jQuery.fn.init.each (jquery-3.3.1.js:189)
    at jQuery.fn.init.trigger (jquery-3.3.1.js:8326)
    at Datagrid.triggerRowEvent (datagrid.js:4382)

To Reproduce Steps to reproduce the behavior:

  1. Use attached sample and save to project.
  2. navigate to attached example
  3. right click on a row to get it to select and show as context menu.
  4. See error

Expected behavior Single number should be allowed as input to selectRows

Platform

Additional context multiple or mixes selection must be turned on. A work around is to put it in an array but this used to work.

pwpatton commented 5 years ago
{{={{{ }}}=}}

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

<ul id="grid-actions-menu" class="popupmenu">
  <li><a href="#">Action One</a></li>
  <li><a href="#">Action Two</a></li>
  <li><a href="#">Action Three</a>
    <ul class="popupmenu">
      <li><a href="#">Action Four</a></li>
      <li><a href="#">Action Five</a></li>
    </ul>
  </li>
</ul>

<ul id="grid-header-menu" class="popupmenu">
  <li><a href="#">Split</a></li>
  <li><a href="#">Sort</a></li>
  <li><a href="#">Hide</a></li>
</ul>

<script>
  $('body').on('initialized', function () {
    //Locale.set('en-US').done(function () {
    var grid,
      columns = [],
      data = [];

    // Some Sample Data
    data.push({ id: 1, productId: 2142201, productName: 'Compressor', activity:  'Assemble Paint', quantity: 1, price: 210.99, status: 'OK', orderDate: new Date(2014, 12, 8), action: 'Action', ordered: 1, setting: {optionOne: 'One', optionTwo: 'One'}});
    data.push({ id: 2, productId: 2241202, productName: 'Different Compressor', activity:  'Inspect and Repair', quantity: 2, price: 210.99, status: '', orderDate: new Date(2015, 7, 3), action: 'On Hold', ordered: true, setting: {optionOne: 'One', optionTwo: 'One'}});
    data.push({ id: 3, productId: 2342203, productName: 'Compressor', activity:  'Inspect and Repair', quantity: 1, price: 120.99, status: null, orderDate: new Date(2014, 6, 3), action: 'Action', ordered: true, comment: 'Dynamic harness out-of-the-box /n syndicate models deliver. Disintermediate, technologies /n scale deploy social streamline, methodologies, killer podcasts innovate. Platforms A-list disintermediate, value visualize dot-com /n tagclouds platforms incentivize interactive vortals disintermediate networking, webservices envisioneer; tag share value-added, disintermediate, revolutionary.'});
    data.push({ id: 4, productId: 2445204, productName: 'Another Compressor', activity:  'Assemble Paint', quantity: 9, price: 210.99, status: 'OK', orderDate: new Date(2015, 3, 3), action: 'Action', ordered: true});
    data.push({ id: 5, productId: 2542205, productName: 'I Love Compressors', activity:  'Inspect and Repair', quantity: 4, price: 18.00, status: 'OK', orderDate: new Date(2015, 5, 5), action: 'On Hold', ordered: false});
    data.push({ id: 5, productId: 2642205, productName: 'Air Compressors', activity:  'Inspect and Repair', quantity: 18, price: 9, status: 'OK', orderDate: new Date(2014, 6, 9), action: 'On Hold', comment: 'B2C ubiquitous communities maximize B2C synergies extend dynamic revolutionize, world-class robust peer-to-peer. Action-items semantic technologies clicks-and-mortar iterate min'});
    data.push({ id: 6, productId: 2642206, productName: 'Some Compressor', activity:  'inspect and Repair', quantity: 41, price: 123.99, status: 'OK', orderDate: new Date(2014, 6, 9), action: 'On Hold', ordered: 0});
    data.push({ id: 7, productId: 2642206, productName: 'Some Compressor', activity:  'inspect and Repair', quantity: 41, price: '100.99', status: 'OK', orderDate: new Date(2014, 6, 9, 12, 12, 12), action: 'On Hold', ordered: 0});

    //Define Columns for the Grid.

    var cellTemplate = '<p class="datagrid-row-heading">{{productId}}</p>' +
      '<p class="datagrid-row-subheading">{{productName}}</p>';

    columns.push({ id: 'drilldown', name: 'Drill In', field: '', width: 80, formatter: Formatters.Drilldown, cssClass: 'l-center-text', click: function (e, args) {console.log('clicked', args);}});
    //columns.push({ id: 'productName', name: 'Product Name', field: 'productName', width: 125, formatter: Formatters.Template, template: cellTemplate});
    columns.push({ id: 'productId', hidden: true, name: 'Product Id', field: 'productId', width: 140, formatter: Formatters.Readonly });
    columns.push({ id: 'productDesc', name: 'Product Desc', sortable: false, field: 'productName', width: 125, formatter: Formatters.Hyperlink, click: function (e, args) {console.log('link was clicked', args);}});
    columns.push({ id: 'activity', name: 'Activity', field: 'activity', width: 160});
    columns.push({ id: 'quantity', name: 'Quantity', field: 'quantity', width: 200});
    columns.push({ id: 'price1', name: 'Price', field: 'price', width: 100, formatter: Formatters.Decimal});
    columns.push({ id: 'price2', name: 'Price', field: 'price', width: 100, formatter: Formatters.Integer});
    columns.push({ id: 'orderDate', name: 'Order Date', field: 'orderDate', formatter: Formatters.Date, width: 100, dateFormat: 'yy/MM/dd'});

    //{date: 'datetime'
    columns.push({ id: 'status', name: 'Status', field: 'status', width: 200, formatter: Formatters.Text});
    columns.push({ id: 'alert', name: 'Alert', field: 'quantity', width: 200, formatter: Formatters.Alert, ranges: [{'min': 0, 'max': 8, 'classes': 'info', 'text': 'value'}, {'min': 9, 'max': 1000, 'classes': 'error', 'text': 'value'}]});
    columns.push({ id: 'ordered', name: 'Ordered', field: 'ordered', width: 200, formatter: Formatters.Checkbox});
    columns.push({ id: '', name: 'Actions', field: '', width: 200, formatter: Formatters.Actions, menuId: 'grid-actions-menu'});
    columns.push({ id: 'nested', name: 'Nested Prop', field: 'setting.optionOne', width: 200, formatter: Formatters.Text});
    columns.push({ id: 'comment', name: 'Comment', field: 'comment', formatter: Formatters.TextArea, width: 200});

    //Init and get the api for the grid
    $('#readonly-datagrid').datagrid({
      selectable: 'multiple',
      columns: columns,
      dataset: data,
      menuId: 'grid-actions-menu',
      headerMenuId: 'grid-header-menu',
      menuSelected: function (e, args) {
        console.log('header item selected', args);
      },
      headerMenuSelected: function (e, args) {
        console.log('header item selected', args);
      }
    });

    grid = $('#readonly-datagrid').data('datagrid');

    $('#readonly-datagrid').on('contextmenu', function (e, args) {
      console.log('contextmenu fired', args);
      grid.selectRows(args.row);
    });

  });

</script>
tmcconechy commented 5 years ago

QA Info..

This issue cannot be tested visually but is covered by functional tests.

brianjuan commented 5 years ago

http://master-enterprise.demo.design.infor.com/components/datagrid/test-paging-multiselect-select-across-page Passed QA, tested using the steps provided in #817