【问题标题】:Angular2 - Pass parameters to a dynamically generated component?Angular2 - 将参数传递给动态生成的组件?
【发布时间】:2017-08-26 21:45:01
【问题描述】:

我有一个简单的演示应用程序,我正在模拟手动从数据库插入/获取数据并注入新组件 - 根据输入的数量。

Plunker

所以如果我点击“手动”按钮两次:

如果我在文本中设置“3”并单击“从 db 获取” - 我会得到预期的延迟(模拟 db)然后:

这一切都按预期工作。

“父”组件是:

//src/MainPage.ts
@Component({
  selector: 'my-app',
  template: `
    <button (click)="putInMyHtml()">Insert component manually</button>
    <p> # Items to fetch  : <input type="text" style='width:40px'  [(ngModel)]="dbNumItems" name="dbNumItems"/> <input type='button' value='fetch from db' (click)='fetchItems($event)'/></p>
    <div #myDiv>
       <template #target></template> 
    </div>
  `
})
export class MainPage {
  @ViewChild('target', { read: ViewContainerRef }) target: ViewContainerRef;
  dbNumItems: string;
  constructor(private cfr: ComponentFactoryResolver) {}

  fetchItems(){ 
        var p= new Promise((resolve, reject) => { //simulate db
        setTimeout(()=>resolve(this.dbNumItems),2000)
    });

  p.then(v=>{

    for (let i =0;i<v;i++)
    {
         this.putInMyHtml() ;// inject "v" times
    }
  })

}

  putInMyHtml() {
   // this.target.clear();
   let compFactory = this.cfr.resolveComponentFactory(TestPage);
    this.target.createComponent(compFactory);
  }
}

这是注入组件:

//src/TestPage.ts
@Component({
  selector: 'test-component',
  template: '<b>Content  : Name={{user.Name}} Age={{user.Age}}</b><br/>',
})
export class TestPage {
    @Input
     User:Person;

}

那么问题出在哪里?

如你所见,在注入的组件中我有:

@Input
User:Person;

这意味着我希望parent 组件将Person 对象传递给每次注入。

换句话说:

问题

查看“db 后阶段”,如何将自定义的person 传递给每次注入?

  p.then(v=>{

    for (let i =0;i<v;i++)
    {
         let p = new Person();
         p.Name = "name"+i;
         p.Age = i;

         this.putInMyHtml() ; //how to I pass `p` ???

    }
  })

}

预期输出:

注意 我不想使用ngFor,因为我不需要在后端保存一个数组。这是一个定期注入新文章的应用程序。我很高兴知道是否有更好的方法。

【问题讨论】:

    标签: javascript angular


    【解决方案1】:

    使用 *ngFor 并遍历 Person 数组,这样您就可以使用 @Input。你可能想要像

    <ul>
      <li *ngFor="let person of people">
        <test-component [User]=person></test-component>
      </li>
    </ul>
    

    将人员:Person[] 添加到您的主要组件以及获取项目时

    p.then(v=>{
    
    for (let i =0;i<v;i++)
    {
       let p = new Person();
       p.Name = "name"+i;
       p.Age = i;  
       people.push(p)
    }
    })
    

    【讨论】:

    • 但是如果注入的控件会有一个 IMG ,我不希望每次有新文章到达时都运行“已经存在”的 SRC。例如说我已经有 array[5] 和文章我又推了 2 ,我不希望这 5 篇文章再次呈现
    • 创建一个可以添加新文章的服务。在主组件中订阅该服务,当有新文章出现时,只需将其附加到数组中。
    • 如果我添加一个已经在数组中的旧文章,是否会重新渲染?
    • 我几乎可以肯定整个列表不会被重新渲染(如果它发生得太快,我无法注意到)。但无论哪种方式,因为它已经在一个数组中,您不必重新向服务器发出请求。
    • 将新值推送到数组时不会重新渲染。检查这个:stackoverflow.com/a/42244702/5706293
    【解决方案2】:

    您可以使用组件引用的instance 属性来做到这一点,如下所示:

    putInMyHtml(p) {
       // this.target.clear();
    
        let compFactory = this.cfr.resolveComponentFactory(TestPage);
    
        let ref = this.target.createComponent(compFactory);
        ref.instance.user = p;
    }
    

    -修复@Input()绑定,语法错误。

    -为模板添加了一个安全导航运算符 (?) 以对异步输入进行空值检查。

    固定插件:https://plnkr.co/edit/WgWFZQLxt9RFoZLR46HH?p=preview

    【讨论】:

    • 正是我想要的。谢谢你。顺便说一句,当我说我不想要 ngFor 因为我不需要/不想在后端保存一个数组(内存等)时,顺便说一句,我的思维方式是正确的——我只想注入新文章。这是正确的方法吗?
    • @Royi 好吧,“正确”的方法当然取决于你的架构,我不想给你错误的建议 :-) 但是,我不明白你为什么需要一个组件.正如您所说,*ngFor 可以使用一组对象(新文章)来做到这一点。当您定期更新 *ngFor 持有的输入时,您几乎可以做同样的事情。
    • 因为我根本不需要数组。而且我不希望每个“附加”到数组 - 从一开始就“渲染”所有项目。 (如果注入的控件会有一个 IMG ,我不希望 SRC 每次有新文章到达时都调整。
    • @Royi 您不需要将新内容推送到数组中,您可以通过将新的对象数组分配给现有数组来替换数组,因此旧的不会显示。
    • 你是什么意思“因此旧的不会显示”?我希望他们在那里。这就像一个新项目到达的无限滚动,我附加它们。 odl 仍然/应该在那里(无需重新渲染)我很乐意看到一个例子
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-07-11
    • 1970-01-01
    • 2015-07-17
    • 2016-12-27
    • 1970-01-01
    • 1970-01-01
    • 2017-03-26
    相关资源
    最近更新 更多