填充选项卡 table

Populating a tabbed table

好的,所以我是 Angular 的新手,不到一周左右的时间,由于开发文档,我设法构建了这个应用程序的大部分内容。

我正在尝试为职位空缺填充一个选项卡 table,点击标题相应地更改描述(例如此处 https://www.w3schools.com/w3css/tryit.asp?filename=tryw3css_tabulators_animate)。我得到的选项卡在静态代码中运行得很好,但现在试图从 mongodb 中提取,它只显示 "posts" collection 中的一个条目,尽管整个数组objects 确实出现在控制台中。

我似乎无法弄清楚我做错了什么。

我的home.component.html:

    <div class="content" *ngFor="let post of posts">
      <div class="row">
        <div class="container">
          <div class="col-md-12 open">
            <h3>Open Positions:</h3>
          </div>
        </div>
      </div>
      <div class="example-loading-shade" *ngIf="isLoadingResults">
        <mat-spinner *ngIf="isLoadingResults"></mat-spinner>
      </div>
      <div class="row" [routerLink]="['/post']" >
        <div class="col-md-3" id="jobNames" data="this.posts">
          <div class="w3-bar w3-black">
            <button class="w3-bar-item w3-button tablink" onclick='openLink(event, post._id)'>{{post.postTitle}}</button>
          </div>
        </div>
        <div class="col-md-9" id="jobContainer">
          <div class="job w3-container w3-animate-opacity" id="post._id">
            <h3 class="jobSections">Date Posted: {{post.updated | date: 'dd MMM yyyy'}}</h3>
            <p [innerHTML]="post.postContent"></p>
          </div>
        </div>
      </div>

Post.js:

    var mongoose = require('mongoose'), Schema = mongoose.Schema;

var PostSchema = new mongoose.Schema({
  category : { type: Schema.Types.ObjectId, ref: 'Category' },
  id: String,
  postTitle: String,
  postAuthor: String,
  postContent: String,
  postReference: String,
  created: { type: Date },
  updated: { type: Date, default: Date.now },
});

module.exports = mongoose.model('Post', PostSchema);

home.component.ts

import { Component, OnInit } from '@angular/core';
import { Post } from '../post/post';
import { PostService } from '../post.service';
import { HomeService } from '../home.service';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.scss']
})
export class HomeComponent implements OnInit {
  post: Post = {
    category: '',
    id: '',
    postTitle: '',
    postAuthor: '',
    postContent: '',
    postReference: '',
    created: null,
    updated: null
  };
  posts: Post[] = [];
  isLoadingResults = true;

  constructor(private api: HomeService) { }

  ngOnInit() {
    this.api.getPosts()
      .subscribe((res: any) => {
        this.posts = res;
        console.log(this.posts);
        this.isLoadingResults = false;
      }, err => {
        console.log(err);
        this.isLoadingResults = false;
      });
  }

}

jobs.js

function openLink(evt, animName) {
  var i, x, tablinks;
  x = document.getElementsByClassName("job");
  for (i = 0; i < x.length; i++) {
    x[i].style.display = "none";
  }
  tablinks = document.getElementsByClassName("tablink");
  for (i = 0; i < x.length; i++) {
    tablinks[i].className = tablinks[i].className.replace(" w3-red", "");
  }
  document.getElementById(animName).style.display = "block";
  evt.currentTarget.className += " w3-red";
}

home.service.ts

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable, of } from 'rxjs';
import { catchError, tap } from 'rxjs/operators';
import { Category } from './category/category';
import { Post } from './post/post';

const apiUrl = 'http://localhost:3000/api/public/';

@Injectable({
  providedIn: 'root'
})
export class HomeService {

  constructor(private http: HttpClient) { }

  getCategories(): Observable<Category[]> {
    return this.http.get<Category[]>(apiUrl + 'category')
      .pipe(
        tap(_ => this.log('fetched Categories')),
        catchError(this.handleError('getCategories', []))
      );
  }

  getPosts(): Observable<Post[]> {
    return this.http.get<Post[]>(apiUrl + 'post')
      .pipe(
        tap(_ => this.log('fetched Posts')),
        catchError(this.handleError('getPosts', []))
      );
  }

  getPostsByCategory(id: any): Observable<Post[]> {
    return this.http.get<Post[]>(apiUrl + 'bycategory/' + id)
      .pipe(
        tap(_ => this.log('fetched Posts')),
        catchError(this.handleError('getPosts', []))
      );
  }

  getPost(id: any): Observable<Post> {
    return this.http.get<Post>(apiUrl + 'post/' + id).pipe(
      tap(_ => console.log(`fetched post by id=${id}`)),
      catchError(this.handleError<Post>(`getPost id=${id}`))
    );
  }

  private handleError<T>(operation = 'operation', result?: T) {
    return (error: any): Observable<T> => {

      console.error(error); // log to console instead
      this.log(`${operation} failed: ${error.message}`);

      return of(result as T);
    };
  }

  private log(message: string) {
    console.log(message);
  }
}

我不知道你的 HomeService 是如何设计的,但是...

我好的解决方案是在您的服务中创建一个方法 getPosts,其参数类似于 section o tab name,您可以使用它来过滤数据

然后你就可以在HomeComponent上轻松使用了

ngOnInit() {
  this.loadPosts('jobs'); // use first tab for default on load component
}

loadPosts(tabName) {
   this.api.getPosts(tanName)
      .subscribe((res: any) => {
        this.posts = res;
        console.log(this.posts);
        this.isLoadingResults = false;
      }, err => {
        console.log(err);
        this.isLoadingResults = false;
      });
}

然后你可以点击使用它

openLink(evt, animName) {
  /* your code */
  evt.currentTarget.className += " w3-red";
  let tabName = evt,currentTarget.innerText.trim() // trim(), maybe forget spaces  
  this.loadPosts(tabName);
}

如果您必须不带参数,可以使用管道过滤器或为所有数据设置一个变量,为过滤后的数据设置另一个变量,然后单击即可更改过滤后的数据

ngOnInit() {
    this.api.getPosts()
      .subscribe((res: any) => {
        this.allPosts = res;      // <----- all post in a variable
        console.log(this.posts);
        this.isLoadingResults = false;
      }, err => {
        console.log(err);
        this.isLoadingResults = false;
      });
}

openLink(evt, animName) {
  /* your code */
  evt.currentTarget.className += " w3-red";
  let tabName = evt,currentTarget.innerText.trim() // trim(), maybe forget spaces
  this.posts = this.allPosts.filter(post=> post.tabName == 'tabName');
}

编辑

如果您选择第一个选项 最好的方法是在通过 api 请求接收 tabName 参数时在服务器上进行过滤 然后在服务器端创造奇迹

export class HomeService {

  constructor(private http: HttpClient) { } 

  getPosts(tabName: string): Observable<Post[]> {
    return this.http.get<Post[]>(apiUrl + 'post?tabName='+tabName)
      .pipe(
        tap(_ => this.log('fetched Posts')),
        catchError(this.handleError('getPosts', []))
      );
  } 
}

我知道了,以防其他人正在寻找类似的东西

home.component.ts :

import { Component, OnInit } from '@angular/core';
import { Post } from '../post/post';
import { PostService } from '../post.service';
import { HomeService } from '../home.service';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.scss']
})
export class HomeComponent implements OnInit {
  post: Post = {
    category: '',
    id: '',
    postTitle: '',
    postAuthor: '',
    postContent: '',
    postReference: '',
    created: null,
    updated: null
  };
  posts: Post[] = [];
  isLoadingResults = true;
  selectedPost: Post = null;

  constructor(private api: HomeService) { }

  openLink(evt, animName) {
    var i, x, tablinks;
    x = document.getElementsByClassName("job");
    for (i = 0; i < x.length; i++) {
      x[i].style.display = "none";
    }
    tablinks = document.getElementsByClassName("tablink");
    for (i = 0; i < x.length; i++) {
      tablinks[i].className = tablinks[i].className.replace(" w3-red", "");
    }
    document.getElementById(animName).style.display = "block";
    evt.currentTarget.className += " w3-red";
  }

  selectPost(post) {
    this.selectedPost = post;
    console.log(this.selectedPost);
  }

  ngOnInit() {
    this.api.getPosts()
      .subscribe((res: any) => {
        this.posts = res;
        console.log(this.posts);
        this.isLoadingResults = false;
      }, err => {
        console.log(err);
        this.isLoadingResults = false;
      }
    );
  }

}

home.component.html

<div class="col-md-12 open">
        <h3>Open Positions:</h3>
      </div>
      <div class="example-loading-shade" *ngIf="isLoadingResults">
        <mat-spinner *ngIf="isLoadingResults"></mat-spinner>
      </div>
      <div class="row">
        <div class="col-md-2" id="jobNames">
          <div class="w3-bar w3-black">
            <button class="w3-bar-item w3-button tablink" *ngFor="let post of posts"
              (click)="selectPost(post)">{{post.postTitle}}</button>
          </div>
        </div>
        <div class="col-md-10" id="jobContainer">
          <div class="job w3-container w3-animate-opacity" id="{{selectedPost.postTitle}}">
            <h3 class="jobSections">Date Posted: {{selectedPost.updated | date: 'dd MMM yyyy'}}</h3>
            <p innerHTML={{selectedPost.postContent}}></p>
          </div>
        </div>
      </div>