我正在使用vmware/clarity
design system,并尝试使用动态组件加载outlined in angular.io来实施动态应用级警报。我以前一直遵循这种模式,但我似乎无法使用来自Clarity的警报。
import { AfterViewInit, Component, ComponentFactoryResolver, OnDestroy, ViewChild } from '@angular/core';
import { ClrAlert } from '@clr/angular';
import { AlertsHostDirective } from './directives/alerts-host.directive';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements AfterViewInit, OnDestroy {
@ViewChild(AlertsHostDirective) alerts: AlertsHostDirective;
private interval: NodeJS.Timer;
constructor(private _componentFactoryResolver: ComponentFactoryResolver) { }
ngAfterViewInit(): void {
this.alert();
this.getAlerts();
}
ngOnDestroy(): void {
clearInterval(this.interval);
}
private alert() {
const componentFactory = this._componentFactoryResolver.resolveComponentFactory(ClrAlert);
const viewContainerRef = this.alerts.viewContainerRef;
const componentRef = viewContainerRef.createComponent(componentFactory);
componentRef.instance.isAppLevel = true;
componentRef.changeDetectorRef.detectChanges();
}
private getAlerts() {
this.interval = setInterval(() => {
this.alert();
}, 5000);
}
}
<clr-main-container>
<clr-alerts>
<ng-template appAlertsHost></ng-template>
<clr-alert clrAlertType="info"
[clrAlertAppLevel]="true">
<div class="alert-item">
<span class="alert-text">This is the first app level alert. </span>
<div class="alert-actions">
<button class="btn alert-action">Fix</button>
</div>
</div>
</clr-alert>
<clr-alert clrAlertType="danger"
[clrAlertAppLevel]="true">
<div class="alert-item">
<span class="alert-text">This is a second app level alert.</span>
<div class="alert-actions">
<button class="btn alert-action">Fix</button>
</div>
</div>
</clr-alert>
</clr-alerts>
...
import { Directive, ViewContainerRef } from '@angular/core';
@Directive({
selector: '[appAlertsHost]'
})
export class AlertsHostDirective {
constructor(public viewContainerRef: ViewContainerRef) { }
}
如果我将指令放在ClrAlerts
组件上,它的工作方式应该是在DOM中ClrAlerts
之后附加的应用程序级警报。但是我希望我的所有应用级警报都会在它们进入时显示在该组件中。反过来,我也希望看到更新的寻呼机组件。
这可能吗?
答案 0 :(得分:3)
在评论中讨论之后,我认为如果我只是简单地使用*ngFor
发布我的意思就会更容易:https://stackblitz.com/edit/clarity-light-theme-v11-vs8aig?file=app%2Fnotifications.provider.ts
使用组件工厂来创建始终相同的组件是完全矫枉过正的,这是一种可怕的做法。您链接的Angular文档部分特别说明了它们的用例是动态地实例化一个新组件,当他们甚至不知道组件的实际类别时。我希望上面的示例可以帮助您了解如何在项目中组织这些警报。
答案 1 :(得分:0)
*ngFor
进行渲染。
但是,ClrAlerts
父组件在某些情况下正确处理这些更改似乎存在问题。例如,如果您从阵列中的警报开始,使用用户交互关闭它们,然后添加更多,则不正确设置当前警报。因此,这似乎是我能提出的最简洁的解决方案:
<clr-main-container>
<clr-alerts>
<clr-alert *ngFor="let alert of alerts"
[clrAlertType]="alert.type"
[clrAlertAppLevel]="true">
<div class="alert-item">
<span class="alert-text">{{alert.text}}</span>
<div class="alert-actions"
*ngIf="alert.action">
<button class="btn alert-action">{{alert.action}}</button>
</div>
</div>
</clr-alert>
</clr-alerts>
...
import 'rxjs/add/Observable/of';
import { AfterViewInit, Component, OnDestroy, ViewChild } from '@angular/core';
import { ClrAlerts } from '@clr/angular';
export interface AppLevelAlert {
type: 'info' | 'warning' | 'success' | 'danger';
text: string;
action: string;
}
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements AfterViewInit, OnDestroy {
@ViewChild(ClrAlerts) alertsContainer: ClrAlerts;
private interval: NodeJS.Timer;
alerts: AppLevelAlert[] = [];
ngAfterViewInit(): void {
this.alert();
this.getAlerts();
}
ngOnDestroy(): void {
clearInterval(this.interval);
}
private alert() {
this.alerts.push({
type: 'success',
text: 'This was added later!',
action: 'Do nothing'
});
if (!this.alertsContainer.currentAlert) {
this.alertsContainer.multiAlertService.current = 0;
}
}
private getAlerts() {
this.interval = setInterval(() => {
this.alert();
}, 5000);
}
}