
In previous articles, we have given an overview of Angular . In the part of custom instructions, we have been able to write them, but in actual scenarios, we still need standardized management.
Angular is an upgraded version of Angular.js. [Recommended related tutorials: "Angular Tutorial"]
So, in this article, we will use Tooltip to explain the content of custom instructions.
Online renderings, as follows:

The directory structure
is based on the code project implemented in the previous article. Execute the command line:
# Enter the directives folder $ cd directives #Create tooltip folder$ mkdir tooltip # Enter the tooltip folder $ cd tooltip # Create tooltip component $ ng generate component tooltip # Create tooltip directive $ ng generate directive tooltip
After executing the above command line, you will get the file directory structure of app/directive/tooltip as follows:
tooltip ├── tooltip // tooltip component │ ├── user-list.component.html // page skeleton │ ├── user-list.component.scss // page unique style │ ├── user-list.component. spec.ts // Test file │ └── user-list.component.ts // javascript file ├── tooltip.directive.spec.ts // Test file └── tooltip.directive.ts // Directive file
Well, Here I put the component at the same level as tooltip , mainly to facilitate management. Of course, this varies from person to person, you can put it in the public components folder.
Write the tooltip component
in the html file:
<div class="caret"></div>
<div class="tooltip-content">{{data.content}}</div> In the style file .scss , there is:
$black: #000000;
$white: #ffffff;
$caret-size: 6px;
$tooltip-bg: transparentize($black, 0.25); // transparentize is the syntax of sass $grid-gutter-width: 30px;
$body-bg-color: $white;
$app-anim-time: 200ms;
$app-anim-curve: ease-out;
$std-border-radius: 5px;
$zindex-max: 100;
// :host pseudo-class selector, sets the style for the component element itself: host {
position: fixed;
padding: $grid-gutter-width/3 $grid-gutter-width/2;
background-color: $tooltip-bg;
color: $body-bg-color;
opacity: 0;
transition: all $app-anim-time $app-anim-curve;
text-align: center;
border-radius: $std-border-radius;
z-index: $zindex-max;
}
.caret { // caret width: 0;
height: 0;
border-left: 6px solid transparent;
border-right: 6px solid transparent;
border-bottom: 6px solid $tooltip-bg;
position: absolute;
top: -$caret-size;
left: 50%;
margin-left: -$caret-size/2;
border-bottom-color: $tooltip-bg;
} Hmm~,
cssis a magical thing, and I will arrange an article to explainsassrelated content...
Then, the content of the javascript file tooltip.component.ts is as follows:
import {
Component,
ElementRef, //The element points to HostBinding,
OnDestroy,
OnInit
} from '@angular/core';
@Component({
selector: 'app-tooltip', // Identifier, indicating what my component is called, here is app-tooltip
templateUrl: './tooltip.component.html', // The skeleton of this component styleUrls: ['./tooltip.component.scss'] // The private style of this component})
export class TooltipComponent implements OnInit {
public data: any; // Assign a value to the directive private displayTimeOut: any;
// The decorator related to the host binding of the component itself @HostBinding('style.top') hostStyleTop!: string;
@HostBinding('style.left') hostStyleLeft!: string;
@HostBinding('style.opacity') hostStyleOpacity!: string;
constructor(
private elementRef: ElementRef
) { }
ngOnInit(): void {
this.hostStyleTop = this.data.elementPosition.bottom + 'px';
if(this.displayTimeOut) {
clearTimeout(this.displayTimeOut)
}
this.displayTimeOut = setTimeout((_: any) => {
// Calculate the distance between the tooltip and the left side here. The calculation formula here is: tooltip.left + .width of the target element - (tooltip.width/2)
this.hostStyleLeft = this.data.elementPosition.left + this.data.element.clientWidth / 2 - this.elementRef.nativeElement.clientWidth / 2 + 'px'
this.hostStyleOpacity = '1';
this.hostStyleTop = this.data.elementPosition.bottom + 10 + 'px'
}, 500)
}
// Component is destroyed ngOnDestroy() {
// After the component is destroyed, clear the timer to prevent memory leaks if(this.displayTimeOut) {
clearTimeout(this.displayTimeOut)
}
}
} Writing tooltip instructions
is the focus of this article. I will mark the specific instructions on the code ~
The content of the relevant file tooltip.directive.ts is as follows:
import {
ApplicationRef, // Global call detection ComponentFactoryResolver, // Create component object ComponentRef, // The association and guidance of the component instance, pointing to the element created by ComponentFactory Directive, ElementRef,
EmbeddedViewRef, // EmbeddedViewRef inherits from ViewRef and is used to represent UI elements defined in template elements.
HostListener, // DOM event listening Injector, // Dependency injection Input
} from '@angular/core';
import { TooltipComponent } from './tooltip/tooltip.component';
@Directive({
selector: '[appTooltip]'
})
export class TooltipDirective {
@Input("appTooltip") appTooltip!: string;
private componentRef!: ComponentRef<TooltipComponent>;
// Get the relative position of the target element, such as left, right, top, bottom
get elementPosition() {
return this.elementRef.nativeElement.getBoundingClientRect();
}
constructor(
protected elementRef: ElementRef,
protected appRef: ApplicationRef,
protected componentFactoryResolver: ComponentFactoryResolver,
protected injector: Injector
) { }
//Create tooltip
protected createTooltip() {
this.componentRef = this.componentFactoryResolver
.resolveComponentFactory(TooltipComponent) // Bind tooltip component.create(this.injector);
this.componentRef.instance.data = { // Bind data data content: this.appTooltip,
element: this.elementRef.nativeElement,
elementPosition: this.elementPosition
}
this.appRef.attachView(this.componentRef.hostView); //Add view const domElem = (this.componentRef.hostView as EmbeddedViewRef<any>).rootNodes[0] as HTMLElement;
document.body.appendChild(domElem);
}
// Delete tooltip
protected destroyTooltip() {
if(this.componentRef) {
this.appRef.detachView(this.componentRef.hostView); // Remove the view this.componentRef.destroy();
}
}
// Listen for mouse movement into @HostListener('mouseover')
OnEnter() {
this.createTooltip();
}
// Listen for mouse movement out@HostListener('mouseout')
OnOut() {
this.destroyTooltip();
}
} At this point, 99% of the functions have been completed. Now we can call it on the page.
On the page, we call
us to add the following content to user-list.component.html :
<p style="margin-top: 100px;">
<!-- [appTooltip]="'Hello Jimmy'" is the key point-->
<span
[appTooltip]="'Hello Jimmy'"
style="margin-left: 200px; width: 160px; text-align: center; padding: 20px 0; display: inline-block; border: 1px solid #999;"
>Jimmy</span>
</p> We have declared the TooltipDirective instruction on app.module.ts , and we can call it directly. The current effect is as follows:

tooltip we implemented is displayed in the bottom center, which is what we usually use the framework, such as the bottom attribute of tooltip in angular ant design . For other attributes, if readers are interested, they can be expanded.
At this point, we can well maintain the instruction files we wrote.