Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Angular 什么';s相当于WPF'的角度;什么是内容演示者?_Angular_Wpf_Angular Ui Router - Fatal编程技术网

Angular 什么';s相当于WPF'的角度;什么是内容演示者?

Angular 什么';s相当于WPF'的角度;什么是内容演示者?,angular,wpf,angular-ui-router,Angular,Wpf,Angular Ui Router,它和打字稿有着很大的关系 我来自WPF世界,现在我正在尝试一些角度的发展 在我的应用程序中有一个地方,我想建立一个选项卡控件来包含各种“打开”文档(角度组件)。也许我完全错了,但让我们考虑一下,有一个可注入的包含TabItems数组TabItem的属性之一是类的字符串、工厂或应用程序组件的类型名(取决于是否容易) @Injectable() 导出类OpenDocumentService{ openTabs:Array=[]; addTab(t:TabItem){openTabs.push(t);

它和打字稿有着很大的关系

我来自WPF世界,现在我正在尝试一些角度的发展

在我的应用程序中有一个地方,我想建立一个选项卡控件来包含各种“打开”文档(角度组件)。也许我完全错了,但让我们考虑一下,有一个可注入的包含
TabItem
s数组
TabItem
的属性之一是类的字符串、工厂或应用程序组件的类型名(取决于是否容易)

@Injectable()
导出类OpenDocumentService{
openTabs:Array=[];
addTab(t:TabItem){openTabs.push(t);}
}
在WPF wolrd中,我将创建一个内容演示器,并将其绑定到要显示的名称或对象

在这个棱角分明的世界里,我会做什么。备注:要显示的组件可能位于不同的模块中

当添加到服务中时,如何通过它显示任意组件?(替换ng contentpresenter)


对于来到这里的人:

简短回答-angular不批准此类shinenigans,因此您最好坚持推荐的方法,以构建类似ui的、正确的路由用法,适用于带有tree add@ngrx/store的项目浏览器等复杂情况

长答案-。 您必须首先建立基础设施:

  • 您将需要创建用于保存模型组件的服务。使用数据类型的构造函数作为键,使用组件构造函数类型作为值(DataTemplateService)
从'@angular/core'导入{Injectable,Type};
/**
*此服务允许在配置阶段动态绑定viewModel和组件,然后在渲染阶段解析它。
*动态组件注册和检测服务。要使用的组件取决于它们必须渲染的视图模型。
*/
@可注射()
导出类DataTemplateService{
私人字典:地图;
构造函数(){
this.dictionary=新映射();
}
/**
*确定组件类,在已注册组件中搜索。
*@param data ViewModel将用于组件,如果未找到,则返回未定义。
*/
公共确定(数据:任意):类型|未定义{
返回数据?this.dictionary.get(data.constructor):未定义;
}
/**
*注册特定视图模型对特定组件的绑定。
*@param viewModelType要注册的ViewModel的类型。
*@param componentType要注册的组件的类型。
*/
公共寄存器(viewModelType:Type,componentType:Type){
this.dictionary.set(viewModelType、componentType);
}
}
  • 您将需要使用ComponentFactoryResolver从构造函数创建组件并在其中设置viewModel的服务(ComponentRenderService)

从“@angular/core”导入{ComponentFactoryResolver,Injectable};
/**
*用于呈现动态组件的服务。
*/
@可注射()
导出类ComponentRenderService{
构造函数(专用componentFactoryResolver:componentFactoryResolver,
专用dataTemplateService:dataTemplateService){
}
公共呈现(数据:任意,容器组件:任意){
设置超时(()=>{
这是doRender(数据、集装箱组件);
}, 0);
}
/**
*根据必须使用的ViewModel渲染动态组件。
*@param必须用于渲染所有子组件的ViewModels的数据集合。
*@param containerComponent父组件,必须承载动态子组件。
*/
公共渲染(数据:数组,容器组件:任意){
设置超时(()=>{
如果(数据){
data.forEach(项=>{
本文件为doRender(项目,集装箱组件);
});
}
}, 0);
}
专用doRender(数据:任意,容器组件:任意){
如果(!数据){
调试('没有ComponentRenderService要呈现的数据(viewModel));
回来
}
const viewContainerRef=containerComponent.viewContainerRef;
const dataItem=数据;
const component=this.dataTemplateService.determinate(dataItem);
if(组件){
const componentFactory=this.componentFactoryResolver.resolveComponentFactory(component);
const componentRef=viewContainerRef.createComponent(componentFactory);
(componentRef.instance).data=数据;
}否则{
console.warn('未能找到类型为'+dataItem.constructor'的viewmodel的组件);
}
}
}
  • 您将需要作为动态组件和将调用服务的组件的标记的指令
import{Directive,ViewContainerRef,Component,Input,OnChanges,SimpleChanges,ViewChild}来自“@angular/core”;
/**
*指令,该指令支持动态子组件的构造。
*/
@指示({
选择器:“[动态组件主机]”,
})
导出类DynamicComponentHostDirective{
构造函数(公共viewContainerRef:viewContainerRef){}
}
/**
*表示用于呈现动态子组件的扩展点的组件。
*/
@组成部分({
选择器:“外部点单主机”,
模板:`
`
})
导出类ExtPointSingleHostComponent实现OnChanges{
@ViewChild(DynamicComponentHostDirective)公共hostDirective:DynamicComponentHostDirective;
@Input()公共视图模型:任意;
构造函数(私有componentRenderer:ComponentRenderService){}
/**
*加载嵌套组件。
*/
公共加载组件(){
const viewModel=this.viewModel;
this.componentRenderer.render(viewModel,this.hostDirective);
}
平民的
export class TabItem {
    public title : string;
    public disabled : boolean;
    public active : boolean;
    public factory: any; // or class name or object
}
@Injectable()
export class OpenDocumentService {
    openTabs: Array<TabItem> = [];
    addTab(t:TabItem){ openTabs.push(t); }
}
     <tabset>
        <tab *ngFor="let tabz of tabservice.openTabs"
[heading]="tabz.titel">
           <ng-contentpresenter use={{tabz?.factory}}/>
        </tab>
    </tabset>

import { Injectable, Type } from '@angular/core';

/**
 * This service allows dynamically bind viewModel and component in configuration stage and then resolve it in render stage.
 * Service for dynamic component registration and detection. Component to be used are determined based on view model they have to render.
 */
@Injectable()
export class DataTemplateService {

    private dictionary: Map<Type<any>, Type<any>>;

    constructor() {
        this.dictionary = new Map<Type<any>, Type<any>>();

    }
    /**
     * Determines component class, searching in registered components.
     * @param data ViewModel that will be used for component, returns undefined if not found.
     */
    public determine(data: any): Type<any> | undefined {
        return data ? this.dictionary.get(data.constructor) : undefined;
    }

    /**
     * Registers binding of certain view model towards certain component.
     * @param viewModelType Type of ViewModel to be registered.
     * @param componentType Type of Component to be registered.
     */
    public register(viewModelType: Type<any>, componentType: Type<any>) {
        this.dictionary.set(viewModelType, componentType);
    }
}

import { ComponentFactoryResolver, Injectable } from '@angular/core';

/**
 * Service fro rendering dynamic components.
 */
@Injectable()
export class ComponentRendererService {

    constructor(private componentFactoryResolver: ComponentFactoryResolver,
        private dataTemplateService: DataTemplateService) {
    }
    public render(data: any, containerComponent: any) {
        setTimeout(() => {
            this.doRender(data, containerComponent);
        }, 0);
    }

    /**
     * Renders dynamic components based on ViewModel they have to use.
     * @param data Collection of ViewModels that have to be used to render all child components.
     * @param containerComponent Parent component, that have to host dynamic child components.
     */
    public renderAll(data: Array<any>, containerComponent: any) {
        setTimeout(() => {
            if (data) {
                data.forEach(item => {
                    this.doRender(item, containerComponent);
                });
            }
        }, 0);
    }

    private doRender(data: any, containerComponent: any) {
        if (!data) {
            console.debug('No data (viewModel) for ComponentRendererService to render.');
            return;
        }
        const viewContainerRef = containerComponent.viewContainerRef;
        const dataItem = data;
        const component = this.dataTemplateService.determine(dataItem);
        if (component) {
            const componentFactory = this.componentFactoryResolver.resolveComponentFactory(component);
            const componentRef = viewContainerRef.createComponent(componentFactory);
            (<any>componentRef.instance).data = data;
        } else {
            console.warn('Failed to find component for viewmodel of type' + dataItem.constructor);
        }
    }
}
import { Directive, ViewContainerRef, Component, Input, OnChanges, SimpleChanges, ViewChild } from '@angular/core';

/**
 *  Directive that enables construction of dynamic child components.
 */
@Directive({
    selector: '[dynamic-component-host]',
})
export class DynamicComponentHostDirective {
    constructor(public viewContainerRef: ViewContainerRef) { }
}

/**
 * Component that represents extention point for rendering dynamic child components.
 */
@Component({
    selector: 'ext-point-single-host',
    template: `
              <div class="ext-point-host">
                <ng-template dynamic-component-host></ng-template>
              </div>
            `
})
export class ExtPointSingleHostComponent implements OnChanges {
    @ViewChild(DynamicComponentHostDirective) public hostDirective: DynamicComponentHostDirective;
    @Input() public viewModel: any;

    constructor(private componentRenderer: ComponentRendererService) { }

    /**
     * Loads nested components.
     */
    public loadComponent() {
        const viewModel = this.viewModel;
        this.componentRenderer.render(viewModel, this.hostDirective);
    }

    public ngOnChanges(changes: SimpleChanges) {
        this.hostDirective.viewContainerRef.clear();
        this.loadComponent();
    }
}


@Component({
    template: '<button type="button" class="">Custom style 2</button>'
})
export class CustomButton1Component  {
    public data: CustomButton1ViewModel;
}

export class CustomButton1ViewModel {

}
@Component({
    template: '<button type="button" class="">Custom style 2</button>'
})
export class CustomButton2Component  {
    public data: CustomButton2ViewModel;
}

export class CustomButton2ViewModel {

}

@NgModule({
    ...
    providers: [..., DataTemplateService]
})
export class DemoModule {
    constructor(dataTemplateService: DataTemplateService) {
        dataTemplateService.register(CustomButton2ViewModel, CustomButton2Component);
        dataTemplateService.register(CustomButton1ViewModel, CustomButton1Component);
    }
}