我的应用程序将包含包含文章的主题。当用户创建文章时,我希望他们选择一个主题来将文章与显示可用主题的下拉列表相关联。 UI方面为用户提供了一个当前看起来正确的表单,但是,主题对象没有与表单一起传递,我无法理解为什么。有人可以帮我理解应该怎么做?
以下相关部分如下: 这是我表单中的select语句,它正确显示了我想要呈现给用户的主题的选项。
<select [ngFormControl]="myForm.find('topic')" id="topic" class="form-control" required>
<option *ngFor="let a of topics" [value]="a">{{a.title}}</option>
</select>
当我尝试验证我收到的数据时,我正在寻找一个未定义的&#39;这一行出错:
console.log(this.myForm.value.topic.title);
如果我这样做,我得到[对象,对象]
console.log(this.myForm.value.topic);
提交给服务的内容是:
Object { content: "8th content", title: "8th title", articleId: "57588eaf1ac787521d15ac34", username: "Jason", userId: Object, topicId: undefined }
有人可以帮助我理解我在这里失踪的能够将此表格选择标签的结果发送到我的Angular2表单吗?
我的整篇文章-input.component.ts文件
import { Component, OnInit } from '@angular/core';
import {Article} from './article';
import {ArticleService} from "./article.service";
import {ErrorService} from "../errors/error.service";
import { FormBuilder, ControlGroup, Validators, Control } from '@angular/common';
import {TopicService} from "../topics/topic.service";
import {Topic} from "../topics/topic";
@Component({
selector: 'my-article-input',
template: `
<section class="col-md-8 col-md-offset-2">
<form [ngFormModel]="myForm" (ngSubmit)="onSubmit()">
<div class="form-group">
<label for="title">Title</label>
<input [ngFormControl]="myForm.find('title')" type="text" id="title" class="form-control" #input [value]="article?.title">
</div>
<div class="form-group">
<label for="content">Content</label>
<input [ngFormControl]="myForm.find('content')" type="text" id="content" class="form-control" #input [value]="article?.content">
</div>
<select [ngFormControl]="myForm.find('topic')" id="topic" class="form-control" required>
<option *ngFor="let a of topics" [value]="a">{{a.title}}</option>
</select>
<button type="submit" class="btn btn-primary" [disabled]="!myForm.valid">{{ !article ? 'Add Article' : 'Save Article' }}</button>
<button type="button" class="btn btn-danger" (click)="onCancel()" *ngIf="article">Cancel</button>
</form>
</section>
`
})
export class ArticleInputComponent implements OnInit {
myForm: ControlGroup;
article: Article = null;
constructor(private _fb:FormBuilder, private _articleService: ArticleService, private _errorService: ErrorService, private _topicService: TopicService ) {}
topics: Topic[];
onSubmit() {
console.log(this.myForm.value.topic.title);
if (this.article) {
// Edit
this.article.content = this.myForm.value.content;
this.article.title = this.myForm.value.title;
this.article.topicId = this.myForm.value.topic.topicId;
this._articleService.updateArticle(this.article)
.subscribe(
data => console.log(data),
error => this._errorService.handleError(error)
);
this.article = null;
} else {
const article: Article = new Article(this.myForm.value.content, this.myForm.value.title, null, 'DummyArticleInput', this.myForm.value.topic);
this._articleService.addArticle(article)
.subscribe(
data => {
console.log(data);
this._articleService.articles.push(data);
},
error => this._errorService.handleError(error)
);
}
}
onCancel() {
this.article = null;
}
ngOnInit() {
this.myForm = this._fb.group({
title: ['', Validators.required],
content: ['', Validators.required],
topic: ['', Validators.required]
});
this._articleService.articleIsEdit.subscribe(
article => {
this.article = article;
}
);
this._topicService.getTopics().subscribe(
topics => {
this.topics = topics;
this._topicService.topics = topics
},
error => this._errorService.handleError(error)
);
}
}
答案 0 :(得分:0)
所以答案是不要将myForm元素和ngFormControl用于对象/表单字段,这些对象/表单字段将引用应用程序中的其他对象。相反,需要做的事情如下。
创建主题,主题和selectedTopic
topics: Topic[];
topic = '';
selectedTopic = '';
向表单添加带有选项标记的select标记,以便用户能够通过将ngModel绑定到“topic”来选择他们想要的主题
<select [ngModel]="topic" (ngModelChange)="onChange($event)">
<option [ngValue]="i" *ngFor="let i of topics">{{i.title}}</option>
</select>
创建一个onChange方法,根据用户选择表单中的主题来更新this.selectedTopic
onChange(newValue) {
this.selectedTopic = newValue;
console.log(this.selectedTopic);
console.log(this.selectedTopic.topicId);
}
然后在onSubmit方法中使用myForm.value来获取来自实际表单的信息,并使用this.selectedTopic上的数据绑定来选择正在选择的主题
onSubmit() {
if (this.article) {
// Edit
this.article.content = this.myForm.value.content;
this.article.title = this.myForm.value.title;
this.article.topicId = this.selectedTopic;
this._articleService.updateArticle(this.article)
.subscribe(
data => console.log(data),
error => this._errorService.handleError(error)
);
this.article = null;
} else {
const article: Article = new Article(this.myForm.value.content, this.myForm.value.title, null, 'dummyUserName', 'dummyUserId', this.selectedTopic.topicId);
this._articleService.addArticle(article)
.subscribe(
data => {
// console.log('what comes back from addArticle is: ' + JSON.stringify(data));
this._articleService.articles.push(data);
},
error => this._errorService.handleError(error)
);
}
从我们开始的地方开始,我们现在已经到了一切可以工作的地方,并且创建的对象看起来像这样:
{ "_id" : ObjectId("5758c2e173fd33e04092c87e"), "content" : "c66", "title" : "t66", "user" : ObjectId("5755e5be96162f52a4f01dd8"), "topic" : ObjectId("57572d92e802307d199f0afa"), "__v" : 0 }
作为参考,整个(工作)article-input.component.ts文件如下所示:
import { Component, OnInit } from '@angular/core';
import {Article} from './article';
import {ArticleService} from "./article.service";
import {ErrorService} from "../errors/error.service";
import { FormBuilder, ControlGroup, Validators, Control } from '@angular/common';
import {TopicService} from "../topics/topic.service";
import {Topic} from "../topics/topic";
@Component({
selector: 'my-article-input',
template: `
<section class="col-md-8 col-md-offset-2">
<form [ngFormModel]="myForm" (ngSubmit)="onSubmit()">
<div class="form-group">
<label for="title">Title</label>
<input [ngFormControl]="myForm.find('title')" type="text" id="title" class="form-control" #input [value]="article?.title">
</div>
<div class="form-group">
<label for="content">Content</label>
<input [ngFormControl]="myForm.find('content')" type="text" id="content" class="form-control" #input [value]="article?.content">
</div>
<select [ngModel]="topic" (ngModelChange)="onChange($event)">
<option [ngValue]="i" *ngFor="let i of topics">{{i.title}}</option>
</select>
<button type="submit" class="btn btn-primary" >{{ !article ? 'Add Article' : 'Save Article' }}</button>
<button type="button" class="btn btn-danger" (click)="onCancel()" *ngIf="article">Cancel</button>
</form>
</section>
`
})
export class ArticleInputComponent implements OnInit {
myForm: ControlGroup;
article: Article = null;
constructor(private _fb:FormBuilder, private _articleService: ArticleService, private _errorService: ErrorService, private _topicService: TopicService ) {}
topics: Topic[];
topic = '';
selectedTopic = '';
onChange(newValue) {
this.selectedTopic = newValue;
console.log(this.selectedTopic);
console.log(this.selectedTopic.topicId);
}
onSubmit() {
if (this.article) {
// Edit
this.article.content = this.myForm.value.content;
this.article.title = this.myForm.value.title;
this.article.topicId = this.selectedTopic;
this._articleService.updateArticle(this.article)
.subscribe(
data => console.log(data),
error => this._errorService.handleError(error)
);
this.article = null;
} else {
const article: Article = new Article(this.myForm.value.content, this.myForm.value.title, null, 'dummyUserName', 'dummyUserId', this.selectedTopic.topicId);
this._articleService.addArticle(article)
.subscribe(
data => {
// console.log('what comes back from addArticle is: ' + JSON.stringify(data));
this._articleService.articles.push(data);
},
error => this._errorService.handleError(error)
);
}
}
onCancel() {
this.article = null;
}
ngOnInit() {
this.myForm = this._fb.group({
title: ['', Validators.required],
content: ['', Validators.required],
topic: ['', Validators.required]
});
this._articleService.articleIsEdit.subscribe(
article => {
this.article = article;
}
);
this._topicService.getTopics().subscribe(
topics => {
this.topics = topics;
this._topicService.topics = topics
},
error => this._errorService.handleError(error)
);
}
}
我的topic.ts角度模型看起来像这样:
export class Topic {
description: string;
title: string;
username: string;
topicId: string;
userId: string;
constructor (description: string, title: string, topicId?: string, username?: string, userId?: string) {
this.description = description;
this.title = title;
this.topicId = topicId;
this.username = username;
this.userId = userId;
}
}
article.service.ts看起来像这样:
addArticle(article: Article) {
const body = JSON.stringify(article);
console.log(body);
const headers = new Headers({'Content-Type': 'application/json'});
const token = localStorage.getItem('token') ? '?token=' + localStorage.getItem('token') : '';
return this._http.post('http://localhost:3000/article' + token, body, {headers: headers})
.map(response => {
const data = response.json().obj;
let article = new Article(data.content, data.title, data._id, data.user.firstName, data.user, data.topicId);
return article;
})
.catch(error => Observable.throw(error.json()));
}
在Node的后端我的article.js看起来像这样:
router.post('/', function(req, res, next) {
var decoded = jwt.decode(req.query.token);
User.findById(decoded.user._id, function(err, doc) {
if (err) {
return res.status(401).json({
title: 'An Error occured',
error: err
});
}
var article = new Article({
content: req.body.content,
title: req.body.title,
user: doc,
topic: req.body.topicId
});
console.log(req.body);
article.save(function(err, result){
if (err) {
return res.status(404).json({
title: 'An Error occured',
error: err
});
}
doc.articles.push(result);
doc.save();
res.status(201).json({
article: 'Saved Article',
obj: result
});
});
});
});
我希望这可以帮助那些遇到与我相同问题的人。