填充选项卡 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>
好的,所以我是 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>