I need help to increase print quality when calling preview component into invoice

Discussão em 'Angular' iniciado por codepro imran, Março 4, 2025.

  1. i have a receipt form in angular 15 that need to be printed on a certain preview. so i have created that preview in a separate component then called that component into main form that loads by clicking on button save and print. everything workign fine but print quality is poor.

    if i print direclty that preview component, Qulity is Good but when printing receipt form Quality is poor and not readable.

    I need help how to improve print quality. there is no problem with printer.

    <div id="receipt-content" class="receipt-container">
    <!-- Header Section: Logo and Store Info -->
    <div class="header">
    <!-- Logo Container -->
    <div class="logo-container">
    <img src="assets/img/logo.png" alt="Eidanas Logo" class="logo" />
    </div>
    <!-- Store Info Container: Store Name, Address, Phone (each on its own line) -->
    <div class="store-info-container">
    <h2 class="store-name">Eidanas</h2>
    <p class="store-address"> Shop 369 St 17, D Sector D PWD, Islamabad</p>
    <p class="store-phone"> 0317-4490994, 0320-5003468</p>
    </div>
    </div>

    <!-- Meta Section: Receipt Details (left aligned) -->
    <div class="meta">
    <p class="receipt-meta"> Date: {{ saleInvoice?.date | date: 'shortDate' }}</p>
    <p class="receipt-meta"> Invoice#: {{ saleInvoice?.invoiceNo }}</p>
    <p class="receipt-meta"> Customer: {{ saleInvoice?.customerName }}</p>
    </div>

    <hr class="divider" />

    <!-- Items Table -->
    <table class="receipt-table">
    <thead>
    <tr>
    <th>Barcode</th>
    <th>Item</th>
    <th>Qty</th>
    <th>Price</th>
    <th>Disc.</th>
    <th>Total</th>
    </tr>
    </thead>
    <tbody>
    <tr *ngFor="let item of saleInvoice?.siLines">
    <td>{{ item.barcode }}</td>
    <td>{{ item.itemCode }}</td>
    <td>{{ item.quantity }}</td>
    <td>{{ item.retailPrice }}</td>
    <td> {{item.discAmount}}</td>
    <td>{{ item.lineTotal }}</td>
    </tr>
    </tbody>
    </table>

    <hr class="divider" />

    <!-- Total Amount (centered) -->
    <p class="total-amount"><strong> Grand Total: {{ saleInvoice?.totalAmount }}</strong></p>

    <!-- Print Button (hidden when printing) -->
    <div class="actions no-print">
    <button class="print-btn" (click)="printReceipt()"> Print</button>
    </div>

    <!-- Footer: Website centered at the very bottom -->
    <footer class="footer">
    <p class="website-link">www.eidanas.com</p>
    </footer>
    </div>




    here is main Receipt Code

    <div class="container-fluid page">
    <div class="d-flex page_box p- mt- header-sticky" position="sticky">
    <div *ngIf="Add">Manage Sale Invoice</div>
    <div *ngIf="Edit">Update Sale Invoice</div>
    </div>
    <div class="page_content shadow p- position-relative">
    <form #userForm="ngForm" >
    <div fxLayout="row" fxLayoutAlign="space-between">
    <mat-form-field fxFlex="45%" appearance="outline" class="form-group">
    <mat-label>Invoice No</mat-label>
    <input matInput [(ngModel)]="selectedSaleInvoice.invoiceNo" name="invoiceNo" required
    #invoiceNo="ngModel" readonly />
    <mat-error *ngIf="invoiceNo.errors?.['required']">Invoice No is required</mat-error>
    </mat-form-field>
    <mat-form-field fxFlex="45%" appearance="outline" class="form-group">
    <mat-label>Date</mat-label>
    <input matInput [ngxMatDatetimePicker]="picker" name="date" required #date="ngModel"
    [(ngModel)]="selectedSaleInvoice.date" />
    <mat-datepicker-toggle matSuffix [for]="$any(picker)"></mat-datepicker-toggle>
    <ngx-mat-datetime-picker
    class="datetimepicker"
    #picker
    [showSpinners]="false"
    [enableMeridian]="false"
    [hideTime]="true"
    [disableTime]="true"
    [disableMinute]="true"
    [min]="minDate"
    type="date">
    </ngx-mat-datetime-picker>
    </mat-form-field>
    <mat-form-field fxFlex="45%" appearance="outline" class="form-group">
    <mat-label>Customer Name</mat-label>
    <input matInput required name="customerName" #customerName="ngModel"
    [(ngModel)]="selectedSaleInvoice.customerName" />
    </mat-form-field>
    <mat-form-field fxFlex="45%" appearance="outline" class="form-group">
    <mat-label>Cell No</mat-label>
    <input matInput required name="cell" #cell="ngModel"
    [(ngModel)]="selectedSaleInvoice.cell" />
    </mat-form-field>


    </div>
    <br />

    <p style="
    font-size: 20px;
    font-weight: bolder;
    color: #04415e;
    margin-top: 30px;
    ">
    Sale Invoice Line
    </p>
    <c-card style="margin-top: 10px; background: rgb(209, 238, 243); padding: 20px" class="mat-elevation-z8">
    <form #SaleInvoiceDetailForm="ngForm" (keydown.enter)="$event.preventDefault();">

    <Row>
    <div fxLayout="row" fxLayoutAlign="space-between">
    <!-- . Service ID with Search Icon -->

    <mat-form-field fxFlex="45%" appearance="outline" class="form-group">
    <mat-label>Barcode</mat-label>
    <input matInput required name="barcode" #barcode="ngModel"
    [(ngModel)]="SaleInvoiceDetail.barcode"
    (ngModelChange)="onBarcodeScanned($event)" />

    <!-- <div matSuffix>
    <button mat-icon-button style="color:#940540;" (click)="OpenItemsDialog(); $event.stopPropagation()">
    <mat-icon cTooltip="Explore Tax">add</mat-icon>
    </button>
    </div> -->
    </mat-form-field>

    <!-- <mat-form-field fxFlex="45%" appearance="outline" class="form-group">

    <mat-label>Bar Code</mat-label>
    <mat-select
    [(ngModel)]="SaleInvoiceDetail.barcodeId"
    [ngModelOptions]="{standalone: true}"
    #barcodeId="ngModel">
    <mat-option *ngFor="let option of Items" [value]="option.barcode" (click)="onSelectItems(option)">
    {{ option.barcode }}
    </mat-option>
    </mat-select>
    <div matSuffix>
    <button mat-icon-button style="color:#940540;" (click)="OpenItemsDialog(); $event.stopPropagation()">
    <mat-icon cTooltip="Explore Tax">add</mat-icon>
    </button>
    </div>
    </mat-form-field>-->
    <mat-form-field appearance="outline" class="form-group" fxFlex="15%">
    <mat-label>Item Code</mat-label>
    <input matInput #itemCode="ngModel" readonly name="itemCode"
    [(ngModel)]="SaleInvoiceDetail.itemCode" />
    </mat-form-field>
    <mat-form-field appearance="outline" fxFlex="15%">
    <mat-label>Quantity</mat-label>
    <input
    matInput
    #qtyInput
    #quantity="ngModel"
    name="quantity"
    [(ngModel)]="SaleInvoiceDetail.quantity"
    type="number"
    min=1
    required
    (keydown.enter)="AddLinetoList()"
    oninput="validity.valid||(value='')"
    (input)="calculateAmount()"
    />
    <mat-error *ngIf="quantity.errors?.['required']">
    Quantity is required
    </mat-error>
    <mat-error *ngIf="quantity.errors?.['min']">
    Quantity must be greater than 0
    </mat-error>
    </mat-form-field>
    <mat-form-field appearance="outline" class="form-group" fxFlex="15%">
    <mat-label>Price </mat-label>
    <input matInput #retailPrice="ngModel" name="retailPrice" (input)="calculateAmount()"
    [(ngModel)]="SaleInvoiceDetail.retailPrice" />
    </mat-form-field>
    <!-- <mat-form-field appearance="outline" class="form-group" fxFlex="15%">
    <mat-label>Discount </mat-label>
    <input matInput #discount="ngModel" name="discount" (input)="calculateAmount()"
    [(ngModel)]="SaleInvoiceDetail.discount" />
    </mat-form-field> -->
    <mat-form-field appearance="outline" fxFlex="12%">
    <mat-label>Disc.%</mat-label>
    <input matInput type="number" max="100" name="discount"
    [(ngModel)]="SaleInvoiceDetail.discount"
    (focus)="lastEditedField='discount'"
    (input)="calculateAmount()" />
    </mat-form-field>

    <mat-form-field appearance="outline" fxFlex="12%">
    <mat-label>Disc.Amt</mat-label>
    <input matInput type="number" name="discAmount"
    [(ngModel)]="SaleInvoiceDetail.discAmount"
    (focus)="lastEditedField='discAmount'"
    (input)="calculateAmount()" />
    </mat-form-field>

    <mat-form-field fxFlex="15%" appearance="outline" class="form-group">
    <mat-label>Line Total</mat-label>
    <input readonly matInput #lineTotal="ngModel" name="lineTotal" required="true"
    [(ngModel)]="SaleInvoiceDetail.lineTotal" (input)="calculateAmount()" />
    </mat-form-field>
    </div>
    </Row>
    <Row>
    <div fxLayout="row" fxLayoutAlign="end" fxFlex="100%">
    <div>
    <button type="submit" mat-icon-button mat-sm-button style="color: rgb(97, 48, 48)"
    cTooltip="Add to the List" cTooltipPlacement="top" (click)="AddLinetoList()">
    <mat-icon>add</mat-icon>
    </button>
    <button type="button" mat-icon-button mat-sm-button color="primary" cTooltip="Refresh"
    cTooltipPlacement="top" (click)="RefreshLine()">
    <mat-icon>refresh</mat-icon>
    </button>
    </div>
    </div>
    </Row>
    </form>
    </c-card>
    <c-card style="padding: px; margin-top: px" class="mat-elevation-z">
    <h style="font-size: 20px; color: #04415e; margin: 20px">
    Items List
    </h>
    <c-card-body style="
    padding: 10px;
    background-image: linear-gradient(
    to bottom,
    rgb(2, 33, 58),
    rgb(7, 95, 122)
    );
    margin: 5px;
    border-radius: 10px;
    ">
    <div class="example-table-container">
    <section class="example-container mat-elevation-z8" tabindex="0" style="border-radius: 5px">
    <table mat-table [dataSource]="dataSource" class="mat-elevation-z">

    <ng-container matColumnDef="barcode">
    <th mat-header-cell *matHeaderCellDef style="color: black">
    <div style="width: 200px">BarCode</div>
    </th>
    <td mat-cell *matCellDef="let element">
    <div style="width: 200px">{{ element.barcode }}</div>
    </td>
    </ng-container>
    <ng-container matColumnDef="itemCode">
    <th mat-header-cell *matHeaderCellDef>
    <div style="width: 200px">Item Code</div>
    </th>
    <td mat-cell *matCellDef="let element">
    <div style="width: 200px">{{ element.itemCode }}</div>
    </td>
    </ng-container>
    <ng-container matColumnDef="retailPrice">
    <th mat-header-cell *matHeaderCellDef>
    <div style="width: 200px">Price</div>
    </th>
    <td mat-cell *matCellDef="let element">
    <div style="width: 200px">{{ element.retailPrice }}</div>
    </td>
    </ng-container>
    <ng-container matColumnDef="quantity">
    <th mat-header-cell *matHeaderCellDef>
    <div style="width: 200px">Quantity</div>
    </th>
    <td mat-cell *matCellDef="let element">
    <div style="width: 200px">{{ element.quantity }}</div>
    </td>
    </ng-container>
    <ng-container matColumnDef="discount">
    <th mat-header-cell *matHeaderCellDef>
    <div style="width: 200px">Disc%</div>
    </th>
    <td mat-cell *matCellDef="let element">
    <div style="width: 200px">{{ element.discount }}</div>
    </td>
    </ng-container>
    <ng-container matColumnDef="discAmount">
    <th mat-header-cell *matHeaderCellDef>
    <div style="width: 200px">Disc.Amount</div>
    </th>
    <td mat-cell *matCellDef="let element">
    <div style="width: 200px">{{ element.discAmount }}</div>
    </td>
    </ng-container>
    <ng-container matColumnDef="lineTotal">
    <th mat-header-cell *matHeaderCellDef>
    <div style="width: 200px">Line Total</div>
    </th>
    <td mat-cell *matCellDef="let element">
    <div style="width: 200px">{{ element.lineTotal }}</div>
    </td>
    </ng-container>
    <ng-container matColumnDef="actions" stickyEnd>
    <th mat-header-cell *matHeaderCellDef style="width: 100px; text-align: center">
    <div style="width: 100px; text-align: center">Actions</div>
    </th>
    <td mat-cell *matCellDef="let row">
    <div style="width: 100px; text-align: center">
    <button mat-icon-button mat-sm-button style="color: #1e293b" (click)="edit(row)"
    cTooltip="Edit Settings ">
    <mat-icon>edit</mat-icon>
    </button>
    <button mat-icon-button mat-sm-button color="warn" cTooltip="Delete Settings "
    (click)="delete(row)" [enabled]="row.isSystemDefined">
    <mat-icon>delete</mat-icon>
    </button>
    </div>
    </td>
    </ng-container>
    <tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: true"></tr>
    <tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
    </table>
    </section>
    </div>
    </c-card-body>
    <div fxLayout="row" fxLayoutAlign="end center" class="form-group">
    <div fxFlex="30%" class="form-group">
    <h4>Total Amount: {{ totalAmount }}</h4>
    </div>
    </div>
    </c-card>
    <div fxLayoutAlign="end start">
    <c-spinner *ngIf="proccessing" style="height: 50px; width: 50px; color: rgb(3, 71, 102)"></c-spinner>
    <div style="margin-top: 10px" *ngIf="!proccessing">
    <div fxLayout="row" fxLayoutAlign="end" fxFlex="100%">
    <c-spinner *ngIf="proccessing" style="height: 50px; width: 50px; color: rgb(3, 71, 102)"></c-spinner>
    <div style="margin-top: 10px" *ngIf="!proccessing">

    <!-- changing this to make primary save and print and primary update and print-->
    <!-- Add Mode: Primary Save & Print, Secondary Save -->
    <ng-container *ngIf="Add">
    <mat-button-toggle-group cButton class="me-1" style="background-color: #192151; width: 150px">
    <!-- Primary Button: Save & Print -->
    <mat-button-toggle (click)="onSaveAndPrint()">
    Save & Print
    </mat-button-toggle>
    <!-- Dropdown trigger -->
    <mat-button-toggle [matMenuTriggerFor]="dropdownMenuAdd">
    <mat-icon style="margin-right: 8px">arrow_drop_down</mat-icon>
    </mat-button-toggle>
    </mat-button-toggle-group>

    <!-- Dropdown Menu for Add Mode -->
    <mat-menu #dropdownMenuAdd="matMenu" xPosition="before">
    <button type="button" (click)="Submit()" class="btn btn-primary">
    Save
    </button>
    </mat-menu>
    </ng-container>

    <!-- Edit Mode: Primary Update & Print, Secondary Update -->
    <ng-container *ngIf="Edit">
    <mat-button-toggle-group cButton class="me-1" style="background-color: #192151; width: 150px">
    <!-- Primary Button: Update & Print -->
    <mat-button-toggle (click)="onSaveAndPrint()">
    Update & Print
    </mat-button-toggle>
    <!-- Dropdown trigger -->
    <mat-button-toggle [matMenuTriggerFor]="dropdownMenuEdit">
    <mat-icon style="margin-right: 8px">arrow_drop_down</mat-icon>
    </mat-button-toggle>
    </mat-button-toggle-group>

    <!-- Dropdown Menu for Edit Mode -->
    <mat-menu #dropdownMenuEdit="matMenu" xPosition="before">
    <button type="button" (click)="Submit()" class="btn btn-primary">
    Update
    </button>
    </mat-menu>
    </ng-container>

    <!-- Hidden Print Receipt Component -->
    <!-- This component is always rendered but will only display when printing (via your CSS) -->
    <div class="print-only">
    <app-sale-invoice-print *ngIf="selectedSaleInvoice" [saleInvoice]="selectedSaleInvoice"></app-sale-invoice-print>
    </div>

    <!-- <mat-menu #dropdownMenuTwo="matMenu" xPosition="before" >
    <button type="submit" mat-menu-item class="menu-item" (click)="isPrint=true;Submit();">
    <mat-icon class="menu-item-icon">picture_as_pdf</mat-icon>
    <span class="menu-item-text">Update & Pdf</span>
    </button>

    </mat-menu> -->
    <button cButton class="me-1" style="background-color: #192151; width: 100px" type="button"
    (click)="Refresh()" >
    Clear
    </button>
    <button cButton class="me-1" style="background-color: #051e51; width: 100px" (click)="Back()">
    Go Back
    </button>

    </div>
    </div>
    </div>
    </div>
    </form>
    </div>
    </div>
    <!--
    Print Component: Always rendered (it can be hidden during normal view via CSS if needed)
    <app-sale-invoice-print *ngIf="selectedSaleInvoice" [saleInvoice]="selectedSaleInvoice"></app-sale-invoice-print>

    <div class="print-only">
    <app-sale-invoice-print
    *ngIf="selectedSaleInvoice"
    [saleInvoice]="selectedSaleInvoice">
    </app-sale-invoice-print>
    </div> -->



    i have tried changin differnt CSS but still unable to solve it.

    here is CSS for preview component

    /* Base Styles */
    .receipt-container {
    width: 80mm;
    max-width: 80mm;
    max-height: 200mm;
    margin: 0 auto;
    padding: 1mm;
    font-family: Arial, sans-serif;
    font-size: 10pt;
    color: #000;
    background: #fff;
    border: 1px solid #ddd;
    text-align: left;
    }

    .header {
    text-align: center;
    margin-bottom: 10px;
    display: flex;
    flex-direction: column;
    align-items: center;
    }

    .logo-container {
    display: flex;
    justify-content: center;
    align-items: center;
    margin-bottom: 2mm;
    }

    .logo {
    max-width: 50mm;
    height: auto;
    }

    .store-info-container {
    text-align: center !important;
    }

    .store-name {
    display: block;
    margin: 1mm 0 1mm 0;
    font-size: 20pt;
    font-weight: bold;
    text-align: center !important;
    }

    .store-address,
    .store-phone {
    display: block;
    margin: 1mm 0;
    font-size: 11pt;
    text-align: center !important;
    }

    .meta {
    text-align: left;
    margin: 3mm 0;
    }

    .receipt-meta {
    margin: 1mm 0;
    font-size: 11pt;
    }

    .divider {
    border: 0;
    border-top: 1px dashed #000;
    margin: 3mm 0;
    }

    .receipt-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 10pt;
    }

    .receipt-table th,
    .receipt-table td {
    padding: 1mm 2mm;
    border-bottom: 1px dashed #ccc;
    text-align: center;
    }

    .total-amount {
    text-align: center;
    margin-top: 3mm;
    font-size: 11pt;
    font-weight: bold;
    }

    .actions {
    text-align: center;
    margin-top: 3mm;
    }

    .print-btn {
    padding: 3mm 6mm;
    font-size: 10pt;
    background-color: #940540;
    color: #fff;
    border: none;
    cursor: pointer;
    }

    .footer {
    margin-top: 3mm;
    border-top: 1px dashed #000;
    padding-top: 2mm;
    font-size: 12pt;
    text-align: center !important;
    }

    .website-link {
    text-align: center !important;
    margin: 0;
    padding: 0;
    width: 100%;
    }

    /* Print-Specific Adjustments */
    @media print {
    @page {
    size: 80mm 200mm;
    margin: 0;
    }

    /* Request a 600dpi resolution for printing */
    html {
    image-resolution: 600dpi;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-rendering: optimizeLegibility;
    }

    /* Hide any non-print elements */
    .no-print,
    .print-btn {
    display: none;
    }
    }



    here is CSS for main invoice component

    .page {
    color: white;
    padding: 0 1rem;
    background: #f1f5f9;
    width: 100%;


    }

    .page_content {
    padding: 20px;
    min-height: calc(100vh - 178px);
    border-radius: 15px;
    margin-top: -2rem;
    background: white;
    color: black;
    }

    .page_box {
    min-height: 100px;
    background-color: rgb(2, 42, 75);

    border-radius: 10px;
    font-size: 25px;
    padding: 10px;

    }

    .example-container {

    width: 100;
    max-width: 100%;
    overflow: auto;

    }

    table {
    width: 100;
    z-index: 1;
    }


    td.mat-column-star {
    width: 20%;
    padding-right: 8px;
    }

    th.mat-column-position,
    td.mat-column-position {
    padding-left: 8px;
    }

    .mat-mdc-table-sticky-border-elem-right {
    border-left: 1px solid #e0e0e0;
    }

    .mat-mdc-table-sticky-border-elem-left {
    border-right: 1px solid #e0e0e0;
    }
    td {
    text-align: center;
    }

    th {
    font-weight: bold;
    text-align: center;
    padding-left: 0;
    padding-right: 0;
    }

    .search-box {
    display: flex;
    align-items: center;
    border: 1px solid #3f9dcd;
    border-radius: 20px 20px 0 0;
    padding: 5px 15px;
    background-color: #daebfa;
    box-shadow: 0 2px 5px rgba(217, 242, 249, 0.2);
    transition: all 0.3s ease;
    }

    .search-box:hover {
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.25);
    }

    .search-icon {
    font-size: 28px;
    font-weight: bold;
    color:#023c58;
    transition: transform 0.3s ease;
    }

    .search-icon:hover {
    transform: scale(1.2);
    }
    th{
    color: black;
    }
    .search-input {
    flex-grow: 1;
    border: none;
    outline: none;
    padding: 10px;
    font-size: 16px;
    color: #023c58;
    background-color: transparent;
    }

    @media screen {
    .print-only {
    display: none;
    }
    }

    @media print {
    .print-only {
    display: block;
    }
    }

    @media print {
    /* Ensure high-quality printing */
    body {
    -webkit-print-color-adjust: exact !important;
    print-color-adjust: exact !important;
    image-rendering: crisp-edges;
    }

    /* Make sure the receipt container is not being shrunk */
    .receipt-container {
    width: 80mm !important;
    max-width: 80mm !important;
    height: auto !important;
    font-size: 10pt !important;
    color: black !important;
    background: white !important;
    }

    /* Prevent scaling issues */
    .print-only {
    transform: none !important;
    filter: none !important;
    }
    }

    Continue reading...

Compartilhe esta Página