Làm cách nào để thêm lớp lớp TIN vào máy chủ lưu trữ?


187

Tôi không biết cách thêm vào thành phần của mình <component></component>một thuộc tính lớp động nhưng bên trong mẫu html (component.html).

Giải pháp duy nhất tôi tìm thấy là sửa đổi mục thông qua phần tử gốc "ElementRef". Giải pháp đó có vẻ hơi phức tạp để làm một cái gì đó rất đơn giản.

Một vấn đề khác là CSS phải được xác định bên ngoài phạm vi thành phần, phá vỡ đóng gói thành phần.

Có một giải pháp đơn giản hơn? Một cái gì đó giống như <root [class]="..."> .... </ root>bên trong mẫu.

Câu trả lời:


293
@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(); 
  }
}

Ví dụ Plunker

Bằng cách này, bạn không cần thêm CSS bên ngoài thành phần. CSS như

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

hoạt động từ bên trong thành phần và bộ chọn chỉ được áp dụng nếu lớp someClassđược đặt trên thành phần máy chủ.


Tôi đã phải làm someField = truetrong ngOnInit()-method thay vì ngAfterViewInit(). Tôi không thể làm cho nó hoạt động khác được.
John

Thực hiện một ngã ba ở đây cho thấy phần thực tế :hostlàm việc. Tôi có thể tìm hiểu thêm về tham số máy chủ trong trình trang trí @Component () (cú pháp không rõ ràng đối với tôi và tài liệu @Component không giải thích nhiều ) hoặc tìm hiểu thêm về HostBinding ưa thích của bạn (nó chỉ được liệt kê dưới dạng Giao diện trên Trang web Angular2?)
The Red Pea

Tôi không biết các tài liệu tốt hơn, nhưng đó chỉ là một cách khác để làm những gì bạn có thể làm với@Input() @Output() @HostBinding() @HostListener() @ViewChild(ren)() @ContentChild(ren)()
Günter Zöchbauer

1
sử dụng một getter với một tên khác cho ràng buộc máy chủ trả về giá trị đảo ngược@HostBinding('class.xxx') get xxxclass(){ return !this.someField;}
Günter Zöchbauer

1
@YochaiAkoka không chắc chắn những gì bạn đề cập đến. Tôi không nhận thức được quy tắc này. Ít thường là nhiều hơn, vì vậy nếu bạn có thể tránh thêm các yếu tố bổ sung, thì bạn nên tránh nó.
Günter Zöchbauer

184

Câu trả lời của Günter rất hay (câu hỏi là yêu cầu thuộc tính lớp động ) nhưng tôi nghĩ tôi sẽ thêm chỉ để hoàn thiện ...

Nếu bạn đang tìm kiếm một cách nhanh chóng và rõ ràng để thêm một hoặc nhiều lớp tĩnh vào thành phần máy chủ của thành phần của bạn (nghĩa là cho mục đích tạo kiểu chủ đề), bạn có thể thực hiện:

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

Và nếu bạn sử dụng một lớp trên thẻ mục nhập, Angular sẽ hợp nhất các lớp, nghĩa là,

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

1
Yêu cái này cho đơn giản. Tuy nhiên, trong trường hợp của tôi là yếu tố chủ được đóng gói với một thuộc tính khác nhau, chúng ta hãy gọi nó ngcontent_hosthơn bất kỳ các thuộc tính trên các yếu tố trong tôi Mẫu , let's call those ngcontent_template , so if I put a style in the styleUrls` của thành phần của tôi, họ sẽ không ảnh hưởng đến các yếu tố chủ vì họ sẽ không ảnh hưởng ngcontent_host, họ Chỉ có thể ảnh hưởng đến các yếu tố mẫu; họ chỉ có thể ảnh hưởng ngcontent_template. Tôi có nhầm không? Bất kỳ đề nghị về điều này? Tôi đoán là tôi luôn có thể quay đầuViewEncapsulation.None
The Red Pea

11
Một cách khác là chỉ cần bỏ qua các biến , @HostBinding('class.someClass') true;. Bạn thậm chí có thể làm điều này từ bất kỳ lớp nào thành phần của bạn mở rộng.
adamdport

3
Để thêm nhiều lớp, bạn có thể làm máy chủ: {'[class]': '"class1 class2"'}
jbojcic

4
Nếu bạn sử dụng máy chủ: {}biến thể, bạn có thể muốn thiết lập use-host-property-decoratorthiết lập để falsetslint.json. Nếu không, bạn sẽ nhận được cảnh báo IDE. @adamdport Phương pháp đó không hoạt động (nữa). Sử dụng Angular 5.2.2 trong ứng dụng của chúng tôi.
Ruud Voost

1
Có phải chỉ có tôi, hay cách cũ có vẻ tốt hơn cách mới? Tôi chắc rằng họ có lý do chính đáng để di cư, nhưng meh ...
đè bẹp

11

Bạn chỉ có thể thêm @HostBinding('class') class = 'someClass';vào bên trong lớp @Component của mình .

Thí dụ:

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

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

  constructor() {}      

  ngOnInit() {}
}

1
Các className chỉ thị cũng có thể được sử dụng và nó là tốt hơn để tránh sử dụng classnhư một tên biến (kể từ khi bạn có thể tham khảo nó và thay đổi nó sau này). Ví dụ : @HostBinding('className') myTheme = 'theme-dark';.
CPHPython


0

Đây là cách tôi đã làm (Angular 7):

Trong thành phần, thêm một đầu vào:

@Input() componentClass: string = '';

Sau đó, trong mẫu HTML của thành phần thêm một cái gì đó như:

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

Và cuối cùng trong mẫu HTML nơi bạn thể hiện thành phần:

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

Tuyên bố miễn trừ trách nhiệm: Tôi khá mới đối với Angular, vì vậy tôi có thể gặp may mắn ở đây!


2
Hơi khó hiểu nhưng: điều này không thêm lớp CSS vào thành phần máy chủ - đây là thành phần cho <root>thẻ, không phải bất cứ thứ gì bạn thêm vào mẫu của thành phần.
millimoose
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.