过滤从 Web 服务获取的 json 数组以仅包含某些元素 - Angular

Filtering a json array obtained from a web service to only contain certain elements - Angular

我正在创建一个项目,它使用从 Web 服务获取的 HTTP 和 returns 一组项目,包括 ID、名称、描述等。

此 Web 服务中有许多项目,但我只关心其中的 9 个,其余的无关紧要。

我有一组所需的 9 个项目,它们在 project.service.http.ts class 中声明了我只想显示的唯一 ID。

我正在尝试过滤 HTTP get 请求以仅包含 9 个特定 ID,我将其存储在字符串类型的 projectIds 数组中。

编辑2: 通过记录响应:

编辑已解决: 我更改了 project.viewer.component 中的构造函数:

 constructor(private service: ProjectService) {
        this.service.fetchProjects().subscribe(response => {
          this.projects = response.filter(elements => {
            // BaseComponent was my class. Use yours.
            return ProjectViewerComponent.projectIds.includes(elements.id);
          });
        })
      }

至:

 constructor(private service: ProjectService) {
        this.service.fetchProjects().subscribe(response => {
          this.projects = response['project'].filter(elements => {
            // BaseComponent was my class. Use yours.
            return ProjectViewerComponent.projectIds.includes(elements.id);
          });
        })
      }

关键是 this.projects = response

之后的 ['project']

project.service.http.ts:

@Injectable()
export class ProjectServiceHttp extends ProjectService {

    //variables
    baseUrl = "http://...";

        static projectIds: string[] = ["..."
                                ,"...", "..","..."];

        //constructor
       constructor(private http: Http) {
            super();
        }

    //methods
    fetchProjects(): Observable<any>{
        let headers = new Headers({'Content-Type': 'application/json'});
        let options = new RequestOptions({headers: headers});
        return this.http.get(this.baseUrl, options)
          .map((response: Response) => response.json())
          .catch(this.handleError);
      }

        private handleError(error: any) {
            // In a real world app, we might use a remote logging infrastructure
            // We'd also dig deeper into the error to get a better message
            let errMsg = (error.message) ? error.message :
                error.status ? `${error.status} - ${error.statusText}` : 'Server error';
            console.log(errMsg); // log to console instead
            return Observable.throw(errMsg);
        }
}

project.viewer.component.ts:

@Component({
    selector: 'project-viewer',
    templateUrl: './project-viewer.html',  
    styleUrls: ['./project-viewer.css']
})


export class ProjectViewerComponent  {
    name = 'ProjectViewerComponent';
    projects: Project[] = [];

    static testIds: string[] = ['qqq', 'aaa'];

    static projectIds: string[] = ["...","..."
    ,"..","..","...","..."
    ,"..", "...","..."];

    errorMessage = "";
    stateValid = true;

      constructor(private service: ProjectService) {
        this.service.fetchProjects().subscribe(response => {
          this.projects = response.filter(elements => {
            return ProjectViewerComponent.projectIds.includes(elements.id);
          });
        })
      }

    private raiseError(text: string): void {
        this.stateValid = false;
        this.errorMessage = text;
    }
}

项目-viewer.html:

<h3>Projects </h3>
<div >
    <ul class= "grid grid-pad">
        <a *ngFor="let project of projects" class="col-1-4">
            <li class ="module project" >
                <h4 tabindex ="0">{{project.name}}</h4>
            </li>
        </a>
    </ul>
</div>

您服务中的方法 fetchProjects() 可以在另一个组件中重复使用。所以您可能希望它 return 所有项目,因为这是此方法的目的。获取所有项目。

第一种方法(推荐):

最好的办法是过滤从 HTTP 调用的 return 中获得的数据。

那样的话,您需要过滤从服务中获取的数据,以便仅在该组件中显示您想要的内容。

project.viewer.component.ts :

.subscribe(response =>{
  this.projects = response.project.
    .filter(elements => someCondition);
  console.log(response);
  console.log(this.projects);
},

第二种方法(不推荐):

您唯一希望使用 .map() 方法来更改从服务调用中获取的数据的情况是当您确定永远不需要所有项目,而只需要这些项目时那些。当然,您可以执行另一个函数来调用相同的 URL 而不是过滤该数据,但是您将不得不维护两个方法来执行基本相同的调用。这就是为什么最好在组件中而不是在服务中过滤数据。

尽管如此,您需要在服务中更改此部分:

project.service.http.ts : (顺便说一句,应该叫 project.service.ts

.map((response: Response) => {
  const results = response.json();
  return = results.filter(elements => someCondition);
})

编辑: 这是使用您的 class 对象和我自己的模拟数据的工作解决方案:

project.service.http.ts : 初始一个,不要用.filter()

fetchProjects(): Observable<any>{
  const headers = new Headers({'Content-Type': 'application/json'});
  const options = new RequestOptions({headers: headers});
  return this.http.get(this.baseUrl, options)
    .map((response: Response) => response.json())
    .catch(this.handleError);
}

project.viewer.component.ts :

你需要稍微调整一下,因为我使用了你的一些代码来做一个快速示例(我的项目 ID 是 'qqq''aaa')。

  static projectIds: string[] = ['yourIds', 'YourIds2', ...];

  projects: Project[] = [];

  constructor(private service: ProjectService) {
    this.service.fetchProjects().subscribe(response => {
      this.projects = response.filter(element => BaseComponent.projectIds.includes(element.id)); // BaseComponent was my class. Use yours.
    })
  }

项目-viewer.html : 不变。

在我的示例中,我的服务向我发送了 4 个项目,我过滤了其中的 2 个以仅显示 2 个。效果很好,如果您在适应您的代码时遇到任何问题,请告诉我。

如您所见,这就是我首先提到的第一种方法的应用。由于第二种方法中所述的原因,也不要将此应用于服务。

您可以使用 pipe 根据您的条件过滤那些项目(仅通过那些 'unique ids'),然后将它们应用到您的 *ngFor 模板中,如下所示,

<a *ngFor="let project of projects | uniqueOnes" class="col-1-4">

像这样定义管道,

@Pipe({
  name: 'uniqueOnes'
})
export class UniqueOnesPipe implements PipeTransform {
  uniqueIds = [ 'id1', 'id2', 'id5'];

  transform(value: any): any {
    return value
            ? value.filter(project => { return <condition to pass only the unique projects (For ex: this.uniqueIds.indexOf(project.id) !== -1)>  })
            : value;
  }

}

有关管道的更多信息 here