ساخت دستورهای صفتی (Attribute Directive) دلخواه در انگولار

22 تیر 1396
angular-custom-attribute-directives

با مطالعه ۴ فصل گذشته به مباحث تخصصی مربوط به کامپوننت‌ها و دستورهای مقدماتی و کاربردی انگولار آشنا شدید. در این فصل قصد داریم شیرجه‌ای عمیق‌تر درون دستورهای انگولار بزنیم و شما را با نحوه‌ی ساخت دستورهای صفتی دلخواه بیشتر آشنا کنیم. با ما همراه باشید.

مقدمه

در فصل مربوط به دستورها، اطلاعات کلی در ارتباط با دستورهای (Directive) انگولار بدست آوردید و متوجه شدید که دستورهای موجود به دو دسته‌ی دستورهای صفتی یا Attribute و دستورهای ساختاری یا Structural تقسیم‌بندی می‌شوند. در ادامه مجددا تعریف هر یک از این نوع دستور را ارائه خواهیم داد:

دستورهای صفتی یا Attribute Directive: به دستورهایی گفته می‌شود که به عنوان یک صفت یا attribute در تگ‌های HTML مورد استفاده قرار می‌گیرند. مثلا دستور ngClass یک کلاس به تگ اضافه می‌کند و دخل و تصرفی در ساختار کلی صفحه ایجاد نخواهد کرد.

دستورهای ساختاری یا Structural Directive: به دستورهایی گفته می‌شود که به عنوان یک دستور ساختاری وارد عمل شده و تگ‌های HTML جدیدی به صفحه و قالب ما اضافه می‌کند. مانند دستور ngIf* که یک المان جدید را تولید و یا حذف می‌کند. به عبارت دیگر این نوع دستور در ساختار DOM تغییرات ایجاد خواهد کرد.

قبل از ورود به سایر مباحث موجود در این فصل از شما عزیزان خواهشمندیم فصل زیر را که حاوی دستورهای مقدماتی ساختاری و صفتی‌است مطالعه بفرمایید:

پس از مطالعه‌ی لینک فوق به ادامه‌ی این آموزش بپردازید.

یک مثال دیگر که در آن به صورت ترکیبی از دستورهای ngIf* و ngFor* و ngClass و همچنین ngStyle استفاده شده است، با یکدیگر بررسی خواهیم کرد. در این مثال از ارائه‌ی توضیحات مربوط به کدها خودداری کرده و تنها صورت مساله را مطرح می‌کنیم.

فرض کنید می‌خواهیم در یک صفحه اعداد زوج و فرد را به صورت مجرا نمایش دهیم. یعنی با کلیک روی یک دکمه مجموعه‌ی اعداد فرد نمایش داده شده که دارای استایل و کلاس خاص هستند. بنابراین در فایل app.component.html کدهای زیر را اعمال خواهیم کرد:

<div class="container" dir="rtl" style="margin-top: 30px;">
    <div class="row">
        <div class="col-xs-12">
            <button class="btn btn-primary" (click)="onlyFalse = !onlyFalse">نمایش اعداد فرد</button>
        </div>
        <br><br>
        <ul class="list-group">
            <div *ngIf="onlyFalse">
                <li class="list-group-item"
                    *ngFor="let odd of oddNumber"
                    [ngClass]="{odd: odd % 2 !== 0}"
                    [ngStyle]="{backgroundColor: odd % 2 !== 0 ? 'Yellow':'transparent'}"
                >
                    {{odd}}
                </li>
            </div>
            <div *ngIf="!onlyFalse">
                <li class="list-group-item"
                    *ngFor="let even of evenNumber"
                    [ngClass]="{even: even % 2 === 0}"
                    [ngStyle]="{backgroundColor: odd % 2 !== 0 ? 'Black':'transparent'}"
                >
                    {{even}}
                </li>
            </div>
        </ul>
    </div>
</div>

سپس در فایل app.component.ts یک سری ویژگی تعریف می‌کنیم:

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

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css']
})
export class AppComponent {
    numbers: number[] = [1,2,3,4,5,6,7,8,9,10];
    oddNumber: number[] = [1,3,5,7,9];
    evenNumber: number[] = [2,4,6,8,10];
    onlyFalse: boolean = false;

    onLoadOdd(){

    }
}

در نهایت فایل app.component.css را نیز به صورت زیر ارائه خواهیم داد تا در قالب HTML تغییرات متناسب با دستور ngClass اعمال شود:

.odd{
    color: red;
}
.even{
    color: yellow;
}

بسیار عالی! در صورتیکه از این مجموعه‌ی دستورات خروجی بگیرید باید با تصویر زیر مواجه شده باشید:

مثال دستورها انگولار

ساخت دستورهای صفتی دلخواه

خوشبختانه انگولار به عنوان فریم‌ورکی بسیار قدرتمند این قابلیت را برای ما فراهم می‌کند که دستورهای دلخواه خود را ایجاد کرده و از آنها متناسب با نوع ساختاری یا صفتی، استفاده کنیم.

برای ایجاد یک دستور باید ابتدا فایلی با پسوند directive.ts ایجاد کنیم. بنابراین یک پوشه به نام basic-highlight در مسیر اصلی ایجاد کرده و در نهایت دستورهای زیر را درون آن اعمال می‌کنیم:

import {Directive, ElementRef, OnInit} from "@angular/core";

@Directive({
    selector: '[appBasicHighlight]'
})
export class BasicHighlightDirective implements OnInit{
    constructor(private elementRef: ElementRef){}

    ngOnInit(){
        this.elementRef.nativeElement.style.backgroundColor = 'green'
    }
}

همانطور که در این فایل ملاحظه می‌کنید یک کلاس به نام BasicHighlightDirective ایجاد کرده‌ایم که یک سازنده‌ی پیشفرض و یک ویژگی به نام elemetRef به صورت private دارد. در نظر داریم که این سازنده‌ی پیشفرض تنها دریافت ورود مورد استفاده قرار می‌گیرد. در نهایت در هوک ngOnInit المان HTML‌ای که در این دستور روی آن اعمال می‌شود با تغییر رنگ پس زمینه روبه‌رو شده و رنگ آن به سبز تغییر می‌کند.

نکته‌ی دیگری که قابل تامل است استفاده از یک مفسر به نام Directive@ در ابتدای برنامه می‌باشد که درون آن یک سلکتور به صورت صفتی ( با علامت [ ]) ایجاد شده است.

حال پس از اعمال تغییرات فوق باید این دستور را به فایل app.module.ts معرفی کنیم:

import {BrowserModule} from '@angular/platform-browser';
import {HttpModule} from '@angular/http';
import {NgModule} from '@angular/core';
import {FormsModule} from '@angular/forms';

import {AppComponent} from './app.component';
import {BasicHighlightDirective} from './basic-highlight/basic-highlight.directive';


@NgModule({
    declarations: [
        AppComponent,
        BasicHighlightDirective
    ],
    imports: [
        BrowserModule,
        HttpModule,
        FormsModule
    ],
    providers: [],
    bootstrap: [AppComponent]
})
export class AppModule {
}

حال در ادامه برای اینکه بتوانیم از این دستور تولید شده استفاده کنیم باید درون فایل app.component.html یک تگ <p> ایجاد کرده و سپس دستور را به آن اعمال کنیم:

<p appBasicHighlight>این تگ تحت تاثیر دستور appBasicHighlight قرار گرفته است. روکسو</p>

حال اگر صفحه را مجددا بارگذاری کنید با تصویر زیر روبه‌رو خواهید شد.

نحوه ساخت یک دستور صفتی در انگولار

چقدر خوب! شما توانستید یک دستور صفتی دلخواه ایجاد کرده و سپس آن را روی یک تگ خاص لحاظ کنید.

اما این راه قطعا بهترین راه برای تغییر دادن استایل یک صفحه و ایجاد دستور یا Directive دلخواه نیست. بلکه بهترین راه استفاده از کلاس Renderer2 در انگولار می‌باشد که در ادامه به معرفی آن می‌پردازیم.

در واقع اگر به صورت مستقیم یک المان native از DOM را مورد هدف قرار داده و استایل آن را تغییر دهیم ممکن است در برخی از مرورگرها دچار مشکل شویم بنابراین منطقی‌ترین راه استفاده از ابزار بسیار قدرتمند Renderer2 است.

کلاس Renderer2

برای روشن‌تر شدن مفهوم این کلاس با یک مثال شروع می‌کنیم. در ابتدا با استفاده از دستور زیر یک directive درون فولدر better-highlight ایجاد می‌کنیم:

ng generate directive better-highlight/better-highlight

// or

ng g d better-highlight/better-highlight

سپس فایل better-highlight.directive.ts را باز کرده و دستورهای زیر را درون آن قرار می‌دهیم:

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

@Directive({
  selector: '[appBetterHighlight]'
})
export class BetterHighlightDirective implements OnInit{

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

  ngOnInit(){
    this.renderer.setStyle(this.elRef.nativeElement, 'background-color', 'blue')
  }

}

همانطور که ملاحظه می‌کنید برای دستور appBetterHighlight در ابتدا دو ویژگی درون سازنده به نام‌های elRef (برای دسترسی به المان HTML یا DOM) و renderer (جهت استفاده از کلاس Rendere2) تعریف کرده‌ایم.

سپس در هوک ngOnInit از کلاس Renderer2 و متد setStyle استفاده کرده و در نهایت مقدار آرگومان آن را به صورت زیر درج کرده‌ایم:

this.renderer.setStyle(elementRef, cssStyleAttribute, cssValue)

که آرگومان اول نشان‌دهنده نوع المان DOM، آرگومان دوم برابر صفت css و آرگومان سوم بیانگر مقدار css است.

در صورتیکه مثال فوق را به درستی انجام داده باشید با خروجی زیر روبه‌رو خواهید شد:

نحوه استفاده از کلاس Renderer2 در انگولار

بسیار عالی به شما تبریک می‌گوییم در این بخش توانستید به صورت استاندارد یک دستور صفتی را ایجاد کرده و مورد بررسی قرار دهید. در بخش بعدی به توضیح مفاهیم عمیق‌تری از دستورات پرداخته و شما را فضای جدیدی آشنا می‌کنیم. با ما همراه باشید.

توجه: دوستان عزیز آموزش ویدیویی انگولار 6 از مقدماتی تا پیشرفته به زبان فارسی را می‌توانید با کلیک روی اینجا یاد بگیرید.

دوره آموزش انگولار به زبان فارسی + پروژه ساخت فروشگاه اینترنتی

تمام فصل‌های سری ترتیبی که روکسو برای مطالعه‌ی دروس سری آموزش رایگان انگولار توصیه می‌کند:
نویسنده شوید

دیدگاه‌های شما (2 دیدگاه)

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

سید قاسم
16 اردیبهشت 1398
با سلام و خسته نباشید میشه به عنوان آرگومان دو تا خصوصیت css به همراه دوتا مقدار بهش پاس بدیم ؟؟؟ در واقع 5 تا آرگومان بهش بدیم مثل این مثال:(البته ارور داره روی پارامتر پنجم) ngOnInit(){ this.renderer.setStyle(this.elRef.nativeElement,'background-color','red','color','orange') }

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

آرش
19 فروردین 1398
سلام در آخرین قسمت blue به عنوان بک گراند انتخاب شد پس چرا نارنجی شده ؟

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

روکسو
19 فروردین 1398
سلام وقت شما بخیر شما می توانید از رنگ دلخواه خودتان استفاده کنید. دستورها درست هستند ولی خروجی روی حالت hover گرفته شده است.

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.