Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generating child components in angular2 with NgFor does not work

Tags:

angular

I'm using angular2 alpha 37.

I've defined a <map> component and a <marker> component (child of <map>). The <map> component has a array data member which contains a list of marker coordinates. The <map> view should display all markers in the array

When defining the <map> view as follows (explicitly listing components for all array members):

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

The <marker> components are updated whenever the corresponding array member changes. This is desired behaviour.

When defining the <map> view as follows (using NgFor):

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

a new marker is created whenever the array members change, which is not desirable.

Needles to say I would like to use the NgFor method.

I've no clue what is going on. How can I use NgFor but avoid that new <marker> instances are created whenever the individual markers update?

like image 927
Sepp Van Rompaey Avatar asked Oct 01 '15 19:10

Sepp Van Rompaey


1 Answers

Split the list ngFor iterates over from the model data.

This is Dart code but shouldn't be hard to translate to 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';
}
like image 77
Günter Zöchbauer Avatar answered Oct 02 '22 14:10

Günter Zöchbauer