2016-12-02 4 views
1

Я пытаюсь создать компонент карусели для своего приложения Angular 2.Angular 2 - when * ngFor завершает функцию вызова на родительском компоненте

Я хочу карусельного быть универсальным, так что он будет поддерживать оба этих случая:

<myCarousel> 
    <div>first card</div> 
    <div>second card</div> 
    .... 
</myCarousel> 

и более общий

<myCarousel> 
    <myCard *ngFor="let card of cards" [card]="card"></myCard> 
</myCarousel> 

Проблема заключается в том, что компонент карусельного требует инициализации в пробег после * ngFor завершен, иначе он будет отображаться неправильно.

Поскольку данные поступают из вызова веб-службы, я не могу угадать точное время, но мне нужен компонент карусели для наблюдения, неявно или явно, когда * ngFor завершен. Может ли кто-нибудь помочь? Спасибо!

ответ

0

Существует еще один Stackoverflow ответа, который уже решает эту проблему: https://stackoverflow.com/a/36750875/463893

Моего решения очень похоже: директива (так называемый CarouselItem), приложенную к карусельным элементам внутри * ngFor, определение булева вход который указывает, является ли элемент последним, и свойство (или eventemitter), которое может быть установлено на функцию для вызова, когда последний элемент был достигнут.

Таким образом, шаблон становится:

<myCarousel #carousel> 
    <myCard *ngFor="let card of cards; let l = last" 
      [card]="card" 
      CarouselItem 
      [ready]="l ? true : false" 
      [init]="carousel.initialize"> 
    </myCard> 
</myCarousel> 

переменная #carousel необходима, чтобы иметь возможность ссылаться на компонент карусельного из директивы myCard ([INIT] = "carousel.initialize").

Ниже приведен код директивы:

@Directive({ 
    selector: `[CarouselItem]` 
}) 
export class CarouselItem { 

    @Input('init') onInit: Function =() => {}; 

    @Input() set ready(isReady: boolean) { 
     if (isReady) 
     setTimeout(()=>this.onInit(), 200); 
    }; 
} 

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

public initialize=()=> { 
    // perform initialisation 
}; 
1

Огнь событие на последнюю попытку ngFor ниже

<myCard *ngFor="#card in cards; #last=last" [card]="card" [attr.ready]="last ? false : true"></myCard> 

и в коде сделать это

@Input() 
set ready(isReady: boolean) { 
    if (isReady) someCallbackMethod(); 
} 

Надеется, что это помогает :)

+0

Спасибо, но не могли бы вы быть более ясными? В каком компоненте указан готовый атрибут? Я попытался определить его на компоненте карусели, но я, похоже, не могу его ссылаться. Это то, что я пытался, расстроить шаблон компилятор :) udik

1

Вы можете использовать ContentChildren.

@ContentChildren(MyCardComponent) cards: QueryList<MyCardComponent>; 

ngOnAfterContentInit() { 
    this.cards 
     .changes 
     //.debounce(100) /* maybe add an additional debounce time.. */ 
     .subscribe(cards => { 
     // received new cards.. 
    }); 
} 
+0

Нет, я не думаю, что это сработает, так как я хочу, чтобы карты были полностью универсальными - это могли быть MyCard или MyPicture или что-то еще.В противном случае я получаю компонент карусели, который тесно связан с одним конкретным типом контента. – udik