วิธีเพิ่ม“ คลาส” ในองค์ประกอบโฮสต์ได้อย่างไร


190

ฉันไม่ทราบวิธีการเพิ่มองค์ประกอบคลาสให้กับแอตทริบิวต์ของฉัน<component></component>แบบไดนามิกแต่ในเทมเพลต html (component.html)

ทางออกเดียวที่ฉันพบคือการแก้ไขรายการผ่านองค์ประกอบพื้นเมือง "ElementRef" วิธีแก้ปัญหานั้นดูซับซ้อนเล็กน้อยที่จะทำสิ่งที่ควรจะง่ายมาก

ปัญหาอีกประการหนึ่งคือ CSS จะต้องมีการกำหนดไว้นอกขอบเขตองค์ประกอบทำลายการห่อหุ้มส่วนประกอบ

มีวิธีแก้ไขที่ง่ายกว่านี้ไหม? บางสิ่งที่เหมือนกับ<root [class]="..."> .... </ root>ในเทมเพลต

คำตอบ:


296
@Component({
   selector: 'body',
   template: 'app-element',
   // prefer decorators (see below)
   // host:     {'[class.someClass]':'someField'}
})
export class App implements OnInit {
  constructor(private cdRef:ChangeDetectorRef) {}

  someField: boolean = false;
  // alternatively also the host parameter in the @Component()` decorator can be used
  @HostBinding('class.someClass') someField: boolean = false;

  ngOnInit() {
    this.someField = true; // set class `someClass` on `<body>`
    //this.cdRef.detectChanges(); 
  }
}

ตัวอย่างของพลั่ว

วิธีนี้คุณไม่จำเป็นต้องเพิ่ม CSS นอกองค์ประกอบ CSS ชอบ

:host(.someClass) {
  background-color: red;
}

ทำงานได้จากด้านในของส่วนประกอบและตัวเลือกจะถูกใช้เฉพาะในกรณีที่ชั้นเรียนsomeClassมีการตั้งค่าในองค์ประกอบโฮสต์


ผมต้องทำsomeField = trueในngOnInit()-method ngAfterViewInit()แทน ฉันไม่สามารถทำงานได้
จอห์น

ทำส้อมที่นี่ซึ่งแสดงให้เห็นว่า:hostส่วนที่เกิดขึ้นจริงทำงาน ฉันจะเรียนรู้เพิ่มเติมเกี่ยวกับพารามิเตอร์โฮสต์ใน @Component () decorator ได้อย่างไร (ไวยากรณ์ไม่ชัดเจนสำหรับฉันและเอกสาร @Component ไม่ได้อธิบายอะไรมาก ) หรือเรียนรู้เพิ่มเติมเกี่ยวกับ HostBinding ที่คุณต้องการ (เป็นเพียงรายการอินเทอร์เฟซบน ไซต์ Angular2?)
The Red Pea

ฉันไม่รู้จักเอกสารที่ดีขึ้น แต่มันเป็นวิธีที่แตกต่างในการทำสิ่งที่คุณสามารถทำได้ด้วย@Input() @Output() @HostBinding() @HostListener() @ViewChild(ren)() @ContentChild(ren)()
GünterZöchbauer

1
ใช้ getter ที่มีชื่อแตกต่างกันสำหรับการโยงโฮสต์ที่ส่งคืนค่า inverted@HostBinding('class.xxx') get xxxclass(){ return !this.someField;}
GünterZöchbauer

1
@YochaiAkoka ไม่แน่ใจว่าคุณหมายถึงอะไร ฉันไม่ได้ตระหนักถึงกฎนี้ โดยทั่วไปมักจะน้อยกว่าดังนั้นหากคุณสามารถหลีกเลี่ยงการเพิ่มองค์ประกอบเพิ่มเติมได้คุณควรหลีกเลี่ยง
GünterZöchbauer

184

คำตอบของGünterนั้นยอดเยี่ยม (คำถามคือการขอคุณลักษณะระดับไดนามิก ) แต่ฉันคิดว่าฉันจะเพิ่มเพียงเพื่อความสมบูรณ์ ...

หากคุณกำลังมองหาวิธีที่รวดเร็วและสะอาดในการเพิ่มคลาสแบบสแตติกหนึ่งรายการขึ้นไปเข้ากับองค์ประกอบโฮสต์ของส่วนประกอบของคุณ (เช่นเพื่อจุดประสงค์ในการออกแบบธีม) คุณสามารถทำได้:

@Component({
   selector: 'my-component',
   template: 'app-element',
   host: {'class': 'someClass1'}
})
export class App implements OnInit {
...
}

และถ้าคุณใช้คลาสบนแท็ก entry Angular จะรวมคลาสเช่น

<my-component class="someClass2">
  I have both someClass1 & someClass2 applied to me
</my-component>

1
รักสิ่งนี้เพื่อความเรียบง่าย อย่างไรก็ตามในกรณีของฉันองค์ประกอบโฮสต์ถูกห่อหุ้มด้วยคุณสมบัติที่แตกต่างกันลองเรียกมันว่าngcontent_hostกว่าแอตทริบิวต์ใด ๆ ในองค์ประกอบในแม่แบบของฉัน, let's call those ngcontent_template , so if I put a style in the styleUrls` องค์ประกอบของฉันพวกเขาจะไม่ส่งผลกระทบต่อองค์ประกอบโฮสต์เพราะพวกเขาจะไม่ส่งผลกระทบต่อngcontent_hostพวกเขา สามารถมีผลกับองค์ประกอบแม่แบบเท่านั้น ngcontent_templateพวกเขาสามารถส่งผลกระทบต่อเท่านั้น ฉันเข้าใจผิด ข้อเสนอแนะเกี่ยวกับเรื่องนี้? ฉันเดาว่าฉันสามารถเลี้ยวได้เสมอViewEncapsulation.None
Red Pea

11
อีกวิธีคือการข้ามตัวแปร, @HostBinding('class.someClass') true;. คุณสามารถทำได้แม้กระทั่งในคลาสใดก็ตามที่ส่วนประกอบของคุณขยาย
adamdport

3
ในการเพิ่มหลายคลาสคุณสามารถทำโฮสต์: {'[class]': '"class1 class2"'}
jbojcic

4
ถ้าคุณใช้โฮสต์: {}ตัวแปรคุณอาจต้องการชุดuse-host-property-decoratorการตั้งค่าไปในfalse tslint.jsonมิฉะนั้นคุณจะได้รับคำเตือนจาก IDE @adamdport วิธีการนี้ใช้ไม่ได้ (อีกต่อไป) ใช้ Angular 5.2.2 ในแอพของเรา
Ruud Voost

1
มันเป็นเพียงฉันหรือแบบเก่าดูดีกว่าวิธีใหม่หรือไม่? ฉันแน่ใจว่าพวกเขามีเหตุผลที่ดีในการโยกย้าย แต่ Meh ...
ปิ๊

13

คุณสามารถเพิ่ม@HostBinding('class') class = 'someClass';ในชั้นเรียน@Componentของคุณ

ตัวอย่าง:

@Component({
   selector: 'body',
   template: 'app-element'       
})
export class App implements OnInit {

  @HostBinding('class') class = 'someClass';

  constructor() {}      

  ngOnInit() {}
}

1
classNameสั่งนอกจากนี้ยังอาจจะใช้และมันจะดีกว่าที่จะหลีกเลี่ยงการใช้classชื่อตัวแปร (ตั้งแต่คุณอาจจะอ้างอิงและการเปลี่ยนแปลงในภายหลัง) ตัวอย่าง: @HostBinding('className') myTheme = 'theme-dark';.
CPHPython

3

หากคุณต้องการเพิ่มคลาสแบบไดนามิกให้กับองค์ประกอบโฮสต์ของคุณคุณสามารถรวมHostBindingกับทะเยอทะยานเป็น

@HostBinding('class') get class() {
    return aComponentVariable
}

การสาธิต Stackblitz ที่https://stackblitz.com/edit/angular-dynamic-hostbinding


0

นี่เป็นวิธีที่ฉันทำ (Angular 7):

ในองค์ประกอบให้เพิ่มอินพุต:

@Input() componentClass: string = '';

จากนั้นในเทมเพลต HTML ขององค์ประกอบจะเพิ่มสิ่งที่ชอบ:

<div [ngClass]="componentClass">...</div>

และในที่สุดในเทมเพลต HTML ที่คุณเป็นส่วนประกอบ:

<root componentClass="someclass someotherclass">...</root>

คำเตือน: ฉันค่อนข้างใหม่กับ Angular ดังนั้นฉันอาจเพิ่งโชคดีที่นี่!


2
necro เล็กน้อย แต่: นี่ไม่ได้เพิ่มคลาส CSS ลงในองค์ประกอบโฮสต์ - ซึ่งเป็นองค์ประกอบสำหรับ<root>แท็กไม่ใช่สิ่งที่คุณเพิ่มลงในแม่แบบขององค์ประกอบ
millimoose
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.