2016-06-24 4 views
3

Как-то возможно в Angular2 получить уведомление до того, как компонент уже уничтожен !? т. е. когда это ОБРАЩЕНИЕ к уничтожению.Angular2 снят вид перед onDestroy?

У меня есть компонент контейнера, который содержит ViewContainerRef для одного из его дочерних элементов, который будет использоваться для динамической загрузки представлений. Если сам контейнерный компонент уничтожается (в моем случае из-за директивы * ngFor в родительском компоненте), я хочу отключить представление, которое в настоящее время загружается в ViewContainerRef, и снова присоединить его к другому контейнеру.

Вещь: в цикле жизненного цикла ngOnDestroy() ViewContainerRef уже очищен, поэтому все виды уничтожены, и ничего больше не нужно отсоединять.

+0

Существует не такой крючок жизненного цикла. Вы можете создать пользовательский 'ngFor'. Исходный код не является сложным. В этом пользовательском 'ngFor' вы можете вызвать метод на добавленном компоненте или испустить событие, которое уведомляет компонент об уничтожении. –

+0

Хорошая идея. Я дам ему попробовать – seraph

ответ

1

Мое решение на данный момент (на самом деле не обходное решение) заключается в реализации ngOnChanges() родительского компонента, который использует директиву ngFor. Если массив, который итерируется ngFor, изменился, и его длина короче, чем до того, как я просто отделил представления всех контейнеров (контейнеры @ViewChildren: QueryList) и сопоставил их с контейнерами (Карта). Затем я снова вставляю отображаемые виды, повторяя список новых контейнеров и загружая ViewRefs с карты в list.changed listener.

@Component({ 
selector: 'container-collection', 
directives: [Container], 
template: `<container *ngFor="let i of views"></container>` 
}) 
export class ContainerCollection { 
public views = []; 

@ViewChildren(Container) private containers: QueryList<Container>; 

private viewMap = new Map<Container, ViewRef>(); 

public ngOnChanges(changes: {[key: string]: SimpleChange]}): void { 
    if(changes['views']) { 
    //detach all views and remember which container had which view 
    this.viewMap = new Map<Container, ViewRef>(); 

    this.containers.forEach(container => { 
    var view = container.viewContainer.detach(); 
    if(view) 
    this.viewMap.set(container, view); 
    }); 
    } 
} 

public ngAfterViewInit(): void { 
    //insert the views again (into the appropriate containers) 
    this.containers.changes.subscribe(() => { 
    this.containers.forEach(container => { 
    var view = this.viewMap.get(container); 
    if(view) 
    container.viewContainer.insert(view); 
    }); 
    }); 
} 
} 

@Component({ 
selector: 'container', 
template: `<div #viewContainer></div>` 
}) 
export class Container { 
@ViewChild('viewContainer') public viewContainer; 
} 

Код только в черновике и может содержать ошибки синтаксиса. Но идея (которая работает для меня) должна быть ясной.

Было бы здорово, если бы команда Angular2 добавила к ней крюк LifeCycle, который будет вызван до того, как компонент будет фактически уничтожен. (например, ngBeforeDestroy()) или так далее.

0

Не уверены, что если есть какой-либо другой жизненный цикл крюк, который удовлетворял бы ваше состояние:

const LIFECYCLE_INTERFACES: Map<any, Type> = MapWrapper.createFromPairs([ 
    [LifecycleHooks.OnInit, OnInit], 
    [LifecycleHooks.OnDestroy, OnDestroy], 
    [LifecycleHooks.DoCheck, DoCheck], 
    [LifecycleHooks.OnChanges, OnChanges], 
    [LifecycleHooks.AfterContentInit, AfterContentInit], 
    [LifecycleHooks.AfterContentChecked, AfterContentChecked], 
    [LifecycleHooks.AfterViewInit, AfterViewInit], 
    [LifecycleHooks.AfterViewChecked, AfterViewChecked], 
]); 

const LIFECYCLE_PROPS: Map<any, string> = MapWrapper.createFromPairs([ 
    [LifecycleHooks.OnInit, 'ngOnInit'], 
    [LifecycleHooks.OnDestroy, 'ngOnDestroy'], 
    [LifecycleHooks.DoCheck, 'ngDoCheck'], 
    [LifecycleHooks.OnChanges, 'ngOnChanges'], 
    [LifecycleHooks.AfterContentInit, 'ngAfterContentInit'], 
    [LifecycleHooks.AfterContentChecked, 'ngAfterContentChecked'], 
    [LifecycleHooks.AfterViewInit, 'ngAfterViewInit'], 
    [LifecycleHooks.AfterViewChecked, 'ngAfterViewChecked'], 
]); 
1

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

Затем используйте @ViewChildren аннотацию для хранения списка всех отображаемых компонентов в *ngFor. Что-то вроде:

<my-component 
    #mycomponents 
    *ngFor="let c of collection" 
</my-component> 

Вы можете перебирать компоненты, определенные #mycomponents, найти который один изменился и вызывать некоторые пользовательский метод, который будет отделяться, что вам нужно.

Другой и, возможно, более простой способ может использовать только @ViewChildren и QueryList, поскольку он имеет свойство changes которое является Observable<any> так подписавшись он должен уведомить вас о любых изменениях в коллекции итерировать с *ngFor. Тем не менее, я не уверен, в какой момент событие выдается, поэтому может быть слишком поздно, как вы описали с помощью onDestroy.

+0

Спасибо за ответ. Но да, уже слишком поздно, когда отправлено событие с изменениями – seraph

+0

Но идея onChanges в основном работала. Я добавил полный ответ, чтобы получить все решение. – seraph

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