cssangularprimengprimeng-datatableprimeng-table

Prime ng: Programatically size the p-accordion which is present inside a p-splitter


Please see my component code below:

I have a p-splitter which is split into 3 sections. I have a p-accordion in each section, which in-turn has a p-table.

<div class="card w-full">
        <p-splitter [panelSizes]="[30, 40, 30]" styleClass="mb-5">
            <ng-template pTemplate>
                <p-accordion [activeIndex]="0" styleClass="h-full">
                    <p-accordionTab header="Signed PDF Documents">
                        <div class="flex justify-content-between">
                            <div>
                                <h6>Proposal PDF Documents</h6>
                            </div>
                            <div><a>Add Attachment(s)</a></div>
                        </div>
                        <ng-template pTemplate>
                            <p-table [value]="documentList" styleClass="p-3 p-datatable-striped">
                                <ng-template pTemplate="header">
                                    <tr>
                                        <th pSortableColumn="name">Attachment Name
                                            <p-sortIcon field="name"></p-sortIcon>
                                        </th>                                            
                                    </tr>
                                </ng-template>
                                <ng-template pTemplate="body" let-doc>
                                    <tr>
                                        <td><a>{{ doc.name }}</a></td>
                                    </tr>
                                </ng-template>
                            </p-table> 
                        </ng-template>                              
                    </p-accordionTab>
                </p-accordion>   
            </ng-template>
            <ng-template pTemplate>
                <p-accordion [activeIndex]="0" >
                    <p-accordionTab header="Papervision Documents">
                        <div class="flex justify-content-between">
                            <div>
                                <h6>Scanned Contract Documents</h6>
                            </div>                                
                        </div>
                        <ng-template pTemplate>
                            <p-table [value]="paperDocumentList" styleClass="p-3 p-datatable-striped">
                                <ng-template pTemplate="header">
                                    <tr>
                                        <th pSortableColumn="number">Customer Number
                                            <p-sortIcon field="number"></p-sortIcon>
                                        </th>
                                        <th pSortableColumn="name">Customer Name
                                            <p-sortIcon field="name"></p-sortIcon>
                                        </th>
                                        <th pSortableColumn="type">Doc Type
                                            <p-sortIcon field="type"></p-sortIcon>
                                        </th>
                                        <th pSortableColumn="docNumber">Doc Number
                                            <p-sortIcon field="docNumber"></p-sortIcon>
                                        </th>
                                        <th pSortableColumn="docDate">Doc Date
                                            <p-sortIcon field="docDate"></p-sortIcon>
                                        </th>                                            
                                    </tr>
                                </ng-template>
                                <ng-template pTemplate="body" let-doc>
                                    <tr>
                                        <td><a>{{ doc.number }}</a></td>
                                        <td>{{ doc.name }}</td>
                                        <td>{{ doc.type }}</td>
                                        <td>{{ doc.docNumber }}</td>
                                        <td>{{ doc.docDate }}</td>
                                    </tr>
                                </ng-template>
                            </p-table> 
                        </ng-template>                              
                    </p-accordionTab>                
                </p-accordion> 
            </ng-template>
            <ng-template pTemplate>
                <p-accordion [activeIndex]="0" class="w-100">
                    <p-accordionTab header="Docusign Documents">
                        <div class="flex justify-content-between">
                            <div>
                                <h6>Docusign Documents</h6>
                            </div>                                
                        </div>
                        <ng-template pTemplate>
                            <p-table [value]="docusignDocumentList" styleClass="p-3 p-datatable-striped">
                                <ng-template pTemplate="header">
                                    <tr>                                            
                                        <th pSortableColumn="name">Document Name
                                            <p-sortIcon field="name"></p-sortIcon>
                                        </th>
                                        <th pSortableColumn="number">Doc Id
                                            <p-sortIcon field="number"></p-sortIcon>
                                        </th>                                                                                       
                                    </tr>
                                </ng-template>
                                <ng-template pTemplate="body" let-doc>
                                    <tr>
                                        <td>{{ doc.name }}</td>                                            
                                        <td><a>{{ doc.number }}</a></td>
                                    </tr>
                                </ng-template>
                            </p-table> 
                        </ng-template> 
                        
                    </p-accordionTab>
                </p-accordion> 
            </ng-template>
        </p-splitter>
    </div>

I have two problems to solve here:

  1. How do I set the size of the all the accordions to be the same. Note the content is dynamic and the each accordion is growing as per it's content. I want all the accordions to be of the same size. (The max size of those 3 accordions)
  2. How can I make the splitter not to re-size? Currently the user can re-size the splitter. If I want to stop it, how can I achieve it?

Thanks for reading and any help would be greatly appreciated!

Best regards,
Nitin Avula.

Dynamically re-size the accordion


Solution

  • Usually component CSS is scoped to only within the component, we can use ::ng-deep to override this behaviour and the CSS is visible outside the component!

    How do I set the size of the all the accordions to be the same. Note the content is dynamic and the each accordion is growing as per it's content. I want all the accordions to be of the same size. (The max size of those 3 accordions)

    I am just adding the below CSS to make sure the full height propagates to all the elements of the accordion, I am using the class custom-accordion to ensure the CSS is limited to the accordion itself!

    HTML

    ...
    <div class="card w-full custom-accordion" [ngClass]="{'no-resize': noResize}">
    ...
    

    CSS

    ::ng-deep .custom-accordion .p-accordion-content {
        height: calc(100% - 54px) !important;
    }
    
    ::ng-deep .custom-accordion .p-toggleable-content,
    ::ng-deep .custom-accordion .p-accordion-tab,
    ::ng-deep .custom-accordion p-accordiontab,
    ::ng-deep .custom-accordion .p-accordion {
        height:100% !important;
    } 
    

    How can I make the splitter not to re-size? Currently the user can re-size the splitter. If I want to stop it, how can I achieve it?

    I am not sure why you would require a resize element, when no resize is needed, you can just do the same with flexbox, if you want to do that you can refer the CSS from bootstrap grids!

    To achieve what you want, we can just hide the resize bar with the class p-splitter-gutter I do the same concept of scoping it to the accordion level using class no-resize

    HTML

    <button (click)="noResize = !noResize">toggle Resize</button>
    {{noResize}}
    <div class="card w-full custom-accordion" [ngClass]="{'no-resize': noResize}">
    ...
    

    CSS

    /* disable the resize */
    ::ng-deep .no-resize .p-splitter-gutter {
        display: none !important;
    }
    

    FULL CODE

    TS

    import { Component } from '@angular/core';
    import { ImportsModule } from './imports';
    
    @Component({
      selector: 'splitter-horizontal-demo',
      templateUrl: './splitter-horizontal-demo.html',
      standalone: true,
      imports: [ImportsModule],
      styles: [
        `
        ::ng-deep .custom-accordion .p-accordion-content {
            height: calc(100% - 54px) !important;
        }
    
        ::ng-deep .custom-accordion .p-toggleable-content,
        ::ng-deep .custom-accordion .p-accordion-tab,
        ::ng-deep .custom-accordion p-accordiontab,
        ::ng-deep .custom-accordion .p-accordion {
            height:100% !important;
        } 
        /* disable the resize */
        ::ng-deep .no-resize .p-splitter-gutter {
            display: none !important;
        }
      `,
      ],
    })
    export class SplitterHorizontalDemo {
      noResize = false;
      documentList = [
        { name: 'test' },
        { name: 'test1' },
        { name: 'test2' },
        { name: 'test3' },
        { name: 'test4' },
        { name: 'test5' },
        { name: 'test6' },
      ];
      paperDocumentList = [
        {
          number: 'test',
          name: 'test',
          type: 'test',
          docNumber: 'test',
          docDate: 'test',
        },
        {
          number: 'test',
          name: 'test',
          type: 'test',
          docNumber: 'test',
          docDate: 'test',
        },
        {
          number: 'test',
          name: 'test',
          type: 'test',
          docNumber: 'test',
          docDate: 'test',
        },
        {
          number: 'test',
          name: 'test',
          type: 'test',
          docNumber: 'test',
          docDate: 'test',
        },
      ];
      docusignDocumentList = [
        {
          name: 'test',
          number: 'test',
        },
      ];
    
      noAction(event: any) {
        event.preventDefault();
        return false;
      }
    }
    

    HTML

    <button (click)="noResize = !noResize">toggle Resize</button>
    {{noResize}}
    <div class="card w-full custom-accordion" [ngClass]="{'no-resize': noResize}">
      <p-splitter
        [panelSizes]="[30, 40, 30]"
        styleClass="mb-5"
        (onResizeEnd)="noAction($event)"
        (onResizeStart)="noAction($event)"
      >
        <ng-template pTemplate>
          <p-accordion [activeIndex]="0" styleClass="h-full">
            <p-accordionTab header="Signed PDF Documents">
              <div class="flex justify-content-between">
                <div>
                  <h6>Proposal PDF Documents</h6>
                </div>
                <div><a>Add Attachment(s)</a></div>
              </div>
              <ng-template pTemplate>
                <p-table
                  [value]="documentList"
                  styleClass="p-3 p-datatable-striped"
                >
                  <ng-template pTemplate="header">
                    <tr>
                      <th pSortableColumn="name">
                        Attachment Name
                        <p-sortIcon field="name"></p-sortIcon>
                      </th>
                    </tr>
                  </ng-template>
                  <ng-template pTemplate="body" let-doc>
                    <tr>
                      <td><a>{{ doc.name }}</a></td>
                    </tr>
                  </ng-template>
                </p-table>
              </ng-template>
            </p-accordionTab>
          </p-accordion>
        </ng-template>
        <ng-template pTemplate>
          <p-accordion [activeIndex]="0">
            <p-accordionTab header="Papervision Documents">
              <div class="flex justify-content-between">
                <div>
                  <h6>Scanned Contract Documents</h6>
                </div>
              </div>
              <ng-template pTemplate>
                <p-table
                  [value]="paperDocumentList"
                  styleClass="p-3 p-datatable-striped"
                >
                  <ng-template pTemplate="header">
                    <tr>
                      <th pSortableColumn="number">
                        Customer Number
                        <p-sortIcon field="number"></p-sortIcon>
                      </th>
                      <th pSortableColumn="name">
                        Customer Name
                        <p-sortIcon field="name"></p-sortIcon>
                      </th>
                      <th pSortableColumn="type">
                        Doc Type
                        <p-sortIcon field="type"></p-sortIcon>
                      </th>
                      <th pSortableColumn="docNumber">
                        Doc Number
                        <p-sortIcon field="docNumber"></p-sortIcon>
                      </th>
                      <th pSortableColumn="docDate">
                        Doc Date
                        <p-sortIcon field="docDate"></p-sortIcon>
                      </th>
                    </tr>
                  </ng-template>
                  <ng-template pTemplate="body" let-doc>
                    <tr>
                      <td><a>{{ doc.number }}</a></td>
                      <td>{{ doc.name }}</td>
                      <td>{{ doc.type }}</td>
                      <td>{{ doc.docNumber }}</td>
                      <td>{{ doc.docDate }}</td>
                    </tr>
                  </ng-template>
                </p-table>
              </ng-template>
            </p-accordionTab>
          </p-accordion>
        </ng-template>
        <ng-template pTemplate>
          <p-accordion [activeIndex]="0" class="w-100">
            <p-accordionTab header="Docusign Documents">
              <div class="flex justify-content-between">
                <div>
                  <h6>Docusign Documents</h6>
                </div>
              </div>
              <ng-template pTemplate>
                <p-table
                  [value]="docusignDocumentList"
                  styleClass="p-3 p-datatable-striped"
                >
                  <ng-template pTemplate="header">
                    <tr>
                      <th pSortableColumn="name">
                        Document Name
                        <p-sortIcon field="name"></p-sortIcon>
                      </th>
                      <th pSortableColumn="number">
                        Doc Id
                        <p-sortIcon field="number"></p-sortIcon>
                      </th>
                    </tr>
                  </ng-template>
                  <ng-template pTemplate="body" let-doc>
                    <tr>
                      <td>{{ doc.name }}</td>
                      <td><a>{{ doc.number }}</a></td>
                    </tr>
                  </ng-template>
                </p-table>
              </ng-template>
            </p-accordionTab>
          </p-accordion>
        </ng-template>
      </p-splitter>
    </div>
    

    Stackblitz Demo