【发布时间】:2017-05-20 01:46:38
【问题描述】:
我有以下代码:
search.component.ts
import { CoreComponent } from './../../core/components/core.component';
import { SearchDropDownComponent } from './search.dropdown.component';
import { Component,Input,EventEmitter, Output, ViewChild} from "@angular/core";
@Component({
selector:'search',
templateUrl:'app/templates/search.component.html',
styleUrls:['app/templates/css/search.component.css']
})
export class SearchComponent
{
@Input() core : CoreComponent;
@Output() onSearch : EventEmitter<any> = new EventEmitter();
@ViewChild(SearchDropDownComponent) dropdown: SearchDropDownComponent;
private searchText:String="";
search(event:any) : void
{
if (+event.keyCode==13 || event.type=="click")
{
this.onSearch.emit(event);
return;
}
}
}
search.component.html
<div class="input-group" id="search">
<input class="form-control kblue-background-pale" [(ngModel)]="searchText" (keypress)=search($event) placeholder="Search" list="search-dropdown" type="text">
<search-dropdown [core]="this.core" [typed]="this.searchText"></search-dropdown>
<div class="input-group-btn">
<div class="btn-group" role="group">
<button (click)="search($event)" type="button" class="btn kblue-background-pale">
<span class="glyphicon glyphicon-search kblue" aria-hidden="true">
</span>
</button>
</div>
</div>
</div>
search.dropdown.component.ts
import { CoreBase } from './../../core/components/core.base';
import { ComponentFactoryService } from './../../services/services/component.fac';
import { SearchResultComponent } from './search.result.component';
import { CoreComponent } from './../../core/components/core.component';
import { Component,
Input,AfterViewInit ,
ContentChildren,ContentChild,
Output,Inject,forwardRef,OnChanges,ElementRef,ViewChild,ViewContainerRef,ViewChildren,QueryList } from "@angular/core";
@Component(
{
selector:'search-dropdown',
templateUrl:'app/templates/search.dropdown.component.html',
styleUrls:['app/templates/css/search.dropdown.component.css']
}
)
export class SearchDropDownComponent implements AfterViewInit , OnChanges
{
@Input() core : CoreComponent;
@ViewChild('searchresult', {read: ViewContainerRef}) p: ViewContainerRef;
@ViewChildren(SearchResultComponent) t: QueryList<any>;
@ViewChild('parent', {read: ViewContainerRef}) children: ViewContainerRef;
private MLENGTH=2;
private RLENGTH=0;
private searchLength=0;
constructor(private factory:ComponentFactoryService) {
}
@Input()
set typed(typed:string)
{
if (typed.length>this.searchLength)
{
if (typed.length>this.MLENGTH)
{
this.core.webservice(this.result,"communities",{search:typed});
}
this.searchLength=typed.length;
}
else
{
if (typed.length==this.RLENGTH)
{
this.p.clear();
this.searchLength=0;
}
}
console.log(this.p.length);
console.log(this.children);
// for(var index = 0; index < this.p.length; index++)
//{
// console.log(this.t);
// }
}
ngAfterViewInit() {
}
ngOnChanges()
{
console.log(this.p.element.nativeElement.childNodes);
console.log(this.children);
}
public result=(data:any)=>
{
data.forEach((item:any)=>
{
this.factory.getComponent(this.p,SearchResultComponent,item);
});
}
}
search.dropdown.component.html:
<datalist id="search-dropdown" #searchresult></datalist>
search.result.component.ts:
import { CoreBase } from './../../core/components/core.base';
import { Component,OnInit,TemplateRef} from "@angular/core";
@Component({
selector:'search-result',
templateUrl:'app/templates/search.result.component.html',
styleUrls:['app/templates/css/search.result.component.css']
})
export class SearchResultComponent extends CoreBase implements OnInit
{
private suggestions:String;
constructor()
{
super();
}
ngOnInit()
{
this.suggestions=this.parameters["search"];
}
}
search.result.component.html:
<option>{{suggestions}}</option>
component.fac.ts(组件工厂服务):
import { CoreBase } from './../../core/components/core.base';
import {
Injectable,
ReflectiveInjector,
ViewContainerRef,
ComponentFactoryResolver
} from '@angular/core';
@Injectable()
export class ComponentFactoryService
{
constructor(private componentFactoryResolver: ComponentFactoryResolver)
{
}
public getComponent(refDOM:ViewContainerRef, component:any,parameters:any)
{
let factory = this.componentFactoryResolver.resolveComponentFactory(component);
let injector = ReflectiveInjector.fromResolvedProviders([], refDOM.parentInjector);
let comp = factory.create(injector);
(<CoreBase>comp.instance).parameters=parameters;
comp.changeDetectorRef.detectChanges();
refDOM.insert(comp.hostView,0);
return comp.instance;
}
}
我想在 Angular 2 中开发一个搜索下拉建议小部件,当用户在输入框占位符中键入 3 个字符时,会向后端发出请求并返回 json 响应。每个搜索建议元素都在 search.dropdown.component 中动态加载,特别是在 search.dropdown.component.html 的 #searchresult 中。
组件 search.result.component 是动态注入的,但会在外部渲染:
我想在数据列表中注入动态组件,然后能够使用 ViewChildren api 访问属性建议 search.result.component。
问题是搜索结果组件呈现在数据列表之外。如果我在 html 中放置一个 div 或一个模板标签来渲染内部的动态元素,则视图会正确渲染,但 ViewChildren api 不检索动态注入的组件。
如何使用 div 标签内呈现的 ViewChildren api 组件进行访问?
谢谢
【问题讨论】:
标签: angular dynamic components