2015-10-06 77 views
7

我需要在ngFor循环中创建唯一锚定名称/组件,以便将其与ComponentResolver.resolveComponent结合使用。使用ComponentResolver和Angular2中的ngFor创建动态锚点名称/组件

<div> 
    <table> 
    <tr *ng-for="#vIndex of vArr"> 
     <td *ng-for="#hIndex of hArr"> 
     <div #uniqueanchorname{{vIndex}}_{{hIndex}}></div> 
     </td> 
    </tr> 
    </table> 
</div> 

生成的HTML看起来应该是这样的:

<div> 
    <table> 
    <tr> 
     <td> 
     <div #uniqueanchorname0_0></div> 
     </td> 
     <td> 
     <div #uniqueanchorname0_1></div> 
     </td> 
    </tr> 
    <tr> 
     <td> 
     <div #uniqueanchorname1_0></div> 
     </td> 
     <td> 
     <div #uniqueanchorname1_1></div> 
     </td> 
     <td> 
     <div #uniqueanchorname1_2></div> 
     </td> 
    </tr> 
    </table> 
</div> 

有了,我可以使用DynamicComponentLoader,如:

loader.loadIntoLocation(responseDependentComponent, elementRef, 'uniqueAnchorName1_2'); 

生成的HTML不会被取代,看起来会如:

<div> 
    <table> 
    <tr> 
     <td> 
     <div #uniqueanchorname{{vIndex}}_{{hIndex}}></div> 
     </td> 
     <td> 
     <div #uniqueanchorname{{vIndex}}_{{hIndex}}></div> 
     </td> 
    </tr> 
    <tr> 
     <td> 
     <div #uniqueanchorname{{vIndex}}_{{hIndex}}></div> 
     </td> 
     <td> 
     <div #uniqueanchorname{{vIndex}}_{{hIndex}}></div> 
     </td> 
     <td> 
     <div #uniqueanchorname{{vIndex}}_{{hIndex}}></div> 
     </td> 
    </tr> 
    </table> 
</div> 

如果创建唯一的锚名称是不可能的。是否有其他方式将组件加载到特定位置?

+0

可以尝试像'#{{” uniqueAnchorName'+ vIndex +' _'+ hIndex}}' –

+0

我真的不明白你的问题。那工作?它没有?我没有尝试过,但唯一能看到的是在变量名中使用大写字母。如果您编写'uniqueAnchorName',则在ng2编译之前,浏览器会将其小写为'uniqueanchorname'。 –

+0

@PankajParkar mustache({{xxx}})在属性中没有被替换,生成的html仍然看起来像#uniqueAnchorName {{vIndex}} _ {{hIndex}} –

回答

4

对不起,有误会。

import { 
    Directive, 
    Component, 
    View, 
    CORE_DIRECTIVES, 
    ElementRef, 
    DynamicComponentLoader, 
    Input, 
    QueryList, 
    ViewChildren 
} from 'angular2/angular2' 

@Component({ 
    selector: 'my-cmp' 
}) 
@View({ 
    template: 'my component' 
}) 
class MyCmp {} 

@Directive({ 
    selector: '[location]' 
}) 
class Location { 
    @Input() h: number; 
    @Input() v: number; 
    constructor(public elementRef: ElementRef) { 
    } 
} 

@Component({ 
    selector: 'my-table' 
}) 
@View({ 
    template: ` 
    <table border> 
    <tr *ng-for="#v of vArr"> 
     <td *ng-for="#h of hArr"> 
     <div location v="{{v}}" h="{{h}}">{{v}}-{{h}}</div> 
     </td> 
    </tr> 
    </table> 
    h:<input #hi value="1"><br> 
    v:<input #vi value="2"><br> 
    <button (click)="load(hi.value, vi.value)">load</button> 
    `, 
    directives: [CORE_DIRECTIVES, Location] 
}) 
class MyTable { 
    vArr = [1, 2, 3]; 
    hArr = [1, 2, 3]; 
    @ViewChildren(Location) locations: QueryList; 
    constructor(
    private loader: DynamicComponentLoader, 
    ) { 
    } 

    load(h, v) { 
    let elementRef = null; 
    for(let i = 0; i < this.locations._results.length; i++) { 
     if(this.locations._results[i].h == h && this.locations._results[i].v ==v) { 
     elementRef = this.locations._results[i].elementRef; 
     } 
    } 

    if(elementRef) { 
     this.loader.loadNextToLocation(MyCmp, elementRef); 
    } 
    } 
} 

@Component({ 
    selector: 'my-app' 
}) 
@View({ 
    template: `<my-table></my-table>`, 
    directives: [MyTable] 
}) 
export class App {} 

http://plnkr.co/edit/dqfPCW3MBa9hM23EW3cS?p=preview 是你需要什么?

+0

您的解决方案正在做我所需要的。创建大量指令仅仅是为了参考是有点不合适的。在我看来,如果我们可以创建字符串锚点作为引用,会更好。但是,你的解决方案正在工作,thx。 –

+0

我认为#xxx作为局部变量名是不可绑定的。唯一的方法是通过ElementRef,这就是使用指令的原因。 –

0

解决方案Angular2 rc.0

HTML:

<div style="display: block"> 
    <table> 
    <tr *ngFor="let v of arr; let i = index"> 
     <td *ngFor="let h of arr[i]; let j = index"> 
     <div location v="i" h="j"></div> 
     </td> 
    </tr> 
    </table> 
</div> 

Location指令:

@Directive({ 
    selector: '[location]' 
}) 
class Location { 
    @Input() h: number; 
    @Input() v: number; 

    constructor(public viewContainerRef: ViewContainerRef) { 
    } 
} 

组件

@Component({ 
    selector: 'example-cmp', 
    directives: [CORE_DIRECTIVES, Location] 
}) 
export class ExampleComponent implements AfterViewInit { 
    public arr: Array<Array<number>> = []; 
    public componentRef: ComponentRef<any>; 

    @ViewChildren(Location) private locations: QueryList<Location>; 

    constructor(private resolver: ComponentResolver) { 
    } 

    ngAfterViewInit() { 
    this.loadTag(0,0,SomeViewComponent); 
    } 

    loadTag(x:number, y:number, component) { 
    let viewContainerRef: ViewContainerRef = null; 
    let locs = this.locations.toArray(); 
    for (let i = 0; i < locs.length; i++) { 
     if (+locs[i].h === x && +locs[i].v === y) { 
     viewContainerRef = locs[i].viewContainerRef; 
     } 
    } 
    if (viewContainerRef != null) { 
     var injector = ReflectiveInjector.fromResolvedProviders(ReflectiveInjector.resolve([ 
     provide(NeededAttribute, { useValue: 42 })]), 
     this.componentRef.injector); 

     this.resolver.resolveComponent(component).then((factory: ComponentFactory<any>) => { 
     var compRef: ComponentRef<any> = viewContainerRef.createComponent(factory, -1, injector); 
     }); 
    } 
    } 
}