2017-02-04 3 views
1

Я довольно новичок в Angular 2, и я хочу передать массив, сделанный в родительском компоненте, через @Input(), его дочернему элементу.Преобразует ли массив объект после @Input() в дочерний?

В родительском я создаю массив, добавляю данные из службы и отображаю его в консоли (выход консоли 1). В дочернем компоненте я затем использую ngOnChanges, чтобы снова отобразить его в консоли (вывод консоли 2). Как вы можете видеть ниже, длина массива изменяется от 12 до 0. Я полагаю, это связано с тем, что массив переходит к объекту, когда он передается ребенку?

Как бы исправить это?

Родитель

import { Component, OnInit } from '@angular/core'; 
import { Module, MapMarkerData } from './coreclasses'; 
import { TimelineService } from './input.service'; 

@Component({ 
    selector: 'my-app', 
    templateUrl: 'app/app.component.html', 
    providers: [TimelineService] 
}) 

export class AppComponent implements OnInit { 
    modules: Module[]; 
    mapMarkerData: any; 

    constructor(private timelineService: TimelineService) { 
    this.mapMarkerData = new Array<MapMarkerData>(); 
    } 

    getModules(): void { 
    this.timelineService.getModules().then(modules => {this.modules = modules; this.setMapModuleData(this.modules);}); 
    } 

    setMapModuleData(modules: Array<any>): void { 
    for (let module of modules) { 
     if (module.className) { 
     var id = module.id; 
     var className = module.className; 
     let contents: Object = {id: id, className: className}; 
     this.mapMarkerData.push(contents); 
     } 
    } 
    console.log(this.mapMarkerData); // CONSOLE OUTPUT 1 
    console.log(this.mapMarkerData.length); 
    } 
} 

Детский

import { Component, Input, OnInit, OnChanges, SimpleChanges } from '@angular/core'; 
import { MapMarkerData } from './coreclasses'; 

@Component({ 
    selector: 'timeline-map', 
    templateUrl: 'app/timeline.map.component.html' 
}) 

export class TimelineMapComponent implements OnChanges { 
    @Input() 
    mapMarkerData: any; 

    ngOnChanges(changes: any) { 
     console.log(this.mapMarkerData); // CONSOLE OUTPUT 2 
     console.log(this.mapMarkerData.length); 
    } 
} 

Родитель Шаблон

... 
<div id="map" class="mapLarge"> 
    <timeline-map [mapMarkerData] = "mapMarkerData"></timeline-map> 
</div> 
... 

Console Output 1 Array [12]: [Object, Object, ...]

Консоль Выход 2 Array [0]: [Object, Object, ...]

+0

массив не изменяется, когда передается ребенку.Я подозреваю, что 'Console Output 2' печатается до' Console Output 1'. Разве это не так? –

+0

изменение осуществляется с помощью 'changes.mapMarkerData.currentValue' – harshes53

ответ

1

EDIT Важно

, потому что вы передаете ту же ссылку в ребенка компонент, поэтому ngOnChanges жизненный цикл только выпустили 1 раз.

пожалуйста извлекает эту версию, откройте вкладки консоли: https://plnkr.co/edit/WUDGOx?p=preview

так, если вы хотите поймать каждые изменения в ngOnChanges жизненного цикла, необходимы прохождение разностного массива, например: https://plnkr.co/edit/8awiqe?p=preview

import { Component, OnInit } from '@angular/core'; 

@Component({ 
    selector: 'app-root', 
    template: ` 
    <h2>App Component</h2> 
    <p><strong>This app will trigger ngOnChanges with immutable array</strong></p> 
    <app-content [posts]="posts"> 
    </app-content> 
    ` 
}) 
export class AppComponent implements OnInit { 
    latestPosts: any[] = []; 
    posts: any[] = []; 


    ngOnInit() { 
    // fake api call 
    setTimeout(() => { 
     this.latestPosts.push.apply(this.latestPosts, [ 
     {name: 'Post no.1'}, 
     {name: 'Post no.2'}, 
     {name: 'Post no.3'} 
     ]); 
     this.posts = [].concat(this.latestPosts); 
    }, 300); 
    } 

} 

=== Второй вариант === Вы можете проверить сами в DoCheck жизненный цикл: https://plnkr.co/edit/oxsISD?p=preview

import { Component, Input, DoCheck, IterableDiffers } from '@angular/core'; 

@Component({ 
    selector: 'app-content', 
    template: ` 
    Status: {{ status }} 
    <div *ngFor="let post of pp"> 
     {{ post.name }} 
    </div> 
    ` 
}) 

export class ContentComponent implements DoCheck { 

    @Input() 
    posts: any[]; 
    differ: IterableDiffers; 
    status: string = ''; 

    constructor(private differs: IterableDiffers) { 
     this.differ = this.differs.find([]).create(null); 
    } 

    ngDoCheck() { 
    var changes = this.differ.diff(this.posts); 
    if (changes) { 
     console.log('ngDoCheck'); 
     this.status = 'ngDoCheck invoked!' 
    } 
    } 
} 

Обратите внимание, что вы оплачиваете расходы, потому что вышеуказанный метод ngDoCheck будет вызывать при каждом запуске обнаружения изменений.

https://angular.io/docs/ts/latest/guide/lifecycle-hooks.html

https://angular.io/docs/ts/latest/api/core/index/DoCheck-class.html

https://angular.io/docs/ts/latest/api/core/index/SimpleChange-class.html

https://angular.io/docs/ts/latest/api/core/index/IterableDiffers-class.html

END

для начального состояния, то пусто, то значение будет присвоить этому свойству.

JS войти асинхронной js log async

+0

Спасибо, что ответили так быстро! Консольный вывод 2 не пуст (см. [Object, Object, ...]) и содержит содержимое массива, полученное от родителя, но его длина как-то равна нулю. console.log (изменения ['mapMarkerData']. currentValue.length) также дает 0, но я вижу, что он содержит содержимое массива, а console.log (изменения ['mapMarkerData']. previousValue) пуст, как и должно быть , Итак, ребенок получил модифицированный массив из своего родителя, но его отображаемая длина изменилась? Это действительно не имеет смысла для меня? – Merlin

+0

hey man, это js way, если вы «регистрируете» массив пустым на временной шкале 0, затем временной шкалой 1, вы ставите значение в это, оно будет выводить длину 0, но содержимое не пусто –

+0

открытая вкладка консоли (f12) , тогда попробуйте это http://jsbin.com/perujayewu/edit?js,console,output –

 Смежные вопросы

  • Нет связанных вопросов^_^