• Skip to main content
  • Skip to primary sidebar

Web Development Archive

  • Archive
You are here: Home / Archives for Other

Other

Update Angular Core Version

ng update @angular/core@17 @angular/cli@17
nvm use 20.11.0

Filed Under: Other

Loader

<div class="loader-wrapper">
<div class="loader">
<app-icon [icon]="'icon-spinner'" [size]="100"> </app-icon>
</div>
</div>
@use 'shared' as *;

:host {
display: block;
}
.loader-wrapper {
display: grid;
place-items: center;
height: 100vh;
}

@media (prefers-reduced-motion: no-preference) {
.loader {
animation: spinner infinite 2s linear;
transform-origin: center;
}
}

@keyframes spinner {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}

Filed Under: Other

Add class only to the clicked item

Component #1

(click)="setActive()"
@Output() activate = new EventEmitter<void>();

setActive() {
  if (!this.isDisabled) {
    this.activate.emit();
  }
}

Component #2

<your-component
  *ngFor="let item of menuItem; let i = index"
  [isActive]="i === activeItemIndex"
  (activate)="onActivate(i)"
></your-component>
activeItemIndex: number | null = null;

onActivate(index: number) {
  this.activeItemIndex = index;
}

Filed Under: Other

Getter for multiple classes for ngClass

// Getter to return classes including backgroundColor
public get classes(): { [key: string]: boolean } {
    const classList: { [key: string]: boolean } = {
      loading: this.isLoading,
      wide: this.isWide,
    };

    if (this.backgroundColor) {
      classList[this.backgroundColor] = true;
    }

    return classList;
}
<div [ngClass]="classes"></div>

Filed Under: Other

Thousand Separator

With Comma

{{ number | number: '1.0-0' }}
420,000

With Space

420 000

Thousand Separator Pipe

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
  name: 'thousandSeparator',
  standalone: true,
})
export class ThousandSeparatorPipe implements PipeTransform {
  transform(value: number): string {
    return value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ' ');
  }
}
{{ number | thousandSeparator }}

Ha az adat, ami backendről érkezik string

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
name: 'thousandSeparator',
standalone: true,
})
export class ThousandSeparatorPipe implements PipeTransform {
public transform(value: number | string): string {
if (typeof value === 'string') {
const parsedValue = parseFloat(value.replace(/,/g, ''));
if (isNaN(parsedValue)) {
return value;
}
value = parsedValue;
}

return value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ' ');
}
}

Filed Under: Other

Ternary Operator in Angular

A ternary operátor a következő formátumot követi: feltétel ? értékHaIgaz : értékHaHamis. Az [icon] attribútum értékét módosítjuk az isFavorite változó függvényében:

<div [ngClass]="isValid ? 'valid' : 'invalid'">
<app-icon [icon]="isFavorite ? 'icon-folder-star' : 'icon-folder'" [size]="84"></app-icon>

Ebben az esetben, ha isFavorite értéke true, akkor az [icon] attribútum értéke 'icon-folder-star' lesz, különben pedig 'icon-folder'. A [size] attribútum értéke mindkét esetben 84 marad, mivel nem változik az isFavorite változó függvényében.

Filed Under: Other

SVG Sprite Icons in Storybook

assets/images/icons/svg-icon-sprite.svg

<svg xmlns="http://www.w3.org/2000/svg">
  <defs>
    <symbol id="icon-search" viewBox="0 0 14 14">
      <path d="M13.3642 10.4131L11.9063 8.9199C11.5927 8.62179 11.1971 8.42427 10.7703 " />           
    </symbol>

    <symbol id="icon-arrow-right" viewBox="0 0 14 14">
      <path
      stroke="currentColor"
      d="M1.16675 6.99984H12.8334M12.8334 6.99984L7.00008 1.1665M12.8334 6.99984L7.00008 12.8332"
      stroke-width="2"
      stroke-linecap="round"
      stroke-linejoin="round"
    />
    </symbol>
  </defs>
</svg>

Icon component

import { CommonModule } from '@angular/common';
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';

@Component({
selector: 'app-icon',
standalone: true,
imports: [CommonModule],
templateUrl: './app-icon.component.html',
styleUrl: './app-icon.component.scss',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AppIconComponent {
@Input() icon: string | undefined;
@Input() size: number | undefined;
}

Icon template

<svg [attr.height]="size" [attr.width]="size">
  <use [attr.href]="'images/icons/svg-icon-sprite.svg#' + icon"></use>
</svg>

Icon styles

:host {
  display: flex;

  use {
    display: block;
    height: 100%;
    width: 100%;
    fill: currentColor;
  }
}

Button component

import { CommonModule } from '@angular/common';
import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core';
import { ButtonGroup, ButtonIcon, ButtonState, ButtonType } from '@app/lib/components/app-button/app-button.enum';

import { appIconComponent } from '../app-icon/app-icon.component';
import { appIconsComponent } from '../app-icons/app-icons.component';

@Component({
selector: 'app-app-button',
standalone: true,
imports: [CommonModule, appIconsComponent, appIconComponent],
templateUrl: './app-button.component.html',
styleUrl: './app-button.component.scss',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class appButtonComponent {
@Input() label = 'Button';

@Input() buttonType: ButtonType = ButtonType.PRIMARY;
@Input() buttonGroup: ButtonGroup = ButtonGroup.DEFAULT;
@Input() buttonIcon: ButtonIcon = ButtonIcon.DEFAULT;
@Input() buttonState: ButtonState = ButtonState.DEFAULT;

@Output() buttonClick = new EventEmitter<Event>();

// Exponáljuk a ButtonIcon enumot, hogy használni tudjuk a template-ben
ButtonIcon = ButtonIcon;
ButtonType = ButtonType;
ButtonState = ButtonState;

public get classes(): string[] {
const typeClass = `app-btn-${this.buttonType}`;
const groupClass = `app-btn-${this.buttonGroup}`;
const iconClass = `app-btn-${this.buttonIcon}`;
const stateClass = `app-btn-${this.buttonState}`;
return ['app-btn', typeClass, groupClass, iconClass, stateClass];
}
}

Template where you want to use the icon

<app-icon [icon]="'icon-arrow-right'" [size]="14"></app-icon>

Filed Under: Other

Enums in Storybook

export enum ButtonIcon {
    DEFAULT = 'only text',
    ICON_LEFT = 'icon left',
    ICON_RIGHT = 'icon right',
    ICON = 'icon',
  }
<button [ngClass]="classes" (click)="buttonClick.emit($event)" type="button">
    <ng-container *ngIf="buttonIcon === ButtonIcon.DEFAULT"> Default </ng-container>
    <ng-container *ngIf="buttonIcon === ButtonIcon.ICON_LEFT"> Icon left </ng-container>
    <ng-container *ngIf="buttonIcon === ButtonIcon.ICON_RIGHT"> Icon right </ng-container>
    <ng-container *ngIf="buttonIcon === ButtonIcon.ICON"> Icon </ng-container>
  </button>
  
import { CommonModule } from '@angular/common';
  import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core';
  import { ButtonGroup, ButtonIcon } from '@app/lib/definitions/buttons.enum';
  
  import { IconsComponent } from '../icons/icons.component';
  
  @Component({
    selector: 'app-button-primary',
    standalone: true,
    imports: [CommonModule, IconsComponent],
    templateUrl: './button-primary.component.html',
    styleUrl: './button-primary.component.scss',
    changeDetection: ChangeDetectionStrategy.OnPush,
  })
  export class ButtonPrimaryComponent {
    @Input() primary = false;
    @Input() backgroundColor?: string;
    @Input() label = 'Button';
    @Input() iconColor = 'white';
    @Input() buttonGroup: ButtonGroup = ButtonGroup.DEFAULT;
    @Input() buttonIcon: ButtonIcon = ButtonIcon.DEFAULT;
  
    @Output() buttonClick = new EventEmitter<Event>();
  
    ButtonIcon = ButtonIcon;
  
    public get classes(): string[] {
      const groupClass = `app-button--${this.buttonGroup}`;
      const iconClass = `app-button--${this.buttonIcon}`;
      return ['app-button', groupClass, iconClass];
    }
  }
  
import { ButtonGroup, ButtonIcon } from '@app/lib/definitions/buttons.enum';
  import type { Meta, StoryObj } from '@storybook/angular';
  import { fn } from '@storybook/test';
  
  import { ButtonPrimaryComponent } from './button-primary.component';
  
  // More on how to set up stories at: https://storybook.js.org/docs/writing-stories
  const meta: Meta<ButtonPrimaryComponent> = {
    title: 'app/Buttons/Button Primary',
    component: ButtonPrimaryComponent,
    tags: ['autodocs'],
    argTypes: {
      backgroundColor: {
        control: 'color',
      },
    },
    // Use `fn` to spy on the buttonClick arg, which will appear in the actions panel once invoked: https://storybook.js.org/docs/essentials/actions#action-args
    args: { buttonClick: fn() },
  };
  
  export default meta;
  type Story = StoryObj<ButtonPrimaryComponent>;
  
  // More on writing stories with args: https://storybook.js.org/docs/writing-stories/args
  export const Default: Story = {
    args: {
      primary: true,
      label: 'Button',
      buttonGroup: ButtonGroup.DEFAULT,
      buttonIcon: ButtonIcon.DEFAULT,
    },
  };
  
  export const Outlined: Story = {
    args: {
      label: 'Button',
      buttonGroup: ButtonGroup.OUTLINED,
      buttonIcon: ButtonIcon.DEFAULT,
    },
  };
  
  export const Underlined: Story = {
    args: {
      label: 'Button',
      buttonGroup: ButtonGroup.UNDERLINED,
    },
  };
  
  export const Text: Story = {
    args: {
      label: 'Button',
      buttonGroup: ButtonGroup.TEXT,
    },
  };

Filed Under: Other

NVM

  1. Ellenőrizze a Shell Konfigurációs Fájlt: Győződjön meg arról, hogy az nvm inicializáló scriptje hozzá lett adva a shell konfigurációs fájlhoz. A Zsh esetében ez általában a ~/.zshrc fájl. Nyissa meg ezt a fájlt egy szövegszerkesztővel (pl. nano ~/.zshrc vagy vim ~/.zshrc) és ellenőrizze, hogy az alábbi sorok szerepelnek-e benne: export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm")" [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
  2. Forrásként Töltsön Be Újra: Miután megbizonyosodott arról, hogy a fenti sorok szerepelnek a ~/.zshrc fájlban, töltse be a konfigurációt újra a következő paranccsal: source ~/.zshrc
  3. Újraindítás: Néha egy egyszerű újraindítás megoldhatja a problémát. Zárja be a terminált, majd nyissa meg újra, és próbálja meg újra futtatni az nvm --version parancsot.
  4. Telepítési Script Újrafuttatása: Ha a fenti lépések nem működnek, érdemes lehet újra futtatni a telepítési scriptet, és figyelmesen követni az esetleges hibajavítási utasításokat.
  5. Manuális Beavatkozás: Amennyiben a telepítési script nem adta hozzá az nvm inicializáló parancsokat a ~/.zshrc fájlhoz, manuálisan is hozzáadhatja őket.

Filed Under: Other

Generate PDF with Angular

Igen, az Angularban létrehozott reaktív form adatai alapján PDF-et lehet generálni. Ehhez általában egy harmadik féltől származó könyvtárat (pl. pdfmake) szokás használni.

Íme egy egyszerű lépésről lépésre terv a reaktív form adatai alapján PDF generálásához Angularban:

  1. Hozza létre a reaktív formot: Elsőként egy egyszerű reaktív formot kell létrehoznia az Angular alkalmazásban, ha még nem rendelkezik vele.
   form: FormGroup;

   constructor(private fb: FormBuilder) {
     this.form = this.fb.group({
       nev: ['', Validators.required],
       email: ['', [Validators.required, Validators.email]]
       // és így tovább...
     });
   }
  1. Telepítse a pdfmake könyvtárat: Ezt a könyvtárat használhatja a PDF generálásához. Telepítheti npm vagy yarn segítségével:
   npm install pdfmake
  1. Generálja le a PDF-et a form adatai alapján:
   import * as pdfMake from 'pdfmake/build/pdfmake';
   import * as pdfFonts from 'pdfmake/build/vfs_fonts';

   pdfMake.vfs = pdfFonts.pdfMake.vfs;

   generatePDF() {
     if (this.form.valid) {
       const docDefinition = {
         content: [
           { text: 'Adatok', style: 'header' },
           { text: `Név: ${this.form.get('nev').value}` },
           { text: `Email: ${this.form.get('email').value}` },
           // és így tovább...
         ]
       };

       pdfMake.createPdf(docDefinition).download('adatok.pdf');
     } else {
       alert('Kérjük, töltse ki az összes szükséges mezőt.');
     }
   }
  1. Hozzon létre egy gombot, amely elindítja a PDF generálását:
   <form [formGroup]="form">
     <!-- űrlap elemek ... -->
     <button (click)="generatePDF()">PDF generálása</button>
   </form>

Ez egy nagyon egyszerű példa, de természetesen további beállításokkal, stílusokkal és egyéb opciókkal is bővítheti a generált PDF tartalmát és kinézetét.

Stílus hozzáadása

A pdfmake könyvtár számos beállítást és stílusopciót kínál a PDF tartalmának és kinézetének testreszabásához. Íme néhány példa, amelyek segíthetnek a PDF tartalmának stílusos formázásában:

  1. Alapvető stílusok:
  • bold: Igaz/hamis értékkel állítható.
  • italics: Igaz/hamis értékkel állítható.
  • color: Hexadecimális színkódokat használ.
  1. Szöveg mérete és stílusa:
  • fontSize: A szöveg mérete pontokban.
  • font: Betűtípus neve.
  1. Táblázatok:
  • table: Táblázat adatok és beállítások.
  • layout: A táblázat elrendezése.
  1. Lista stílusok:
  • ul: Nem rendezett lista.
  • ol: Rendezett lista.
  1. Margók és padding:
  • margin: [felső, jobb, alsó, bal] margó beállítások.
  • alignment: Szöveg igazítása (left, right, center stb.)

Íme egy példa a fenti stílusok alkalmazására:

const docDefinition = {
  content: [
    { text: 'Cím', style: 'header' },
    {
      text: `Név: ${this.form.get('nev').value}`,
      fontSize: 14,
      bold: true,
      margin: [0, 0, 0, 10]
    },
    {
      text: `Email: ${this.form.get('email').value}`,
      italics: true,
      color: '#666666'
    },
    {
      table: {
        body: [
          ['Fejléc1', 'Fejléc2'],
          ['Adat1', 'Adat2'],
          ['Adat3', 'Adat4']
        ]
      },
      layout: 'lightHorizontalLines'
    },
    {
      ol: [
        'Első elem',
        'Második elem',
        'Harmadik elem'
      ],
      margin: [0, 20]
    }
  ],
  styles: {
    header: {
      fontSize: 22,
      bold: true,
      margin: [0, 0, 0, 10]
    }
  }
};

pdfMake.createPdf(docDefinition).download('adatok.pdf');

A fenti kód példázza, hogyan lehet az alapvető stílusokat és egyéb formázási lehetőségeket alkalmazni a pdfmake könyvtár segítségével. A hivatalos dokumentációban sokkal több stílus és opció található, így érdemes ott további részletekért és lehetőségekért keresgélni.

PDF küldése emailen

A PDF-et egy e-mailhez csatolva nem lehet egyszerűen és közvetlenül az ügyfél oldaláról elküldeni a böngésző korlátozásai miatt. Azonban a következő általános lépéseket követve megoldható:

  1. Generálja le és tárolja el a PDF-et a memóriában vagy egy szerveren: Miután létrehozta a PDF-et a pdfmake-kel, elmentheti azt a memóriában, vagy közvetlenül feltöltheti egy szerverre, ahelyett, hogy letöltené azt.
  2. Küldjön egy kérést a szervernek: Miután a PDF elkészült és el van tárolva, küldjön egy HTTP kérést egy backend szervernek az e-mail cím és a PDF helye (vagy maga a PDF bináris adat formájában, ha nem túl nagy) adataival.
  3. Használjon egy e-mail küldő szolgáltatást a backendben: A backend szerverén használjon egy e-mail küldő szolgáltatást, mint például a SendGrid, a Mailgun, az AWS SES stb. Ezek a szolgáltatások API-kat kínálnak, amelyek lehetővé teszik az e-mailek programozott küldését.
  4. Küldje el az e-mailt a csatolt PDF-fájllal: Amikor a szerver megkapja a kérést az ügyfél oldaláról, elkészíti az e-mailt, csatolja a PDF-et, és elküldi a megadott e-mail címre az e-mail küldő szolgáltatás segítségével.

Példaként egy egyszerű Express.js backend használatával és a nodemailer könyvtárral való e-mail küldésre:

const express = require('express');
const nodemailer = require('nodemailer');

const app = express();

app.post('/send-email', async (req, res) => {
  let transporter = nodemailer.createTransport({
    service: 'gmail',
    auth: {
      user: 'your-email@gmail.com',
      pass: 'your-password'
    }
  });

  let info = await transporter.sendMail({
    from: 'your-email@gmail.com',
    to: 'recipient-email@example.com',
    subject: 'Your PDF',
    text: 'Here is your PDF!',
    attachments: [{
      filename: 'document.pdf',
      path: 'path/to/your/pdf' // This should be the path where you saved your PDF
    }]
  });

  res.send('Email sent!');
});

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

Figyelem: A fenti példában a Gmailt használjuk az e-mailek küldésére, de ez nem biztonságos, és nem ajánlott produkciós környezetben. Ehelyett használjon hivatalos e-mail küldő szolgáltatást, mint amilyen a SendGrid vagy a Mailgun.

Emellett győződjön meg róla, hogy az érzékeny adatokat, mint például a jelszavakat vagy az API kulcsokat, nem tárolja közvetlenül a kódban, hanem környezeti változókban vagy titkosított konfigurációs fájlokban.

Filed Under: Other

  • « Go to Previous Page
  • Page 1
  • Interim pages omitted …
  • Page 4
  • Page 5
  • Page 6
  • Page 7
  • Page 8
  • Interim pages omitted …
  • Page 11
  • Go to Next Page »

Primary Sidebar

  • angular.io
© 2026 WP Flames - All Right Reserved