问题
I'm using ngb-accordion in ng-bootstrap. Toggling a header causes its child components to reinitialize. For example, toggling headers cause dropdowns to reset. It looks like this is because <div class="card-block"></div>
is deleted when the panel is hidden.
How do I maintain the state of components even when they're "hidden" in the accordion?
Template file:
<ngb-accordion activeIds="side-bar-accordion-1" (panelChange)="beforeChange($event)">
<div [class.hide-card-block]="status">
<ngb-panel id="side-bar-accordion-1" class="foo">
<template ngbPanelTitle>
<div class="title">Axes</div>
</template>
<template ngbPanelContent>
<!--This is the component whose state I want to maintain:-->
<side-bar-axes></side-bar-axes>
</template>
</ngb-panel>
</div>
<ngb-panel id="side-bar-accordion-2">
<template ngbPanelTitle>
<div class="title">Fancy</div>
</template>
<template ngbPanelContent>
blah blah
</template>
</ngb-panel>
<ngb-panel id="side-bar-accordion-3">
<template ngbPanelTitle>
<div class="title">Settings</div>
</template>
<template ngbPanelContent>
blah blah
</template>
</ngb-panel>
</ngb-accordion>
Component TypeScript file:
import { Component, ViewChildren, ViewEncapsulation } from '@angular/core';
import { NgbPanelChangeEvent } from '@ng-bootstrap/ng-bootstrap';
import { FieldChooseFiltersComponent } from '../field-choose-filters/field-choose-filters.component';
@Component({
moduleId: module.id,
selector: 'side-bar',
templateUrl: 'side-bar.component.html',
styleUrls: ['side-bar.component.css'],
encapsulation: ViewEncapsulation.None
})
export class SideBarComponent {
hideNum: number = 1;
status: boolean = false;
toggleStatus() {
this.status = !this.status;
}
public beforeChange($event: NgbPanelChangeEvent) {
if ($event.panelId === '1' && $event.nextState === false) {
$event.preventDefault();
}
if ($event.panelId === '2' && $event.nextState === false) {
$event.preventDefault();
}
if ($event.panelId === '3' && $event.nextState === false) {
$event.preventDefault();
}
};
}
回答1:
The current implementation of https://ng-bootstrap.github.io/#/components/accordion assumes that only active (visible) panels shell be kept in the DOM. This was a conscious design decision as keeping non-visible panels around would mean that:
- their content gets initialised even if never shown
- Angular would have to run change detection on parts that are no visible and don't add to the experience to the end users.
So, currently things work as designed. If you want to preserve state when a panel gets opened / closed one option would be to move relevant state to one of a parent components.
If there is enough interest in the community we might add an option to not destroy panels' content when those are closed.
回答2:
NgbAccordion
has input option destroyOnHide
. It needs to be false. Take a look in docs here.
Example: <ngb-accordion [destroyOnHide]="false">
来源:https://stackoverflow.com/questions/40451452/ng-bootstrap-accordion-reinitializes-component