Icons are not showing for custom button

Product: @pdftron/webviewer

Product Version:^11.7.1

Below is my code. I added new buttons to header, in dark mode those icons are not visible.

ngAfterViewInit() {

const baseHref = this.platformLocation.getBaseHrefFromDOM();



WebViewer({

  path: baseHref + 'lib/webviewer',

  licenseKey: this.commonService.aspyreKey,

  initialDoc: '',

  // enableFilePicker: true,

  fullAPI: true,

  css: 'assets/css/webviewer-docview.css'

}, this.viewer.nativeElement).then(instance => {

  this.viewerInstance = instance;

  const { UI, Core } = instance;

  const { Annotations, annotationManager, documentViewer, Tools } = Core;

  const { Feature } = instance.UI;

  // instance.UI.disableFeatures(\[Feature.FilePicker\]);

  // instance.UI.disableTools(\[Tools.ToolNames.STAMP\]);

  // instance.UI.disableTools(\[Tools.ToolNames.ARROW\]);

  UI.setToolbarGroup('toolbarGroup-View');

  UI.disableElements(\[

    'toolbarGroup-View', // entire View menu

    'toolbarGroup-Edit', // entire Edit menu

    'toolbarGroup-Annotate', // entire Annotate menu

    'toolbarGroup-FillAndSign',

    'toolbarGroup-Shapes',

    'toolbarGroup-Insert',

    'menuOverlay', // context menu

    'downloadButton', // single button

    'toolbarGroup-Edit',

    'toolbarGroup-Forms',

    'panToolButton',

    // this.viewerInstance.UI.Feature.FilePicker

    // 'textSelectButton',

  \]);    

  if(this.docBlob){

    this.viewerInstance.UI.loadDocument(this.docBlob);

    this.docBlob = '';

  }  



  this.viewerInstance.Core.documentViewer.addEventListener('documentLoaded', async () => {

    UI.setToolbarGroup('toolbarGroup-View');

    const readUserInfo: any = this.commonService.getItem('userInfo');

    const userInfo = JSON.parse(readUserInfo);

    this.viewerInstance.Core.annotationManager.setCurrentUser(userInfo\[0\]\["FullName"\]);

    if (this.showCustomActions) {

      let allButtonConfigs: Record<string, any> = {}

      if(!this.recordSecureHold){

        allButtonConfigs = {

          addTask: { name: 'TaskCompletionAssignTask', title: 'Add Task', img: 'assets/images/book.svg', onClick: () => this.addDoctask() },

          addRecordTask: { name: 'TaskCompletionAssignTask', title: 'Add Record Task', img: 'assets/images/list.svg', onClick: () => this.addRecordtask() },

          // newDocument: { title: 'Add New Document', img: 'assets/images/file-plus.svg', onClick: () => console.log('') },

          // keyEdit: { title: 'Key Edit', img: 'assets/images/key.svg', onClick: () => this.keyEdit() },

          showNotes: { name: 'DocNotesView,NotesAdminView', title: 'Hide/Show Documents Notes', img: 'assets/images/file-o.svg', onClick: () => this.docAction('showNotes') },

          save: { name: 'Save', title: 'Save', img: 'assets/images/save.svg', onClick: () => this.saveDocument() },

          delete: { name: 'DocDelete', title: 'Delete Document', img: 'assets/images/trash.svg', onClick: () => this.docAction('delete') },

          // auditTrail: { title: 'View Audit Trail', img: 'assets/images/list-check.svg', onClick: () => this.docAction('auditTrail') },

          indexing: {name:'DocSendToIndexing', title: 'Send To Indexing', img: 'assets/images/receipt.svg', onClick: () => this.docAction('indexing') },

          problemQueuee: {name:'DocSendToProblemQ', title: 'Send To Problem Queue', img: 'assets/images/verified.svg', onClick: () => this.docAction('problemQueuee') },

          workflow: {name:'DocSendToWorkflowQ', title: 'Send To Workflow', img: 'assets/images/list-check.svg', onClick: () => this.docAction('workflow') },

          anotherRecord: {name:'DocSendToAnotherRecord', title: 'Send To Another Record', img: 'assets/images/sitemap.svg', onClick: () => this.docAction('anotherRecord') },

          fax: { name: 'DocFax', title: 'Fax', img: 'assets/images/send.svg', onClick: () => this.docAction('fax') },

          email: { name: 'DocEmail', title: 'Email', img: 'assets/images/envelope.svg', onClick: () => this.docAction('email') },

          changeDocType: { name: 'DocChangeType', title: 'Change Document Type', img: 'assets/images/directions.svg', onClick: () => this.docAction('changeDocType') },

          indexingWorkflow: { name: 'Workflow', title: 'Indexing Workflow', img: 'assets/images/file-plus.svg', onClick: () => this.docAction('indexingWorkflow') },

        };

      }

      else{

        allButtonConfigs = {

          fax: { name: 'DocFax', title: 'Fax', img: 'assets/images/send.svg', onClick: () => this.docAction('fax') },

          email: { name: 'DocEmail', title: 'Email', img: 'assets/images/envelope.svg', onClick: () => this.docAction('email') },

        };

      }

      

      let buttonsToAdd = \[...this.customButtons\];



      //Check General permission

      const buttonConfigs: Record<string, any> = {};

      for (const \[key, config\] of Object.entries(allButtonConfigs)) {

        const actionName = config.name || key;

        if (this.commonService.hasGeneralPermission(actionName) || actionName == 'Save') {

          buttonConfigs\[key\] = config;

        }

      }

      if (this.recordSecureHold || this.isDocSecureHold) {

        buttonsToAdd = this.customButtons.filter(

          (btn: any) => btn !== 'workflow' && btn !== 'indexingWorkflow'

        );

      }  



      // Remove button if condition is false

      if (!this.indexWorkflowVisible) {

        buttonsToAdd = buttonsToAdd.filter((btn : any) => btn !== 'indexingWorkflow');

      }

      

      const customButtonInstances = buttonsToAdd

        .filter((btn: any) => !this.notRequiredAction.includes(btn))

        .filter((btn: any) => buttonConfigs\[btn\])

        .map((btn: any) =>

          new UI.Components.CustomButton({

            dataElement: btn,

            ...buttonConfigs\[btn\],

          })

        );



      // Get the modula \*/

      // const header = UI.getModularHeader('default-top-header');

      // // Existing items in header

      // const existing = header.getItems();

      // // Append your buttons

      // header.setItems(\[

      //   ...existing, ...customButtonInstances

      // \]);



      const header = UI.getModularHeader('default-top-header');

      // Remove previously added custom buttons

      const cleanedItems = header.getItems().filter((item: any) =>

        !this.customButtons.includes(item.dataElement)

      );

      // Add fresh buttons

      header.setItems(\[

        ...cleanedItems,

        ...customButtonInstances

      \]);



      if (!this.recordSecureHold) {

        if (this.commonService.hasGeneralPermission('DocEdit')) {

          UI.enableFeatures(\[

            UI.Feature.Redaction, UI.Feature.ContentEdit, UI.Feature.Annotations

          \])

          UI.enableElements(\[

            'toolbarGroup-View', // entire View menu

            'toolbarGroup-Edit', // entire Edit menu

            'toolbarGroup-Annotate', // entire Annotate menu

            'toolbarGroup-FillAndSign',

            'toolbarGroup-Shapes',

            'toolbarGroup-Insert',

            'menuOverlay', // context menu

            'toolbarGroup-Edit',

            'toolbarGroup-Forms',

            'panToolButton',

          \]);

        }         

      }

      if (this.commonService.hasGeneralPermission('DocDownload')) {

        UI.enableElements(\[

          'downloadButton'

        \])

      }

      if (!this.commonService.hasGeneralPermission('DocPrint')) {

          UI.disableElements(\[

            'printButton'

          \])

        }

      this.getStamps();

    }

  });




  documentViewer.addEventListener('mouseLeftDown', e => {

    if(this.addNewtask){

      try {

        this.stamData = {};

        const rect = documentViewer.getViewerCoordinatesFromMouseEvent(e)

        this.startX = rect.x;

        this.startY = rect.y;

        const pageNumber = documentViewer.getCurrentPage();            

        this.stamData = {

          PageNumber: pageNumber,

          X: this.startX,

          Y: this.startY,

          Width: this.width,

          Height: this.height,

          TextAlign: 'center',

          TextVerticalAlign: 'center',

          FontSize: '32pt',

        }

      } catch (err) {

        return;

      }

    }        

  });



  // mouse up

  documentViewer.addEventListener('mouseLeftUp', e => {  

    if(this.addNewtask){

      let pageCoords;

      try {

        pageCoords = documentViewer.getViewerCoordinatesFromMouseEvent(e)

      } catch (err) {

        return;

      }

      if (!pageCoords) {

        return;

      }

      this.endX = pageCoords.x;

      this.endY = pageCoords.y;

      // calculate rectangle bounds

      this.width = Math.abs(this.startX - this.endX);

      this.height = Math.abs(this.startY - this.endY);

      this.stamData\['Width'\] = this.width;

      this.stamData\['Height'\] = this.height;

      if(this.width > 0)

        this.addDoctask();

    }



  });



  // 🔹 Detect stamp delete (use annotationChanged with action = delete)

  annotationManager.addEventListener('annotationChanged', (annotations: any\[\], action: string) => {

    if(this.annotationAddedProgramatically)

      this.annotationAddedProgramatically =  false;

    if (action === 'delete') {

      annotations.forEach(annot => {

        if (annot instanceof Annotations.FreeTextAnnotation && !this.deletingStampForSave) {

          this.deleteTask(annotations\[0\].Id);

        }

      });

    }

    if (action === 'add') {

      annotations.forEach((annot: any) => {

        if (annot instanceof this.viewerInstance.Core.Annotations.FreeTextAnnotation) {

          // this.addUserHeader(annot);

        }

      });

    }        

  });

  annotationManager.addEventListener('annotationSelected', (annotations, action) => {

    if(annotations\[0\] instanceof this.viewerInstance.Core.Annotations.FreeTextAnnotation && action=='selected'){

      if (annotations\[0\] && annotations\[0\].Id &&  typeof annotations\[0\].Id == 'number' && !this.taskAdded) {

        console.log(annotations\[0\].Id);

        this.onTaskRowSelect(this.stamList.find((el: any) => el.TaskID == annotations\[0\].Id))

      }

    }        

  });



  // documentViewer.addEventListener('rotationUpdated', (pageIndex, rotation) => {

  //   // this.syncViewerRotationToDocument();

  //   this.annotationAddedProgramatically = false;

  //   this.rotationMap\[pageIndex + 1\] = rotation / 90; 

  // });

  documentViewer.addEventListener('rotationUpdated', async () => {

    // We fire the process, but the main logic is deferred to a function that guarantees completion

    // await this.synchronizeRotationsAndDownload(instance);

    this.annotationAddedProgramatically = false;

  });



  instance.UI.addEventListener('toolbarGroupChanged', (e) => {

    // if(e?.detail != 'toolbarGroup-View')

    // setTimeout(() => {

    //   const { UI} = this.viewerInstance;

    //   UI.setToolbarGroup('toolbarGroup-View');

    // }, 500);

  });

})

}

Hi there,

It looks like there’s some missing variables in your snippet. Could you please share a minimal snippet with a screenshot of the missing icon?

Are you able to reproduce this issue on our showcase demo? https://showcase.apryse.com/

Using the sample snippet for custom button in our guide, I can see the icon even in dark mode within WebViewer:

Best regards,

Kevin

Hi,

Thanks for the quick response. it is working now.

1 Like