使用NgFor在angular2中生成子组件不起作用

时间:2015-10-01 19:05:09

标签: angular

我使用angular2 alpha 37。

我已经定义了<map>组件和<marker>组件(<map>的子组件)。 <map>组件有一个数组数据成员,其中包含标记坐标列表。 <map>视图应显示数组中的所有标记

如下定义<map>视图(明确列出所有数组成员的组件):

@View({
  template:`
    <marker [model]="markers[0]"></marker>
    <marker [model]="markers[1]"></marker>
  `,
  directives:[Marker]
})

只要相应的数组成员发生更改,<marker>组件就会更新。这是理想的行为。

按如下方式定义<map>视图时(使用NgFor):

@View({
  template: '<marker *ng-for="#m of markers" [model]="m"></marker>',
  directives:[Marker,NgFor]
})

每当数组成员发生更改时都会创建一个新标记,这是不可取的。

有人说我想使用NgFor方法。

我不知道发生了什么事。如何使用NgFor,但避免在单个标记更新时创建新的<marker>实例?

3 个答案:

答案 0 :(得分:3)

拆分列表ngFor从模型数据中迭代。

这是Dart代码,但不应该很难转换为TS

import 'dart:math' show Random;
import 'package:angular2/angular2.dart';

@Component(
    selector: 'app-element',
    template: '''
<h3>app-element</h3>
<map></map>
    ''',
    directives: const [MapComponent])
class AppElement {}
    
@Component(selector: 'map',
    template: '''
<button (click)="changeValue()">Change value</button>
<marker *ngFor="let m of markersIndexes" [model]="markers[m]"></marker>
<!-- use `markers[m]` to assign a model but `markersIndexes` for `*ng-for` -->
''',
    directives: const [MarkerComponent, NgFor])
class MapComponent {
  MapComponent() {
    markers = <Marker>[
      new Marker('m0', 0),
      new Marker('m1', 1),
      new Marker('m2', 2),
      new Marker('m3', 3)
    ];
    markersIndexes = new List<int>.generate(markers.length, (int index) => index);
  }
  List<Marker> markers; // model to pass to <marker>
  List<int> markersIndexes; // indexes used by *ng-for
  // when markers are added or removed markersIndexes need to by updated of course

  // Update random marker item with random position value    
  Random _rnd = new Random();
  void changeValue() {
    int idx = _rnd.nextInt(3);
    markers[idx].position = _rnd.nextInt(100);
  }
}
@Component(
    selector: 'marker',
    template: '''
<h3>marker</h3>
<div>name: {{model.name}} pos: {{model.position}} created: {{createdAt}}</div>
''',
    styles: const [
      '''
:host {
  display: block;
  border: 1px solid green;
}
'''
    ])
class MarkerComponent implements OnInit {
  @Input() Marker model;
  String createdAt;

  MarkerComponent() {
    createdAt = new DateTime.now().toString();
  }
  void ngOnInit() {
    print(model);
  }
}
// Marker model
class Marker {
  String name;
  int position;

  Marker(this.name, this.position);

  @override
  String toString() => 'Marker: $name - $position';
}

答案 1 :(得分:0)

试试这个

@View({
template:"<marker *ng-for="#m of markers" [model]="m">{{m}}</marker>",
 directives:[Marker,NgFor]
})

答案 2 :(得分:0)

我看到您使用的alpha37版本仍然是alpha版本而且您可能有一些错误...我使用beta0版本进行了一些测试,它似乎按预期工作。所以我建议你升级到这个版本......我们希望beta版本更稳定; - )

以下是我用来测试的代码:

  • 主要组件

    @Component({
        selector: 'first-app',
        template: `
          <map></map>
        `,
        directives: [ MapComponent ]
    })
    export class AppComponent {
    }
    
  • Marker数据对象

    class Marker {
      name: string;
      position: int;
    
      constructor(name, position) {
        this.name = name;
        this.position = position;
      }
    }
    
  • Marker组件

    @Component({
      selector: 'marker',
      template:`
        <div class="marker">Marker {{model.name}} <button (click)="update()">Update</button></div>
      `,
      directives:[MarkerComponent]
    })
    export class MarkerComponent implements OnInit {
      @Input() model: Marker;
    
      constructor() {
    
      }
    
      ngOnInit() {
      }
    
      update() {
        this.model.name = this.model.name + 'a';
      }
    }
    
  • Map组件

    @Component({
      selector: 'map',
      template:`
        <marker *ngFor="#m of markers" [model]="m"></marker>
        <button (click)="update()">Update</button>
      `,
      directives:[MarkerComponent]
    })
    export class MapComponent {
      constructor() {
        this.markers = [
          new Marker('m0', 0),
          new Marker('m1', 1),
          new Marker('m2', 2),
          new Marker('m3', 3)
        ];
      }
    
      update() {
        this.markers[1].name = 'm1a';
      }
    }
    

当我点击两个更新按钮时,第二个标记的名称会在视图中更新,并且不会显示其他<marker>元素。

修改

这可能是您更新列表中元素的方式。您是使用新实例覆盖它还是更新列表中存在的实例的属性值?在第一种情况下,我认为您可以在列表中添加新元素。

update() {
  this.markers[1]= new Marker('m1a', 1);
}

经过一些测试后,这种方法也可以。列表中未添加任何元素。

希望它可以帮到你, 亨利