Skip to content

Commit 2d892e3

Browse files
Liza Katzalexwizp
authored andcommitted
Fix angular stack overflow by changing apply filters popover directive implementation (#48559)
1 parent 6658922 commit 2d892e3

4 files changed

Lines changed: 60 additions & 47 deletions

File tree

src/legacy/core_plugins/data/public/filter/apply_filters/apply_filters_popover.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import React, { Component } from 'react';
3636
import { IndexPattern } from '../../index_patterns';
3737
import { getDisplayValueFromFilter } from '../filter_bar/filter_editor/lib/filter_editor_utils';
3838
import { getFilterDisplayText } from '../filter_bar/filter_editor/lib/get_filter_display_text';
39+
import { mapAndFlattenFilters } from '../filter_manager/lib/map_and_flatten_filters';
3940

4041
interface Props {
4142
filters: Filter[];
@@ -70,9 +71,11 @@ export class ApplyFiltersPopover extends Component<Props, State> {
7071
return '';
7172
}
7273

74+
const mappedFilters = mapAndFlattenFilters(this.props.filters);
75+
7376
const form = (
7477
<EuiForm>
75-
{this.props.filters.map((filter, i) => (
78+
{mappedFilters.map((filter, i) => (
7679
<EuiFormRow key={i}>
7780
<EuiSwitch
7881
label={this.getLabel(filter)}

src/legacy/core_plugins/data/public/shim/apply_filter_directive.html

Lines changed: 0 additions & 8 deletions
This file was deleted.

src/legacy/core_plugins/data/public/shim/legacy_module.ts

Lines changed: 42 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,11 @@
2020
import { once } from 'lodash';
2121

2222
import { wrapInI18nContext } from 'ui/i18n';
23-
import { Filter } from '@kbn/es-query';
2423

2524
// @ts-ignore
2625
import { uiModules } from 'ui/modules';
2726
import { npStart } from 'ui/new_platform';
2827
import { FilterBar, ApplyFiltersPopover } from '../filter';
29-
import template from './apply_filter_directive.html';
3028

3129
// @ts-ignore
3230
import { mapAndFlattenFilters } from '../filter/filter_manager/lib/map_and_flatten_filters';
@@ -76,35 +74,53 @@ export const initLegacyModule = once((): void => {
7674
['pluginDataStart', { watchDepth: 'reference' }],
7775
]);
7876
})
79-
.directive('applyFiltersPopoverComponent', (reactDirective: any) =>
80-
reactDirective(wrapInI18nContext(ApplyFiltersPopover))
81-
)
8277
.directive('applyFiltersPopover', () => {
8378
return {
84-
template,
8579
restrict: 'E',
86-
scope: {
87-
filters: '=',
88-
onCancel: '=',
89-
onSubmit: '=',
90-
indexPatterns: '=',
91-
},
92-
link($scope: any) {
93-
$scope.state = {};
94-
95-
// Each time the new filters change we want to rebuild (not just re-render) the "apply filters"
96-
// popover, because it has to reset its state whenever the new filters change. Setting a `key`
97-
// property on the component accomplishes this due to how React handles the `key` property.
98-
$scope.$watch('filters', (filters: any) => {
99-
const mappedFilters: Filter[] = mapAndFlattenFilters(filters);
100-
$scope.state = {
101-
filters: mappedFilters,
102-
key: Date.now(),
103-
};
104-
});
80+
template: '',
81+
compile: (elem: any) => {
82+
const child = document.createElement('apply-filters-popover-helper');
83+
84+
// Copy attributes to the child directive
85+
for (const attr of elem[0].attributes) {
86+
child.setAttribute(attr.name, attr.value);
87+
}
88+
89+
// Add a key attribute that will force a full rerender every time that
90+
// a filter changes.
91+
child.setAttribute('key', 'key');
92+
93+
// Append helper directive
94+
elem.append(child);
95+
96+
const linkFn = ($scope: any, _: any, $attr: any) => {
97+
// Watch only for filter changes to update key.
98+
$scope.$watch(
99+
() => {
100+
return $scope.$eval($attr.filters) || [];
101+
},
102+
(newVal: any) => {
103+
$scope.key = Date.now();
104+
},
105+
true
106+
);
107+
};
108+
109+
return linkFn;
105110
},
106111
};
107-
});
112+
})
113+
.directive('applyFiltersPopoverHelper', (reactDirective: any) =>
114+
reactDirective(wrapInI18nContext(ApplyFiltersPopover), [
115+
['filters', { watchDepth: 'collection' }],
116+
['onCancel', { watchDepth: 'reference' }],
117+
['onSubmit', { watchDepth: 'reference' }],
118+
['indexPatterns', { watchDepth: 'collection' }],
119+
120+
// Key is needed to trigger a full rerender of the component
121+
'key',
122+
])
123+
);
108124

109125
const module = uiModules.get('kibana/index_patterns');
110126
let _service: any;

src/legacy/core_plugins/kibana/public/dashboard/dashboard_app_controller.tsx

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -422,19 +422,21 @@ export class DashboardAppController {
422422
};
423423

424424
$scope.onApplyFilters = filters => {
425-
// All filters originated from one visualization.
426-
const indexPatternId = filters[0].meta.index;
427-
const indexPattern = _.find(
428-
$scope.indexPatterns,
429-
(p: IndexPattern) => p.id === indexPatternId
430-
);
431-
if (indexPattern && indexPattern.timeFieldName) {
432-
const { timeRangeFilter, restOfFilters } = extractTimeFilter(
433-
indexPattern.timeFieldName,
434-
filters
425+
if (filters.length) {
426+
// All filters originated from one visualization.
427+
const indexPatternId = filters[0].meta.index;
428+
const indexPattern = _.find(
429+
$scope.indexPatterns,
430+
(p: IndexPattern) => p.id === indexPatternId
435431
);
436-
queryFilter.addFilters(restOfFilters);
437-
if (timeRangeFilter) changeTimeFilter(timefilter, timeRangeFilter);
432+
if (indexPattern && indexPattern.timeFieldName) {
433+
const { timeRangeFilter, restOfFilters } = extractTimeFilter(
434+
indexPattern.timeFieldName,
435+
filters
436+
);
437+
queryFilter.addFilters(restOfFilters);
438+
if (timeRangeFilter) changeTimeFilter(timefilter, timeRangeFilter);
439+
}
438440
}
439441

440442
$scope.appState.$newFilters = [];

0 commit comments

Comments
 (0)