在 Angular 应用程序中处理过滤值的更优雅的方式

Posted

技术标签:

【中文标题】在 Angular 应用程序中处理过滤值的更优雅的方式【英文标题】:A More Elegant Way to Handle Filtering Values in Angular App 【发布时间】:2018-02-02 18:40:59 【问题描述】:

我在 Angular 2 应用程序中多次重新加载表格显示中的数据时遇到了一些问题。我认为主要问题与以下事实有关:在初始组件加载时,我正在为一系列过滤器发送数据作为网络请求。

基本上,我们正在使用 Mongo/Mongoose 功能,该功能允许我们在发布请求的对象正文中传递键/值对,然后根据这些传入的值返回过滤数据集。此代码如下所示:

private processType(name: string, value: any, body)

    if (this.body[name] && !value) 
            delete this.body[name];
         else 
            this.body[name] =  $in: value ;
        
 

所有这些都按预期工作。但是,在我当前的实现中感觉不太理想的是,在初始组件加载时,我为每个过滤器传递了一个包含所有可能值的数组。从那里,用户可以通过 UI 过滤器列表更改传递和过滤的内容。我在初始组件加载时为每个过滤器传递了整个可能值数组,因为如果我传入一个空数组,则没有任何匹配项。但是,似乎应该有更好的方法来处理我的初始请求。

理想情况下,我希望我的初始请求有效地是“最初不过滤任何内容”,而不是像我现在所做的那样“最初过滤所有内容”。我现在已经这样做了,因为处理初始加载时的条件以及用户删除过滤器或所有过滤器的情况有点棘手。现在,在任何一种情况下,我都只是再次传入所有可能值的数组。我有什么作品,但它似乎并不像它应该的那样优雅。由于这一切都在 post 请求的正文中作为对象传递,有没有办法我可以删除该对象而不是传递一个包含所有值的数组的对象?

这就是我其余的相关代码的样子:

public initLanguageFilterOptions(): void

    this.languageFilterOptions = new FilterOptions([
         value: 'English', toString: () => 'English' ,
         value: 'Spanish', toString: () => 'Spanish' ,
         value: 'Mandarin', toString: () => 'Mandarin' 
    ]);

    let arr = [];

    // Update array when filter selection is made
    arr.push(this.languageFilterOptions.addEventListener(FilterOptions.CHANGE_EVENT, () => this.sendLangSelections(true)));

    // Update array when filter options are loaded from URL parameters
    arr.push(this.languageFilterOptions.addEventListener(FilterOptions.URL_LOAD_EVENT, () => this.sendLangSelections(true)));

    // Clean up after component is no longer used
    this.addEventListener('ngOnDestroy', function ()
    
        arr.forEach(s => s()); // Remove all listeners
        return true;
    .bind(this));



/**
* Handles the emitting of the selected values to the API
*/
private sendLangSelections(languageFilterOptions) 
    const origLangArray = ['English', 'Spanish', 'Mandarin'];
    if (languageFilterOptions)
        
            let selectionsArray = this.languageFilterOptions.selection;
            let values = selectionsArray.map((a) =>  return a.value; );
            if (values && values.length > 0)
                
                    this.sendLanguage.emit(values);
                
            else if (values && values.length < 1)
                
                    this.sendLanguage.emit(origLangArray);
                
        

这就是我对 Mongo/Mongoose/Node 后端的 API 调用:

// A POST request to work with observables
public obsPost(strReq, page, pagesize, body, sort?) 
    const headers = new Headers( 'Content-Type': 'application/json' );
    const options = new RequestOptions( headers: this.headers );
    return this.http.post
    (`$API.URL/$API.VER$strReq?apikey=$API.KEY&page=$page&pagesize=$pagesize`,
    body, options)
        .map((res: Response) => res.json())
        .catch(this.filterErrorHandler);

    filterErrorHandler(error: Response) 
    console.error(error);
    return Observable.throw(error.json().error || 'Server error');

【问题讨论】:

【参考方案1】:

要完成这项工作,需要在通过 $in: value 传递值时添加更多条件逻辑。由于弹出的错误是因为 $in: value 的格式问题,关键是要确保只有在有要传递的值时才会触发。

所以,最后,为了让它工作 - 不必传入所有可能值的数组,这不是一个优雅或高性能的解决方案 - 我改变了这个:

private processType(name: string, value: any, body)

    if (this.body[name] && !value) 
            delete this.body[name];
         else 
            this.body[name] =  $in: value ;
        

...到这个:

private processType(name: string, value: any, body)

    if (this.body[name] && !value || this.body[name] && value.length < 1) 
            delete this.body[name];
         else if (value) 
            this.body[name] =  $in: value ;
        

这基本上是确保在触发 $in: value 时至少有一个值的数组可用。

唯一需要的其他更改是涉及当用户取消选择所有值时发出的内容。我是这样处理的:

private sendLangSelections(languageFilterOptions) 
    const origLangArray = ['English', 'Spanish', 'Mandarin'];
    if (languageFilterOptions)
        
            let selectionsArray = this.languageFilterOptions.selection;
            let values = selectionsArray.map((a) =>  return a.value; );
            if (values && values.length > 0)
                
                    this.sendLanguage.emit(values);
                
            else if (values && values.length < 1)
                
                    this.sendLanguage.emit(this.obj = undefined);
                
        

【讨论】:

以上是关于在 Angular 应用程序中处理过滤值的更优雅的方式的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript 复杂判断的更优雅写法

在 Angular 应用程序的 API 调用中处理发送两个参数

在 Java 6 中等待方法结果(超时)的更优雅的方式

处理空值的最优雅方法是啥

在环绕的一维数组网格中寻找邻居的更优雅的方法?

从逗号 sep 属性列表创建数组的更优雅的解决方案?