• Skip to main content
  • Skip to primary sidebar

Web Development Archive

  • Archive
You are here: Home / Archives for Other

Other

AdBlock Detector in Angular

adblock.service.ts

import { Injectable } from '@angular/core';

@Injectable({ providedIn: 'root' })
export class AdblockService {
public detect(): Promise<boolean> {
return new Promise((resolve) => {
const script = document.createElement('script');
script.src = 'https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js';
script.async = true;
script.onload = (): void => resolve(false);
script.onerror = (): void => resolve(true);
document.body.appendChild(script);
});
}
}

app.component.ts

private readonly _adblockService = inject(AdblockService);

public ngOnInit(): void {
this._adblockService.detect().then((isBlocked) => {
if (isBlocked) {
console.log('AdBlock true');
this.adBlockModal();
} else {
console.log('AdBlock false');
}
})
}

Filed Under: Other

Localized Routes

export const localizedRoutes: Record<string, Record<string, string>> = {
hu: {
home: '',
'cookie-policy': 'suti-szabalyzat',
'privacy-policy': 'adatvedelmi-szabalyzat'
},
en: {
home: '',
'cookie-policy': 'cookie-policy',
'privacy-policy': 'privacy-policy'
},
de: {
home: '',
'cookie-policy': 'cookie-richtlinie',
'privacy-policy': 'datenschutz'
}
};

app.routes.ts

import { Routes } from '@angular/router';
import { localizedRoutes } from './localized-routes';

export const generateLocalizedRoutes = (lang: string): Routes => {
const routesForLang = localizedRoutes[lang];

return [
{
path: routesForLang['home'],
loadComponent: () => import('./features/home/home.component').then((m) => m.HomeComponent),
data: {
title: 'TITLE.HOME'
}
},
{
path: routesForLang['cookie-policy'],
loadComponent: () =>
import('./features/cookie-policy/cookie-policy.component').then((m) => m.CookiePolicyComponent),
data: {
title: 'TITLE.COOKIE_POLICY'
}
},
{
path: routesForLang['privacy-policy'],
loadComponent: () =>
import('./features/privacy-policy/privacy-policy.component').then((m) => m.PrivacyPolicyComponent),
data: {
title: 'TITLE.PRIVACY_POLICY'
}
},
{
path: routesForLang['terms-and-conditions'],
loadComponent: () =>
import('./features/terms-and-conditions/terms-and-conditions.component').then(
(m) => m.TermsAndConditionsComponent
),
data: {
title: 'TITLE.TERMS_AND_CONDITIONS'
}
},
{
path: routesForLang['impressum'],
loadComponent: () => import('./features/impressum/impressum.component').then((m) => m.ImpressumComponent),
data: {
title: 'TITLE.IMPRESSUM'
}
},
{
path: routesForLang['404'],
loadComponent: () => import('./core/not-found/not-found.component').then((m) => m.NotFoundComponent),
data: {
title: 'TITLE.NOT_FOUND'
}
},
{
path: '**',
redirectTo: routesForLang['404']
}
];
};

const langs = ['hu', 'en', 'de'];
export const routes: Routes = [
...langs.map((lang) => ({
path: lang,
children: generateLocalizedRoutes(lang)
})),
{ path: '', redirectTo: 'hu', pathMatch: 'full' },
{ path: '**', redirectTo: 'hu/404' }
];

Filed Under: Other

ReCaptcha in Angular

recaptcha.service.ts

import { Injectable } from '@angular/core';

import { environment } from '../../../environments/environment';

@Injectable({
providedIn: 'root'
})
export class RecaptchaService {
public loadRecaptchaScript(): void {
const script = document.createElement('script');
script.src = `https://www.google.com/recaptcha/api.js?render=${environment.recaptchaSiteKey}`;
script.async = true;
script.defer = true;

document.head.appendChild(script);
}
}

environment.ts

export const environment = {
recaptchaSiteKey: 'xxxxxxxxxxxxxxxx',
};

app.component.ts

private readonly _recaptchaService = inject(RecaptchaService);

public ngOnInit(): void {
if (isPlatformBrowser(this._platformId)) {
this._recaptchaService.loadRecaptchaScript();
}
}

Filed Under: Other

Swiper as WebComponent with AutoPlay

<section class="news">
<div class="container">
<h2 class="news-title">Látásmódunk - néhány kiragadott példán keresztül</h2>

<div class="news-swiper">

<!-- Swiper Container -->
<swiper-container
#swiperRef
[slidesPerView]="1"
[spaceBetween]="10"
[loop]="true"
autoplay-delay="3000"
autoplay-disable-on-interaction="true"
autoplay-pause-on-mouse-enter="true"
>
<swiper-slide *ngFor="let news of newsItems">
<article class="news-card">
<div class="news-card-overlay"></div>
<picture>
<source media="(min-width: 1200px)" [srcset]="news.img_xl">
<source media="(min-width: 992px)" [srcset]="news.img_lg">
<source media="(min-width: 768px)" [srcset]="news.img_md">
<img class="news-image" [src]="news.img_sm" [alt]="news.alt" />
</picture>
<div class="news-caption">
<h3 class="news-caption-title">{{ news.title }}</h3>
<app-button [link]="news.link" [label]="'CTA.READMORE' | transloco"></app-button>
</div>
</article>
</swiper-slide>
</swiper-container>

<!-- Custom Pagination -->
<div class="news-pagination">
<div
class="pagination-item"
*ngFor="let news of newsItems; let i = index"
[class.active]="i === activeIndex"
(click)="setActiveSlide(i)"
>
<span class="pagination-progress" [class.running]="i === activeIndex"></span>
<span class="pagination-label">
{{ news.title }}
</span>
</div>
</div>
<span class="news-swiper-overlay"></span>
</div>
</div>
</section>
import { Component, CUSTOM_ELEMENTS_SCHEMA, PLATFORM_ID, Inject, ViewChild, ElementRef } from '@angular/core';
import { ButtonComponent } from '../../../../shared/components';
import { TranslocoPipe } from '@jsverse/transloco';
import { MockNews } from './news.mock';
import { News } from './news.model';
import { CommonModule, isPlatformBrowser } from '@angular/common';

import { register, SwiperContainer } from 'swiper/element/bundle';
register();



@Component({
selector: 'app-news',
imports: [CommonModule, ButtonComponent, TranslocoPipe],
templateUrl: './news.component.html',
styleUrl: './news.component.scss',
schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class NewsComponent {
@ViewChild('swiperRef', { static: true })
protected _swiperRef!: ElementRef<HTMLElement>;

newsItems: readonly News[] = MockNews;
activeIndex: number = 0;

constructor(@Inject(PLATFORM_ID) private platformId: object) {}

ngAfterViewInit() {
if (!isPlatformBrowser(this.platformId)) return;
const el = this._swiperRef.nativeElement as any;

el.addEventListener('slidechange', (e: any) => {
this.activeIndex = e.detail[0].realIndex;
});

el.initialize();
}

setActiveSlide(idx: number) {
if (!isPlatformBrowser(this.platformId)) return;
const swiper = (this._swiperRef.nativeElement as any).swiper;
swiper.slideToLoop(idx);
this.activeIndex = idx;
}

}
@use "shared" as *;

.news{
background: var(--color-black);
color: var(--color-white);
&-swiper{
position: relative;
padding-bottom: 80px;

}
&-title{
font-size: 32px;
text-align: center;
line-height: 120%;
margin-bottom: 48px;
@include media-breakpoint-up(md){
font-size: 40px;
}
}
&-card {
position: relative;
display: inline-block;
width: 100%;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 8px 24px rgba(0,0,0,0.2);
&-overlay{
background: linear-gradient(180deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.9) 70%);
position: absolute;
width: 100%;
height: 70%;
bottom: 0;
left: 0;
z-index: 9;
}
}
&-image {
display: block;
width: 100%;
height: auto;
object-fit: cover;
}
&-caption {
position: absolute;
bottom: 100px;
left: 0px;
right: 20px;
text-align: left;
padding: 60px 24px 32px;
width: 100%;
z-index: 9;
@include media-breakpoint-up(md){
padding: 60px 32px 40px;
}
&-title {
font-weight: bold;
line-height: 1.2;
margin-bottom: 24px;
font-size: 20px;
position: relative;
z-index: 999;
@include media-breakpoint-up(md){
font-size: 24px;
max-width: 423px;
}
}
}
&-pagination {
position: absolute;
bottom: 110px;
left: 32px;
display: flex;
justify-content: space-between;
padding: 0;
gap: 16px;
margin-top: 32px;
z-index: 9;
@include media-breakpoint-up(md){
margin-top: 45px;
}
@include media-breakpoint-up(lg){
margin-top: 48px;
gap: 32px;
}
.pagination-item {
flex: 1;
position: relative;
cursor: pointer;
border-top: 2px solid var(--color-grey-400);
transition: opacity 0.3s, border-color 0.3s;
width: 100%;

.pagination-progress {
position: absolute;
top: -2px;
left: 0;
height: 2px;
width: 0;
background-color: var(--color-primary);
transition: width 1s;
}

.pagination-label {
display: none;
@include media-breakpoint-up(lg){
display: block;
font-size: 14px;
line-height: 1.4;

color: var(--color-grey-400);
display: block;
margin-top: 8px;
}
}

&.active,
&:hover {
opacity: 1;
border-top-color: var(--color-primary);
.pagination{
&-progress {
width: 100%;
}
&-label{
color: var(--color-white);
}
}
}
}

.pagination-item.active .pagination-progress {
background-color: var(--color-primary);
}
}
}



swiper-container {
width: 100%;
}

swiper-slide {
display: flex;
justify-content: center;
align-items: center;
font-size: 1.5rem;
}

Filed Under: Other

Mock in Angular

export interface News{
id: string;
title: string;
link: string;
alt: string;
img_sm: string;
img_md: string;
img_lg: string;
img_xl: string;
}
import { News } from "./news.model";

export const MockNews: readonly News[] = [
{
id: '1',
title: 'Lorem ipsum sit amet 1',
link: 'https://trendency.hu',
alt: 'Kép 1',
img_sm: './assets/pictures/news/article-1/img-1-sm.jpg',
img_md: './assets/pictures/news/article-1/img-1-md.jpg',
img_lg: './assets/pictures/news/article-1/img-1-lg.jpg',
img_xl: './assets/pictures/news/article-1/img-1-xl.jpg'
},
{
id: '2',
title: 'Lorem ipsum sit amet 1',
link: 'https://trendency.hu',
alt: 'Kép 2',
img_sm: './assets/pictures/news/article-2/img-2-sm.jpg',
img_md: './assets/pictures/news/article-2/img-2-md.jpg',
img_lg: './assets/pictures/news/article-2/img-2-lg.jpg',
img_xl: './assets/pictures/news/article-2/img-2-xl.jpg'
},
];
newsItems: readonly News[] = MockNews;

Filed Under: Other

Swiper in Angular as WebComponent

npm install swiper
import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { register } from 'swiper/element/bundle';

register();

@Component({
selector: 'app-news',
imports: [],
templateUrl: './news.component.html',
styleUrl: './news.component.scss',
schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class NewsComponent {}
<swiper-container
slides-per-view="1"
space-between="10"
pagination="true"
navigation="true"
loop="true"
>
<swiper-slide>
<img src="assets/images/slide1.jpg" alt="Slide 1" />
</swiper-slide>
<swiper-slide>
<img src="assets/images/slide2.jpg" alt="Slide 2" />
</swiper-slide>
<swiper-slide>
<img src="assets/images/slide3.jpg" alt="Slide 3" />
</swiper-slide>
</swiper-container>
swiper-container {
width: 100%;
height: 400px;
}

swiper-slide {
display: flex;
justify-content: center;
align-items: center;
font-size: 1.5rem;
background: #f5f5f5;
}

Filed Under: Other

Where to put robots.txt in Angular

public/robots.txt
User-agent: *
Disallow:

Filed Under: Other

Favicon in Angular

Angular 19-ben a favicon beállítása ugyanúgy történik, mint a korábbi verziókban. Itt van a lépések listája, hogyan állíthatod be a saját faviconodat:


🔧 Lépések:

1. Tedd be a favicon fájlt a projektedbe

Helyezd el a saját favicon.ico (vagy .png, .svg) fájlodat a src mappába. Például:

src/assets/favicon.ico

2. Frissítsd az index.html fájlt

Nyisd meg a src/index.html fájlt, és módosítsd vagy add hozzá a következő sort a <head> szekcióba:

<link rel="icon" type="image/x-icon" href="assets/favicon.ico">

Ha .png vagy .svg típusút használsz, akkor módosítsd a MIME típust, pl. type="image/png".

3. (Ha van régi favicon) Töröld vagy cseréld le az eredetit

Ha a projektben már van egy alapértelmezett favicon.ico (pl. a src/favicon.ico), azt cseréld le a sajátodra vagy töröld, és használj assets mappás hivatkozást, ahogy fentebb írtam.

4. Build újra a projektet

Ha ng serve-öt használsz, néha újra kell indítani, vagy a cache törlése kell, hogy a böngésző frissítse a favicon-t.


💡 Tipp:

Használhatsz több formátumot és méretet is, pl.:

<link rel="icon" type="image/png" sizes="32x32" href="assets/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="assets/favicon-16x16.png">

Szeretnéd .ico helyett modern .svg formátumban használni? Vagy legyen sötét módhoz más favicon is? Szívesen segítek abban is!

Filed Under: Other

UnderScore to Space Directive

Only when typeof string

import {
Directive,
ElementRef,
Input,
OnChanges,
OnInit,
Renderer2,
SimpleChanges,
} from '@angular/core';

@Directive({
selector: '[appUnderscoreToSpace]',
})
export class UnderscoreToSpaceDirective implements OnInit, OnChanges {
@Input('appUnderscoreToSpace') text?: string;

constructor(private el: ElementRef, private renderer: Renderer2) {}

private updateText(): void {
if (typeof this.text === 'string') {
const transformedText = this.text.replace(/_/g, ' ');
this.renderer.setProperty(
this.el.nativeElement,
'textContent',
transformedText
);
}
}

ngOnInit(): void {
this.updateText();
}

ngOnChanges(changes: SimpleChanges): void {
if (changes['text']) {
this.updateText();
}
}
}

Filed Under: Other

Angular Boolean Service

Service

BehaviorSubject létrehozása, amely egy figyelhető boolean értéket tárol.

private readonly _isLoginPageBs$ = new BehaviorSubject<boolean>(false);

Observable létrehozása, hogy a külső kód figyelhesse, de ne módosíthassa az állapotot.

public readonly isLoginPageObs$ = this._isLoginPageBs$.asObservable();

Getter metódust definiál, amely az _isLoginPageBs$ aktuális értékét (value) adja vissza szinkron módon.

public get isLoginPage(): boolean {
return this._isLoginPageBs$.value;
}

Setter metódust definiál, amely az _isLoginPageBs$ értékét frissíti a megadott isLoginPage értékre.

public set isLoginPage(isLoginPage: boolean) {
this._isLoginPageBs$.next(isLoginPage);
}

Parent component

private readonly _headerNavService = inject(HeaderNavService);
public isLoginPage: boolean;

public ngOnInit(): void {
this._initIsLoginPage();
}

private _initIsLoginPage(): void {
this._headerNavService.isLoginPageObs$.pipe(takeUntil(this._destroy$)).subscribe((isLoginPage: boolean) => {
this.isLoginPage = isLoginPage;
this._cdr.markForCheck();
console.log(isLoginPage);
});
}

Child component

private readonly _headerNavService = inject(HeaderNavService);
@Input() public isLoginPage: boolean;

public ngOnInit(): void {
this._setLoginPage();
}

private _setLoginPage(): void {
this._headerNavService.isLoginPage = true;
}

Filed Under: Other

  • « Go to Previous Page
  • Page 1
  • Page 2
  • Page 3
  • Page 4
  • Interim pages omitted …
  • Page 11
  • Go to Next Page »

Primary Sidebar

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