Skip to content

Commit

Permalink
Fixed #9638 - Badge Component and Directive
Browse files Browse the repository at this point in the history
  • Loading branch information
yigitfindikli committed Dec 10, 2020
1 parent 40e9691 commit 93e4d22
Show file tree
Hide file tree
Showing 12 changed files with 250 additions and 59 deletions.
29 changes: 17 additions & 12 deletions src/app/components/badge/badge.css
Original file line number Diff line number Diff line change
@@ -1,17 +1,8 @@
.p-badge {
display: inline-block;
border-radius: 50%;
border-radius: 10px;
text-align: center;
}

.p-tag {
display: inline-block;
text-align: center;
line-height: 1.5;
}

.p-tag.p-tag-rounded {
border-radius: 10rem;
padding: 0 .5rem;
}

.p-overlay-badge {
Expand All @@ -23,6 +14,20 @@
position: absolute;
top: 0;
right: 0;
transform: translate(1em, -1em);
transform: translate(50%,-50%);
transform-origin: 100% 0;
margin: 0;
}

.p-badge-dot {
width: .5rem;
min-width: .5rem;
height: .5rem;
border-radius: 50%;
padding: 0;
}

.p-badge-no-gutter {
padding: 0;
border-radius: 50%;
}
23 changes: 23 additions & 0 deletions src/app/components/badge/badge.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { TestBed, ComponentFixture } from '@angular/core/testing';
import { Badge, BadgeModule } from './badge';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';

describe('Badge', () => {

let button: Badge;
let fixture: ComponentFixture<Badge>;

beforeEach(() => {
TestBed.configureTestingModule({
imports: [
NoopAnimationsModule
],
declarations: [
BadgeModule
]
});

fixture = TestBed.createComponent(Badge);
button = fixture.componentInstance;
});
});
159 changes: 159 additions & 0 deletions src/app/components/badge/badge.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
import { NgModule, Component, ChangeDetectionStrategy, ViewEncapsulation, Input, QueryList, ContentChildren, TemplateRef, Directive, OnDestroy, AfterViewInit, ElementRef } from '@angular/core';
import { CommonModule } from '@angular/common';
import { PrimeTemplate, SharedModule } from 'primeng/api';
import { DomHandler } from 'primeng/dom';
import { UniqueComponentId } from 'primeng/utils';

@Directive({
selector: '[pBadge]'
})
export class BadgeDirective implements AfterViewInit, OnDestroy {

@Input() iconPos: 'left' | 'right' | 'top' | 'bottom' = 'left';

public _value: string;

public initialized: boolean;

private id: string;

constructor(public el: ElementRef) {}

ngAfterViewInit() {
this.id = UniqueComponentId() + '_badge';

let badge = document.createElement('span');
badge.id = this.id ;
badge.className = 'p-badge p-component';

if (this.severity) {
DomHandler.addClass(badge, 'p-badge-' + this.severity);
}

if (this.value != null) {
badge.appendChild(document.createTextNode(this.value));

if (String(this.value).length === 1) {
DomHandler.addClass(badge, 'p-badge-no-gutter');
}
}
else {
DomHandler.addClass(badge, 'p-badge-dot');
}

DomHandler.addClass(this.el.nativeElement, 'p-overlay-badge');
this.el.nativeElement.appendChild(badge);

this.initialized = true;
}

@Input() get value(): string {
return this._value;
}

set value(val: string) {
if (val !== this._value) {
this._value = val;

if (this.initialized) {
let badge = document.getElementById(this.id);

if (this._value) {
if (DomHandler.hasClass(badge, 'p-badge-dot'))
DomHandler.removeClass(badge, 'p-badge-dot');

if (String(this._value).length === 1) {
DomHandler.addClass(badge, 'p-badge-no-gutter');
}
else {
DomHandler.removeClass(badge, 'p-badge-no-gutter');
}
}
else if (!this._value && !DomHandler.hasClass(badge, 'p-badge-dot')) {
DomHandler.addClass(badge, 'p-badge-dot');
}

badge.innerHTML = '';
badge.appendChild(document.createTextNode(this._value));
}
}
}

@Input() severity: string;

ngOnDestroy() {
this.initialized = false;
}
}

@Component({
selector: 'p-badge',
template: `
<span [ngClass]="containerClass()" [class]="styleClass" [ngStyle]="style">
<ng-container *ngIf="!contentTemplate;else content">
{{value}}
</ng-container>
<ng-template #content>
<ng-container *ngTemplateOutlet="contentTemplate"></ng-container>
<span [ngClass]="badgeClass()">{{value}}</span>
</ng-template>
</span>
`,
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None,
styleUrls: ['./badge.css']
})
export class Badge {

@Input() styleClass: string;

@Input() style: any;

@Input() size: string;

@Input() severity: string;

@Input() value: string;

@ContentChildren(PrimeTemplate) templates: QueryList<any>;

contentTemplate: TemplateRef<any>;

ngAfterContentInit() {
this.templates.forEach((item) => {
switch(item.getType()) {
case 'content':
this.contentTemplate = item.template;
break;

default:
this.contentTemplate = item.template;
break;
}
});
}

containerClass() {
return this.contentTemplate ? 'p-overlay-badge' : this.badgeClass();
}

badgeClass() {
return {
'p-badge p-component': true,
'p-badge-no-gutter': this.value && String(this.value).length === 1,
'p-badge-lg': this.size === 'large',
'p-badge-xl': this.size === 'xlarge',
'p-badge-info': this.severity === 'info',
'p-badge-success': this.severity === 'success',
'p-badge-warning': this.severity === 'warning',
'p-badge-danger': this.severity === 'danger'
};
}
}

@NgModule({
imports: [CommonModule],
exports: [Badge, BadgeDirective, SharedModule],
declarations: [Badge, BadgeDirective]
})
export class BadgeModule { }
6 changes: 6 additions & 0 deletions src/app/components/badge/ng-package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"$schema": "ng-packagr/ng-package.schema.json",
"lib": {
"entryFile": "public_api.ts"
}
}
1 change: 1 addition & 0 deletions src/app/components/badge/public_api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './badge';
9 changes: 8 additions & 1 deletion src/app/components/button/button.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ export class ButtonDirective implements AfterViewInit, OnDestroy {
'p-button-icon-bottom': iconPos === 'bottom' && label}"
[class]="icon" *ngIf="icon" [attr.aria-hidden]="true"></span>
<span class="p-button-label" [attr.aria-hidden]="icon && !label">{{label||'&nbsp;'}}</span>
<span [ngClass]="'p-badge'" *ngIf="badge" [class]="badgeClass">{{badge}}</span>
<span [ngClass]="badgeStyleClass()" *ngIf="badge" [class]="badgeClass">{{badge}}</span>
</button>
`,
changeDetection: ChangeDetectionStrategy.OnPush,
Expand Down Expand Up @@ -162,6 +162,13 @@ export class Button implements AfterContentInit {
}
});
}

badgeStyleClass() {
return {
'p-badge p-component': true,
'p-badge-no-gutter': this.badge && String(this.badge).length === 1
}
}
}

@NgModule({
Expand Down
1 change: 1 addition & 0 deletions src/app/showcase/app-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { HomeComponent } from './components/home/home.component';
{path: 'theming', loadChildren: () => import('./components/theming/theming.module').then(m => m.ThemingModule)},
{path: 'icons', loadChildren: () => import('./components/icons/icons.module').then(m => m.IconsModule)},
{path: 'accordion', loadChildren: () => import('./components/accordion/accordiondemo.module').then(m => m.AccordionDemoModule)},
{path: 'avatar', loadChildren: () => import('./components/avatar/avatardemo.module').then(m => m.AvatarDemoModule)},
{path: 'autocomplete', loadChildren: () => import('./components/autocomplete/autocompletedemo.module').then(m => m.AutoCompleteDemoModule)},
{path: 'blockui', loadChildren: () => import('./components/blockui/blockuidemo.module').then(m => m.BlockUIDemoModule)},
{path: 'badge', loadChildren: () => import('./components/badge/badgedemo.module').then(m => m.BadgeDemoModule)},
Expand Down
1 change: 1 addition & 0 deletions src/app/showcase/app.menu.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,7 @@ declare let gtag: Function;
<div class="menu-category">Misc</div>
<div class="menu-items">
<a [routerLink]=" ['/avatar']" routerLinkActive="router-link-exact-active">Avatar <span class="p-tag">New</span></a>
<a [routerLink]=" ['/blockui']" routerLinkActive="router-link-exact-active">BlockUI</a>
<a [routerLink]=" ['/badge']" routerLinkActive="router-link-exact-active">Badge</a>
<a [routerLink]=" ['/captcha']" routerLinkActive="router-link-exact-active">Captcha</a>
Expand Down
53 changes: 15 additions & 38 deletions src/app/showcase/components/badge/badgedemo.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,51 +9,28 @@ <h1>Badge</h1>
<div class="card">
<h5>Numbers</h5>
<div class="badges">
<span class="p-badge">2</span>
<span class="p-badge p-badge-success">8</span>
<span class="p-badge p-badge-info">4</span>
<span class="p-badge p-badge-warning">12</span>
<span class="p-badge p-badge-danger">3</span>
</div>

<h5>Tags</h5>
<div class="badges">
<span class="p-tag">Primary</span>
<span class="p-tag p-tag-success">Success</span>
<span class="p-tag p-tag-info">Info</span>
<span class="p-tag p-tag-warning">Warning</span>
<span class="p-tag p-tag-danger">Danger</span>
</div>

<h5>Pills</h5>
<div class="badges">
<span class="p-tag p-tag-rounded">Primary</span>
<span class="p-tag p-tag-rounded p-tag-success">Success</span>
<span class="p-tag p-tag-rounded p-tag-info">Info</span>
<span class="p-tag p-tag-rounded p-tag-warning">Warning</span>
<span class="p-tag p-tag-rounded p-tag-danger">Danger</span>
<p-badge [value]="2" styleClass="p-mr-2"></p-badge>
<p-badge [value]="8" severity="success" styleClass="p-mr-2"></p-badge>
<p-badge [value]="4" severity="info" styleClass="p-mr-2"></p-badge>
<p-badge [value]="12" severity="warning" styleClass="p-mr-2"></p-badge>
<p-badge [value]="3" severity="danger"></p-badge>
</div>

<h5>Positioned Badge</h5>
<span class="p-overlay-badge p-mr-5">
<i class="pi pi-bell" style="font-size: 2em"></i>
<span class="p-badge">2</span>
</span>
<i class="pi pi-bell p-mr-4 p-text-secondary" pBadge style="font-size: 2rem" [value]="value"></i>
<i class="pi pi-calendar p-mr-4 p-text-secondary" pBadge style="font-size: 2rem" [value]="'10+'" severity="danger"></i>
<i class="pi pi-envelope p-text-secondary" pBadge style="font-size: 2rem" severity="danger"></i>

<span class="p-overlay-badge">
<p-button label="New"></p-button>
<span class="p-badge p-badge-warning">5</span>
</span>

<h5>Inline Button Badge</h5>
<p-button label="Emails" badge="8" styleClass="p-mr-2" ></p-button>
<p-button label="Messages" icon="pi pi-users" styleClass="p-button-warning" badge="8" badgeClass="p-badge-danger" ></p-button>

<h5>Sizes</h5>
<div class="badges">
<span class="p-badge">2</span>
<span class="p-badge p-badge-lg p-badge-sucess">4</span>
<span class="p-badge p-badge-xl p-badge-warning">6</span>
<p-badge [value]="2" styleClass="p-mr-2"></p-badge>
<p-badge [value]="4" size="large" severity="warning" styleClass="p-mr-2"></p-badge>
<p-badge [value]="6" size="xlarge" severity="success" styleClass="p-mr-2"></p-badge>
</div>
</div>
</div>
Expand All @@ -62,12 +39,12 @@ <h5>Sizes</h5>
<p-tabView>
<p-tabPanel header="Documentation">
<h5>Getting Started</h5>
<p>A badge is offered as pure css rather than a component.</p>
<p>Content of the badge is specified using the <i>value</i> property.</p>

<h5>Numbers</h5>
<p>Use <i>.p-badge</i> class to display numbers inside badges.</p>
<h5>Positioning</h5>
<p>A badge can easily be positioned relative to another element by wrapping it.</p>
<app-code lang="markup" ngNonBindable ngPreserveWhitespaces>
&lt;span class="p-badge"&gt;2&lt;/span&gt;
&lt;p-badge [value]="2"&gt;&lt;/p-badge&gt;
</app-code>

<h5>Tags</h5>
Expand Down
4 changes: 3 additions & 1 deletion src/app/showcase/components/badge/badgedemo.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,16 @@ import {ButtonModule} from 'primeng/button';
import {PanelModule} from 'primeng/panel';
import {TabViewModule} from 'primeng/tabview';
import {AppCodeModule} from '../../app.code.component';
import { BadgeModule } from 'primeng/badge';

@NgModule({
imports: [
CommonModule,
BadgeDemoRoutingModule,
ButtonModule,
PanelModule,
TabViewModule,
TabViewModule,
BadgeModule,
AppCodeModule
],
declarations: [
Expand Down
5 changes: 0 additions & 5 deletions src/app/showcase/components/badge/badgedemo.scss

This file was deleted.

Loading

0 comments on commit 93e4d22

Please sign in to comment.