【问题标题】:Angular2 applying Pipe after data is receivedAngular2在收到数据后应用管道
【发布时间】:2017-08-28 02:55:51
【问题描述】:

我有一个Object,用于管理从后端接收的数据。 它以display: false的所有字段启动,如果我从服务器收到该特定字段,我最终会将其更改为true

filterGroups(初始):

export let filterGroups: any = {
    genericFilters: {
        iboId: {
            'display': false,
            'template': ''
        },
        iboCode: {
            'display': false,
            'template': 'text/iboCode'
        },
        iboName: {
            'display': false,
            'template': 'text_input_iboName'
        },
        iboSurname: {
            'display': false,
            'template': 'text_input_iboSurname'
        },
        iboRank: {
            'display': false,
            'template': 'select/multi_iboRank',
        },
        iboEmail: {
            'display': false,
            'template': 'text_input_iboEmail'
        },
        iboNewsletter: {
            'display': false,
            'template': 'select/simple_iboNewsletter',
        },
    },
    orderFilters: {
        iboTotalOrders: {
            'display': false,
            'template': 'compound/iboTotalOrders',
        }
    },
    peFilters: {
        iboTotalPE: {
            'display': false,
            'template': 'checkbox/iboTotalPE',
        }
    },
};

在我的模板中,我希望div 与过滤器组一样多。在这种情况下,我们有 3 个过滤器组:genericFiltersorderFilterspeFilters

一旦我从服务器接收到数据(我在我的constructor 中调用),这个Object 就会被修改。

因此,在我收到来自我的异步调用的数据后,我的filterGroups 将如下所示。

filterGroups(异步调用后):

export let filterGroups: any = {
    genericFilters: {
        iboId: {
            'display': true,
            'template': ''
        },
        iboCode: {
            'display': true,
            'template': 'text/iboCode'
        },
        iboName: {
            'display': true,
            'template': 'text_input_iboName'
        },
        iboSurname: {
            'display': true,
            'template': 'text_input_iboSurname'
        },
        iboRank: {
            'display': false,
            'template': 'select/multi_iboRank',
        },
        iboEmail: {
            'display': true,
            'template': 'text_input_iboEmail'
        },
        iboNewsletter: {
            'display': false,
            'template': 'select/simple_iboNewsletter',
        },
    },
    orderFilters: {
        iboTotalOrders: {
            'display': true,
            'template': 'compound/iboTotalOrders',
        }
    },
    peFilters: {
        iboTotalPE: {
            'display': false,
            'template': 'checkbox/iboTotalPE',
        }
    },
};

现在,在我的模板中,我有这个:

模板 (HTML):

<div *ngFor="let group of filterGroups | keysCheckDisplay">
    <div>
        <h4>{{group.key}}</h4>
    </div>
</div>

而且,很明显,这是我的@Pipe

@Pipe:

import { PipeTransform, Pipe } from '@angular/core';
import { isNullOrUndefined } from 'util';

@Pipe({name: 'keysCheckDisplay'})
export class KeysCheckDisplayPipe implements PipeTransform {
    transform(value, args: string[]): any {
        let keys = [];
        for (let key in value) {
            if (!isNullOrUndefined(value[key])) {
                let display = false;
                for (let keyChild in value[key]) {
                    if (!isNullOrUndefined(value[key][keyChild]) && value[key][keyChild]['display'] === true) {
                        display = true;
                        break;
                    }
                }
                if (display === true) {
                    keys.push({key: key, value: value[key]});
                }
            }
        }
        return keys;
    }
}

在这个@Pipe 中,你可以看到我做了几件事:

  • 循环遍历filterGroups 对象
  • 检查对象中的每个组是否存在具有display: true 的子项。

功能:

我希望这个@Pipe 循环通过我的Object返回至少有一个display: true 元素的“过滤器组”

问题:

@Pipe 正在获取filterGroups 对象的第一个版本,并且忽略了对象在我从服务器接收到数据后立即更改的事实。

如果我修改 filterGroups 对象的初始值,@Pipe 可以正常工作。

我尝试过的:

  • 研究,研究,研究
  • 我将@Pipe 更改为inpure,但我讨厌这个解决方案,因为性能很差,而且它进入了无限循环。
  • 我也尝试过这种方法: *ngFor="let group of filterGroups | async | keysCheckDisplay"。 但是它抛出了以下错误:

错误:InvalidPipeArgument:管道“AsyncPipe”的“[object Object]”

可能的解决方案?

  • 修改@Pipe?

  • 修改初始object

  • 创建第二个@Pipe 来循环第一个管道的结果?

我希望它是详细和清晰的,如果没有,请不要评论要求更多细节,我很乐意更新帖子。

先谢谢你!

【问题讨论】:

  • 你有 Plunkr 吗?能帮到你真是太好了!在这里使用异步管道对您没有帮助,因为您不是在处理可观察对象。您是否更改了组件中的ChangeDetectionStrategy? (也许是 OnPush ?)
  • 嘿@Maxime!不,我没有更改ChangeDetectionStrategy。我会看看它,看看在这种情况下如何使用它。感谢您的提示。

标签: angular typescript angular4


【解决方案1】:

纯管道仅在数据更改时才被调用。这意味着当“数据”是一个新的对象实例时。如果只修改了对象的内容,那么 Angular 更改检测不会将其识别为更改,也不会调用管道。

可能的方法

  • 使管道不纯:通常对性能造成很大负担
  • 复制对象,如:
var tmp = this.data; this.data = {}; Object.assign(this.data, tmp);
  • 向管道添加附加参数并更新参数值
*ngFor="let item of data | myPipe:counter"
// updated `data`
// this.counter++;

【讨论】:

  • 感谢您的快速回答。我会尝试一下,并在我完成实施后立即通知您!
  • 我选择了第二种方法。我刚刚为布局/渲染目的创建了一个新对象。并保持原样,因为其他功能依赖于它。这样做,我保持我的所有功能完好无损,并且布局功能(使用我的新对象)按我的预期工作。谢谢你。在 Angular 2 和 4 中,我还有很长的路要走。:D
  • 是的,有很多东西要学。很高兴听到你能成功。
猜你喜欢
  • 1970-01-01
  • 2016-12-24
  • 2021-02-14
  • 2019-10-10
  • 1970-01-01
  • 2017-11-10
  • 1970-01-01
  • 2017-06-09
  • 2017-05-04
相关资源
最近更新 更多