Flex Grid Master- Detail (Nested Grid Question)

Posted by: kapil.r.shah on 1 July 2019, 11:17 pm EST

    • Post Options:
    • Link

    Posted 1 July 2019, 11:17 pm EST

    Hello,

    Hello,

    I am using Angular 7 . Installed Angular CLI and created a new app . Working on NestedGrids(RowDetail) sample .

    https://www.grapecity.com/wijmo/demos/Grid/Master-Detail/NestedGrids(RowDetail)/angular

    I see that in app.Component.ts , the categories and product data is already loaded in the constructor and then filtered in getProducts method

    In my use case , I have child records data which will be large ( around 20,000) so do not want to load all the data in the constructor. I want to make a API call by clicking the wj-glyph-plus icon and make a API call to the server and fetch the child records.

    Do Wijmo have an example of fetching the child records by making an API call to the server.

    I am doing a POC to make a API call and its not working.

    Thanks,

  • Posted 2 July 2019, 6:48 pm EST

    Hello,

    You may use the createDetailCell property of FlexGridDetailProvider class to call you API and load the grid when the data is returned from the server.

    Please refer to the sample attached.FlexGridDetail.zip

  • Posted 2 July 2019, 10:52 pm EST

    Thank you for the sample project. I build the project . Had a compilation error

    ERROR in src/app/app.component.ts(53,22): error TS2339: Property ‘style’ does not exist on type ‘Element’.

    Still , the application works on Chrome Browser and shows the products data .However does not show correctly in IE browser.

  • Posted 3 July 2019, 4:48 pm EST

    ‘style’ does not exist

    The children property of an HTML element returns an object of HTMLElement class which does not have a style property. But in our case, the element returned will be an instance of HTMLDivElement which have a style property. But, typescript does not know that because it works at runtime. To solve this issue, we just need to cast the element to a div element.

    var c0 = cell.children[0] as HTMLDivElement;
    c0.style.display = "none";
    
    >> Does not work in IE
    

    We just need to invalidate the child grid when it is loaded by calling the invalidate method of FlexGrid.

    How to update using CollectionView

    Please refer to the attached sample.

    In the sample, I have changed the DataService class to use CollectionView instead of ODataCollectionView. In this method, I created an empty collectionView object and returned this object. When the data is returned from the server, I just assigned it to the sourceCollection property of the CollectionView.

    In the createDetailCell, I handled the sourceCollectionChanged event of CollectionView instead of loaded event of ODataCollectionView. FlexGridDetail _SAMPLE.zip

  • Posted 5 July 2019, 1:17 am EST

    I did a console.log on gridChild on your sample project and see that it has property _activeCell: div.wj-cell.wj-state-selected.wj-state-active

    When I did a console.log on gridChild on the my project, I see that it is null

    _activeCell : null

    Is this a css issue ?

    I am getting the correct data but the wj-btn wj-btn-glyph wj-elem-detail icon does not expand and collapse.

    I am loading node_modules/@grapecity/wijmo.styles/wijmo.scss file and I see that you are loading node_modules/@grapecity/wijmo.styles/wijmo.css.

    Thanks

  • Posted 7 July 2019, 6:35 pm EST

    Hi,

    Please refer to the attached sample.

    In this sample, We have updated the code to use Observable like you are using and it works without any issues. Please use the provided sample as a reference and if the issue still persists, please provide us with a sample so we can investigate further.

    >> _activeCell is null

    The null value of _activeCell indicates that there is no currently selected cell in the grid because the itemsSource of the grid is empty.

    >> CSS issue

    We have also updated the sample to use SCSS instead of CSS and there is no issue in the project. SCSS is an extension of CSS and if your project was created with SCSS, then it should work without any issues.

    FlexGridDetail_updated.zip

  • Posted 8 July 2019, 12:32 am EST

    I implemented your sample code and now the code works. Thank you for providing support

  • Posted 8 July 2019, 4:06 am EST

    Question : How do I show the default sort indicators when the FlexGrid loads with data ?

    Currently when the Flex Grid Loads, it does not show any sort indicators. I would like to show the sort indicators to make the user aware that sorting works

    Thanks,

  • Posted 8 July 2019, 10:13 pm EST

    You may apply default sorting by using the sortDescriptions property of CollectionView class. You may simply pass an array of string with property names on which sorting should be applied:

    self.products = new wjcCore.CollectionView([], {
        filter: function(item, prop) {
         return item.CategoryID == catId;
        },
        sortDescriptions: ['ProductName']
       });
    
    

    You could also pass a SortDescription object to the sortDescriptions property:

    constructor(private dataSvc: DataService) {
     this.categories = this.dataSvc.getCategories();
     this.categories.sortDescriptions.push(new wjcCore.SortDescription('CategoryName', true));
    }
    

    You could also simply sort the grid by clicking on the column header of the column by which you wish to sort the grid.

    When sorting is applied on the grid, you may see an arrow glyph icon on the column header on which the sorting is applied.

    You may also refer to the updated sample attached. Please let us know if this is your requirement.

    API Reference:

    FlexGridDetail.zip

  • Posted 9 July 2019, 12:44 am EST

    Yes the Sorting Example helps. I am able to use to show the default sort for the column

    
    this.categories.sortDescriptions.push(new wjcCore.SortDescription('CategoryName', true));
    }
    
    

    Thank you for providing support.

  • Posted 9 July 2019, 4:14 am EST - Updated 3 October 2022, 9:07 am EST

    I see that the sorting does not sort the date correctly. Please see screen shot . I am trying to sort date in descending order.```

    this.auditDataCollectionView.sortDescriptions.push(new wjcCore.SortDescription(‘EventDateUTC’, false));

  • Posted 9 July 2019, 4:21 am EST

    Also , I am also interested in printing out the flexgrid as pdf, along with Master and its Details i.e parent and child rows. Does Wijmo support that feature.

    Thanks

  • Posted 9 July 2019, 9:42 pm EST

    Hi again,

    1. The date is not sorted correctly

    We are sorry but we were not able to replicate the issue at our end. Please refer to the sample attached and let us know whether we are missing something to replicate the issue. Also, could you please try using the sortComparer property of CollectionView class to sort the dates as shown in the code snippet below:

    this.auditDataCollectionView.sortComparer = function(a, b) {
       if(wjcCore.isDate(a) && wjcCore.isDate(b)) {
        return a.valueOf() - b.valueOf();
       }
       return null;
      }
    

    Please let us know if this solves your issue.

    1. Export to PDF

    We have asked the dev team on how to export the FlexGrid with all the row details. We will give you an update as soon as we have any further information.

    FlexGridDetails_using_observable_updated.zip

  • Posted 10 July 2019, 5:31 am EST

    In my code , I am converting into CollectionView First and then looping through it to convert it to date. After that I am sorting it.

    Here formatDate is imported from

    import { formatDate } from ‘@angular/common’;

    In your code, I see that you are first converting to Date and then converting the data to collection and then sorting it

    Is that creating a problem. Also if you see the screen shot attached, I am having problem with date having time between 07/09/2019 12:35:04 PM and 07/09/2019 12:47:06 PM

    Thanks

    
     this.auditSearchResults$.subscribe(data => {
          this.auditDataCollectionView = new wjcCore.CollectionView(data);
    
          this.auditDataCollectionLength = this.auditDataCollectionView._view.length;
          // Convert to Date
          for (let i = 0; i < this.auditDataCollectionView.items.length; i++) {
              const item = this.auditDataCollectionView.items[i];
    
              const dt = new Date(item.EventDateUTC);
              item.EventDateUTC = formatDate(dt, 'MM/dd/yyyy h:mm:ss a', 'en-US');
          }
         this.auditDataCollectionView.sortDescriptions.push(new wjcCore.SortDescription('EventDateUTC', false));
          // Set Page Size
          this.auditDataCollectionView.pageSize = 50;
         // return this.auditDataCollectionView;
        });
    
    ```[img]https://gccontent.blob.core.windows.net/forum-uploads/file-0f4678e3-0cd2-4753-843a-0f759dcbce62.PNG[/img]
  • Posted 10 July 2019, 5:33 am EST

    If I comment out , then the dates do show correctly in descending order.

    ;```

    this.auditDataCollectionView.sortDescriptions.push(new wjcCore.SortDescription(‘EventDateUTC’, false))

  • Posted 10 July 2019, 9:30 pm EST

    Hi,

    The reason for the date not sorting correctly maybe because the date is the converted to string in your code using the formatDate method. Due to this, when sorting is applied, the column is sorted according to the String data type instead of the Date data type.

    To solve this issue, instead of converting the date to a string , I would suggest using the format property of Column class to format the date in the grid. Please refer to the sample that I provided earlier.

    Commenting out the line works

    Removing the sort description line from the code as the data is already sorted according to date before being loaded into the grid.

  • Posted 10 July 2019, 9:55 pm EST

    Export grid to PDF

    You may use the export method of FlexGridPdfConverter to export the grid to PDF. To also include the row details, you may set the drawDetailRows and customCellContent to true and use the formatItem callback to draw the detail cells. Please refer to the sample attached.

    PS: Only the visible row details will be exported to the PDF because when a row detail is not visible, the HTML element containing the detail row is also not visible in the DOM. Therefore, the PDF converter will not be able to render it.

    API Reference:

    FlexGridDetails_export.zip

  • Posted 17 October 2019, 3:52 am EST

    In the nested grid, what is the property for word wrap. The text inside the grid is around 4000 characters

    
     const cell = wjcCore.createElement(`<div>
                <div>Loading......</div>
                <div style="display: none"></div>
                </div>`);
            const gridChild = new wjcGrid.FlexGrid(cell.children[1], {
              columns: [
                { header: 'Property Name', binding: 'PropertyName', width: '*' },
                { header: 'Before Edit', binding: 'OriginalValue', width: '3*' },
                { header: 'After Edit', binding: 'NewValue', width: '3*' }
              ],
              headersVisibility: wjcGrid.HeadersVisibility.Column,
              isReadOnly: true,
              autoGenerateColumns: false
            });
    
    
    
    
    
    ``` [img]https://gccontent.blob.core.windows.net/forum-uploads/file-3c8d2c34-5eed-485c-aad4-85cbc50d5374.PNG[/img]
  • Posted 17 October 2019, 5:31 pm EST

    Hi Kapil,

    Could you please try using the wordWrap and the multiLine property of the Column class?

    columns: [
                { header: 'Property Name', binding: 'PropertyName', width: '*' },
                { header: 'Before Edit', binding: 'OriginalValue', width: '3*', wordWrap: true, multiLine: true },
                { header: 'After Edit', binding: 'NewValue', width: '3*', wordWrap: true, multiLine: true }
    ]
    

    Let me know if this solves your issue.

    ~regards

  • Posted 17 October 2019, 11:39 pm EST

    It did not solve the issue. In fact it truncated the test. My text was

    Remove/Restore Email Template

    ,View Document List,Edit Document,Edit Email Template

    ,View Email Template List,Remove/Restore Document,Create Email Template

    ,Create Document,02. Approve OSEC Approval,12. Finalize NV,Create Email,Remove/Restore Vote Template,Edit Quorum Rule

    ,Edit Governor Profile

    ,View Vote Option List

    ,11. Notify Vote Tally,01. Admin,04. Active Users,View Implemenation Template List

    ,Create Governor Profile

    ,03. Notify vote,View OSEC Governors Portal,Remove/Restore Quorum Rule

    ,02. Approve OSEC Approval Mobile,Remove/Restore Lookup Data,Edit Emails,05. Activity Log,Remove/Restore Governor Profile

    ,08. Notify NV for Distribution List Approval,Edit Implemention Template,View Emails,Remove/Restore Emails,View NV Distribution,Create Implementation Template,02. Role-Group Managment,Edit Lookup Data,07. Notify NV for Governor Actions,View Quorum Rule

    List,02. View Governor Mobile,View Lookup Data List,02. Submit vote ,01. View Governor Portal,Create Vote Template,Migrate,03. Create NV,View Access Denied,04. Notify vote Govenror Mobile,04. Edit NV,View Governor Profile

    List,Remove/Restore Vote Option,Create Lookup Data,Edit Vote Template,01. View Governor NV,Create Vote Option,Edit Vote Option,View Vote Template List,Remove/Restore Implementation Template,Create Quorum Rule

    ,View OSEC Portal,03. Submit vote Governor Mobile

    and it showed only Remove/Restore Email Template

    Please advice

    Kapil

  • Posted 20 October 2019, 10:08 am EST

    I have a bug in my master detail grid i.e NestedGrids(RowDetail)

    Sometimes whenever I click the icon to show the child rows, the code breaks.

    TypeError: Cannot read property ‘style’ of null

    gridChild.hostElement.style.display = ‘block’;

    Does gridChild has a property of style???

    
    initGrid(grid: wjcGrid.FlexGrid) {
        const self = this;
        grid.autoSizeRows(0, grid.rows.length - 1, false, 20);
        // tslint:disable-next-line:no-unused-expression
         new wjcGridDetail.FlexGridDetailProvider(grid, {
          createDetailCell: function(row) {
            const AuditLogId = row.dataItem.AuditLogId;
            console.log(AuditLogId);
    
            // filtering is done here because the api returns all the data
            self.auditLogDetailsDataCollectionView = new wjcCore.CollectionView(
              [],
              {
                filter: function(item, prop) {
                  return item.AuditLogId === AuditLogId;
                }
              }
            );
            //  self.LogDetails$ =  self.auditService.getAuditLogDetails(AuditLogId);
            self.store.dispatch(new fromStore.LoadAuditLogDetails(AuditLogId));
            self.LogDetails$ = self.store.select(fromStore.getAuditLogDetail);
            self.LogDetails$.subscribe(data => {
              console.log(data);
              self.auditLogDetailsDataCollectionView.sourceCollection = data;
            });
    
            // First div is to show the user that data is loading
            // Second is to create the grid
            const cell = wjcCore.createElement(`<div>
                <div>Loading......</div>
                <div style="display: none"></div>
                </div>`);
            const gridChild = new wjcGrid.FlexGrid(cell.children[1], {
              columns: [
                { header: 'Property Name', binding: 'PropertyName', width: '*' },
                { header: 'Before Edit', binding: 'OriginalValue', width: '3*'  },
                { header: 'After Edit', binding: 'NewValue', width: '3*' }
              ],
              headersVisibility: wjcGrid.HeadersVisibility.Column,
              isReadOnly: true,
              autoGenerateColumns: false
            });
    
            self.auditLogDetailsDataCollectionView.sourceCollectionChanged.addHandler(
              function(s, e) {
                const c0 = cell.children[0] as HTMLDivElement;
                c0.style.display = 'none';
             [b]   gridChild.itemsSource = self.auditLogDetailsDataCollectionView;
                gridChild.hostElement.style.display = 'block';
                grid.autoSizeRows(0, grid.rows.length - 1, false, 20);
                gridChild.invalidate();[/b]
              }
            );
            // console.log('K2', gridChild);
            return cell;
          },
          rowHasDetail: function(row) {
            return (
              row.dataItem.Action === 'Update' &&
              row.dataItem.AuditLogDetails.length > 0
            );
          }
        });
      }
    
    
    
    
  • Posted 20 October 2019, 5:23 pm EST

    Hi Kapil,

    Regarding word-wrap:

    The reason that your data is not visible is that the height of the row is small to show all of the data that is wrapped in the next lines. To show the wrapped data, you may simply set the height of the row to a large value.

    gridChild.rows[0].size = 200; // set the size of the row
    

    I would also suggest you to set the value of allowResizing property of FlexGrid to ‘Both’ to allow resizing of the row also.

    Regarding the error:

    Could you please try adding a condition to check whether the child FlexGrid is created and then change its properties:

    if (gridChild instanceof wjcGrid.FlexGrid && gridChild.hostElement) {
    	gridChild.itemsSource = self.products;
    	gridChild.hostElement.style.display = "block";
    	grid.autoSizeRows();
    	gridChild.invalidate();
    	gridChild.rows[0].size = 200; // set the size of the row
    }
    

    If the issue still exists, could you please modify the sample attached so that it replicates the issue.

    ~regards

    FlexGridDetail.zip

  • Posted 21 October 2019, 1:29 am EST

    Hi Ashwin,

    Thanks for your help. The error looks fixed and

    the gridChild.rows[0].size = 200; seems to be working.

    Where do I set the value of allowResizing property of FlexGrid to ‘Both’ to allow resizing of the row also.

    Thanks,

  • Posted 21 October 2019, 3:19 pm EST

    Hi Kapil,

    You could set the allowResizing property when you are creating the child FlexGrid:

    var gridChild = new wjcGrid.FlexGrid(cell.children[1], {
    	columns: [
    		{ header: "Name", binding: "ProductName", width: "*" },
    		{
    			header: "Oty/Unit",
    			binding: "QuantityPerUnit",
    			width: "*",
    			wordWrap: true,
    			multiLine: true
    		},
    		{ header: "Unit Price", binding: "UnitPrice" },
    		{ header: "Discontinued", binding: "Discontinued" }
    	],
    	headersVisibility: wjcGrid.HeadersVisibility.All,
    	isReadOnly: true,
    	autoGenerateColumns: false,
    	allowResizing: "Both" // allow resizing of both rows and columns
    });
    

    ~regards

  • Posted 19 December 2019, 7:18 am EST

    Hi Ashvin,

    In Master detail grid, Is it possible to expand all the row details.

    https://www.grapecity.com/wijmo/demos/Grid/Master-Detail/NestedGrids(RowDetail)/angular

    In the current example, when I click one row detail, it closes the other row details.

    How do I set the row details so that it keeps remain open till I go and close it?

    Thanks

  • Posted 19 December 2019, 3:51 pm EST

    Hi Kapil,

    You can set the detailVisibilityMode of the FlexGridDetailProvider to ‘ExpandMulti’:

    <ng-template wjFlexGridDetail [detailVisibilityMode]="'ExpandMulti'">
    ...
    </ng-template>
    

    ~regards

  • Posted 20 December 2019, 5:57 am EST

    Also, I am setting wordwrap & multiline to true but the text is not going to the next line.

    This is for inner row details using FlexGridDetailProvider

    Please see image.

    
    
    columns: [
                { header: 'Property Name', binding: 'PropertyName', width: '*' },
                { header: 'Before Edit', binding: 'OriginalValue', width: '3*' , wordWrap: true, multiLine: true  },
                { header: 'After Edit', binding: 'NewValue', width: '3*' , wordWrap: true, multiLine: true }
              ],
    
    
    
    ```[img]https://gccontent.blob.core.windows.net/forum-uploads/file-b2b91005-8f2b-4924-bd86-06d4a5b5cf18.PNG[/img]
  • Posted 22 December 2019, 9:05 pm EST

    Hi Kapil,

    You can set the detailVisibilityMode setting while creating the FlexGridDetailProvider:

    new wjcGridDetail.FlexGridDetailProvider(grid, {
    	detailVisibilityMode: wjcGridDetail.DetailVisibilityMode.ExpandMulti,
    	...
    }
    

    Regarding closing the details:

    You can use the hideDetail method of the FlexGridDetailProvider to hide all the open details. You can also add this on a button click:

    <button (click)="detail.hideDetail()">Close Details</button>
    

    Regarding wordWrap and multiLine:

    The data is wrapped and moved to the next line but it does not seem like it since the height of the row is small. You can increase the height of the rows when the detail is open:

    if (gridChild instanceof wjcGrid.FlexGrid && gridChild.hostElement) {
    	gridChild.itemsSource = self.products;
    	gridChild.hostElement.style.display = "block";
    	grid.autoSizeRows();
    	gridChild.invalidate();
    	gridChild.rows[0].size = 200; // set the size of the row
    	setTimeout(() => {
    		gridChild.autoSizeRows();
    	}, 10);
    }
    

    You can refer to the sample attached.

    ~regards

    src.zip

  • Posted 23 December 2019, 6:16 am EST

    Thanks Ashwin. Its working for now. Will get back to you for more questions.

  • Posted 10 January 2020, 3:04 am EST

    How can I check first whether the row has rowdetails and then use the hidedetail method.

    I am using the hidedetail method in my clear button which clears the flex grid. If there is no data and the hidedetail method is called , the code breaks.

    Thanks,

    [quote=“ashwin.saxena”]

    Hi Kapil,

    You can set the detailVisibilityMode setting while creating the FlexGridDetailProvider:

    new wjcGridDetail.FlexGridDetailProvider(grid, {
    	detailVisibilityMode: wjcGridDetail.DetailVisibilityMode.ExpandMulti,
    	...
    }
    

    Regarding closing the details:

    You can use the hideDetail method of the FlexGridDetailProvider to hide all the open details. You can also add this on a button click:

    <button (click)="detail.hideDetail()">Close Details</button>
    
  • Posted 12 January 2020, 5:16 pm EST

    Hi Kapil,

    As per my understanding, you have a Button that clears all the data in the FlexGrid and also calls the hideDetail method to close all the details that are open in the FlexGrid. It does not give any error if no details are open. Could you please provide the implementation of how are you clearing the data from the grid? Could you also check whether there is an error thrown in the browser’s console and provide the screenshot of the error?

    ~regards

  • Posted 13 January 2020, 4:30 am EST

    Hi Ashwin,

    Sending u the screen shot and the code

    Thanks,

    Kapil

    
    ClearAuditValues() {
        this.auditDataCollectionLength = 0;
        this.auditMessage = '';
        this.detail.hideDetail();
        
    
      }
    
     where   detail: wjcGridDetail.FlexGridDetailProvider;
    
    
    
    
    ```[img]https://gccontent.blob.core.windows.net/forum-uploads/file-f71edf29-6f4b-42aa-bd8c-bef7d3672110.png[/img]
  • Posted 13 January 2020, 2:57 pm EST

    Hi Kapil,

    We are sorry but we were not able to replicate the issue at our end. Please refer to the sample attached that we used to replicate the issue. Could you please let us know whether we are missing something in order to replicate the issue?

    Also, please make sure the detail is a class variable and also that the ‘this’ refers to the AppComponent in ClearAuditValues method.

    ~regards

    details.zip

  • Posted 22 January 2020, 3:37 pm EST

    Hi Kapil,

    After setting the sourceCollection, please try calling the autoSizeRows method:

    self.LogDetails$.subscribe(data => {
    	console.log(data);
    	self.auditLogDetailsDataCollectionView.sourceCollection = data;
    	grid.autoSizeRows();
    });
    

    ~regards

  • Posted 27 January 2020, 11:13 pm EST

    Hi Ashwin,

    I tried the suggestion above but it did not work .Any other ideas

    Thanks

  • Posted 28 January 2020, 7:27 pm EST

    Hi Kapil,

    Sorry but currently I do not have any new suggestions. If you could modify the last sample that I provided so that it replicates the issue, then I can easily assist you further. Can you modify the sample?

    Also, could you please create a new forum case related to this because this post is getting bigger and a little harder to track.

    ~regards

Need extra support?

Upgrade your support plan and get personal unlimited phone support with our customer engagement team

Learn More

Forum Channels