2017-12-08 3 views
1

개발자가 최소한의 노력으로 일관성을 유지하지만 레이아웃과 내용을 완전히 제어 할 수있는 특정 기본 유형을 지정할 수있는 엔터프라이즈 웹 사이트의 기본 프레임 워크 컨트롤을 개발하려고합니다. . 각 컨트롤은 스타일을 정의하고 접근성 요구 사항을 유지해야 할 책임이 있습니다. Windows 데스크톱 응용 프로그램에서 유추 할 수 있습니다. GroupBox 또는 Panel을 양식으로 드래그하고 양식에서 속성을 설정할 수는 있지만 배치 할 콘텐트에 대해 알 필요가없는 패널없이 해당 패널에 컨트롤 및 사용자 지정 콘텐트를 추가 할 수 있습니다.각도 2+ 프레임 워크 개발 구성 요소

예를 들어 지금까지는 대시 보드 구성 요소가 있었고 화면 상단에 몇 개의 타일을 배치하고 두장의 패널을 배치하려고합니다. 한 패널에는 표가 표시되고 다른 패널에는 텍스트 단락이 있고 다른 표에는 세로로 쌓인 일부 타일이 표시됩니다. 프레임 워크 컨트롤을 지정해야하며 배치 할 위치는 지정해야하지만 리치 컨텐츠 또는 다른 구성된 구성 요소를 내 패널 구성 요소의 panel-body div에 렌더링되도록 전달하는 방법은 확실하지 않습니다.

이이 알려진 문자열 값으로 쉽게 결합 될 것이다 속성을 받아들이는 일부 패널 뒤에 타일 정의 대시 보드 템플릿 :

<h1 class="page-header">{{title}}</h1> 
<div class="row"> 
    <div class="col-md-3 col-sm-6"> 
     <app-infra-tile headerText="Total Visitors" [mainText]="'0' | number" footerText="Some Text" icon="fa-users" colour="bg-blue"></app-infra-tile> 
    </div> 

</div> 
<div class="row"> 
    <div class="col-md-3 col-sm-6"> 
    <app-infra-panel heading="Table Panel"></app-infra-panel> 
    </div> 
    <div class="col-md-3 col-sm-6"> 
    <app-infra-panel heading="Graph Panel"></app-infra-panel> 
    </div> 
    <div class="col-md-3 col-sm-6"> 
    <app-infra-panel heading="Some Panel"></app-infra-panel> 
    </div> 
</div> 

타일의 구성 요소 및 템플릿

import { Component, OnInit, Input } from '@angular/core'; 

@Component({ 
    selector: 'app-infra-tile', 
    templateUrl: './tile.component.html', 
    styleUrls: ['./tile.component.css'] 
}) 
export class TileComponent implements OnInit { 
    @Input() icon: string; 
    @Input() headerText: string; 
    @Input() mainText: string; 
    @Input() footerText: string; 
    @Input() colour = 'bg-blue'; 

    constructor() { } 

    ngOnInit() { 
    } 

} 
<div class="widget widget-stats {{colour}}"> 
    <div *ngIf="icon" class="stats-icon"><i class="fa {{icon}}"></i></div> 
    <div class="stats-info"> 
     <div class="stats-title | uppercase">{{headerText}}</div> 
     <div class="stats-number">{{mainText}}</div> 
     <div class="stats-desc">{{footerText}}</div> 
    </div> 
</div> 

패널 구성 요소 및 템플릿

,
import { Component, OnInit, Input } from '@angular/core'; 

@Component({ 
    selector: 'app-infra-panel', 
    templateUrl: './panel.component.html', 
    styleUrls: ['./panel.component.css'] 
}) 
export class PanelComponent implements OnInit { 
    @Input() htmlId: string; 
    @Input() heading: string; 

    constructor() { } 

    ngOnInit() { 
    } 

} 
<div class="panel panel-inverse" id="{{htmlId}}"> 
    <div class="panel-heading"> 
    <div class="panel-heading-btn"> 
     <a href="javascript:;" class="btn btn-xs btn-icon btn-circle btn-default" data-click="panel-expand"><i class="fa fa-expand"></i></a> 
     <a href="javascript:;" class="btn btn-xs btn-icon btn-circle btn-success" data-click="panel-reload"><i class="fa fa-repeat"></i></a> 
     <a href="javascript:;" class="btn btn-xs btn-icon btn-circle btn-warning" data-click="panel-collapse"><i class="fa fa-minus"></i></a> 
     <a href="javascript:;" class="btn btn-xs btn-icon btn-circle btn-danger" data-click="panel-remove"><i class="fa fa-times"></i></a> 
    </div> 
    <h4 class="panel-title">{{heading}}</h4> 
    </div> 
    <div class="panel-body"> 
    ----- The internal content managed by the dashboard should be rendered here ---- 
    </div> 
</div> 

나는 공장 방법과 결과에 유형 any의 로컬 변수를 설정 패널의의 onInit에 포함 된 서비스 전달에 대해 생각했습니다하지만 대시 보드는 단지 출력 원시 HTML로 메소드를 구현해야 또는 수 다른 구성 요소 인스턴스를 통해 전달합니다 ... ??

모든 조언을 크게 듣습니다. 나는 정말 간단한 것을 놓친 것 같습니다.

답변

0

생각해 보면 Transclusion (콘텐츠 투영 NG2 +)는 갈 방법입니다

1

일주일에 간신히 볼 수 있지만 대답은 colleague입니다. 이 접근법은 지침을 사용하고 있습니다.

<div class="row"> 
    <div class="col-md-4 col-sm-6"> 
    <app-infra-panel heading="Some Panel" [componentName]="somePanelComponent"></app-infra-panel> 
    </div> 

    <div class="col-md-8 col-sm-6"> 
    <app-infra-panel heading="Other Panel" [componentName]="otherPanelComponent"></app-infra-panel> 
    </div> 
</div> 

heading는 상기 PanelComponent의 특성뿐만 아니라 somePanelComponent입니다 : 그래서 내가 계속 내 DashboardComponent의 템플릿에서이 작업을 수행 패널의 HTML을 작성하지 않고도에 패널의 몇 가지를 배치했다 대시 보드 구성 요소가 주어진 및 otherPanelComponent. Sub Component을 채우려는 모든 패널에 대해 구성 요소 이름에 해당하는 문자열을 만듭니다.

@Component({ 
    selector: 'app-dashboard', 
    templateUrl: './dashboard.component.html', 
    styleUrls: ['./dashboard.component.css'] 
}) 
export class ProviderDashboardComponent implements OnInit { 
    title = 'The Dashboard'; 

    // Panel Content Component Names 
    somePanelComponent = 'SomePanelComponent'; 
    otherPanelComponent = 'OtherPanelComponent'; 


    constructor() { } 

    ngOnInit() {  

    } 

} 

PanelComponent 배치되고 :

<div class="panel panel-inverse"> 
    <div class="panel-heading"> 
    <div class="panel-heading-btn"> 
     <a href="javascript:;" class="btn btn-xs btn-icon btn-circle btn-default" data-click="panel-expand"><i class="fa fa-expand"></i></a> 
     <a href="javascript:;" class="btn btn-xs btn-icon btn-circle btn-success" data-click="panel-reload"><i class="fa fa-repeat"></i></a> 
     <a href="javascript:;" class="btn btn-xs btn-icon btn-circle btn-warning" data-click="panel-collapse"><i class="fa fa-minus"></i></a> 
     <a href="javascript:;" class="btn btn-xs btn-icon btn-circle btn-danger" data-click="panel-remove"><i class="fa fa-times"></i></a> 
    </div> 
    <h4 class="panel-title">{{heading}}</h4> 
    </div> 
    <div class="panel-body"> 
    <div control-factory component="{{componentName}}"></div> 
    </div> 
</div> 

import { Component, Input, ComponentFactoryResolver, ViewChild } from '@angular/core'; 

@Component({ 
    selector: 'app-infra-panel', 
    templateUrl: './panel.component.html', 
    styleUrls: ['./panel.component.css'] 
}) 
export class PanelComponent { 

    @Input() heading: string; 
    @Input() componentName: string; 

    constructor() { } 

} 

control-factory 지침 :

import { Directive, 
    Component, 
    ComponentFactory, 
    OnChanges, 
    Input, 
    ViewContainerRef, 
    Compiler, 
    ComponentFactoryResolver, 
    OnDestroy 
} from '@angular/core'; 

import { CommonModule } from '@angular/common'; 
import { AppComponent } from 'app/app.component'; 

@Directive({ 
    selector: '[control-factory]' 
}) 
export class ControlFactoryDirective implements OnChanges, OnDestroy { 

    @Input() component: string; 
    componentRef: any; 
    init = false; 
    factoryClass: any; 

    constructor(private vcRef: ViewContainerRef, private resolver: ComponentFactoryResolver) { } 

    ngOnChanges(): void { 

    if (!this.component || this.init) return; 

    var factories = Array.from(this.resolver['_factories'].keys()); 
    console.log(this.component); 

    this.factoryClass = factories.find((x: any) => x.name === this.component); 
    const factory = this.resolver.resolveComponentFactory<any>(this.factoryClass); 
    const compRef = this.vcRef.createComponent(factory); 


    if (this.componentRef) { 
     this.componentRef.destroy(); 
    } 

    this.componentRef = compRef; 
    this.init = true; 
    } 

    public ngOnDestroy() { 
    if (this.componentRef) { 
     this.componentRef.destroy(); 
     this.componentRef = null; 
    } 
    } 
} 

각 구성 요소는 제 경우, 컴포넌트는 생성 될 필요가있는 패널에 배치되는 SomePanelComponentOtherPanelComponent.이것들은 App.module 내의 declarationsentryComponents 배열에 추가 될 필요가 있습니다. 나는 상위 레벨에 모든 것을 두지 않고 내 프로젝트에서 더 깊은 모듈에 배치하는 방법을 찾으려고 노력 중이다. 지금까지 내가 어디에 넣든 상관없이 app.module에없는 경우 entryComponents 배열에 지정되지 않은 오류가 발생합니다.

어쨌든, 나는 이것이 누구에게나 가치가 있기를 바랍니다.