【问题标题】:How can I use a dropdown in my angular2 form to submit an object如何在我的 angular2 表单中使用下拉列表来提交对象
【发布时间】:2016-06-09 23:43:46
【问题描述】:

我有一个应用程序,其中包含包含文章的主题。当用户创建一篇文章时,我希望他们从显示可用主题的下拉列表中选择一个主题以将文章与之关联。这个 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> 

当我尝试验证我是否收到了我正在寻找的数据时,我收到此行的“未定义”错误:

console.log(this.myForm.value.topic.title);

如果我这样做,我会得到 [object, object]

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)
        );

}


}

【问题讨论】:

    标签: node.js forms mongodb drop-down-menu angular


    【解决方案1】:

    因此,对此的答案是不要将 myForm 元素与 ngFormControl 一起用于对象/表单字段,这些对象/表单字段将引用应用程序中的其他对象。相反,需要做的事情如下。

    1. 创建主题、主题和选定主题

      topics: Topic[];
      topic = '';
      selectedTopic = ''; 
      
    2. 将带有选项标签的选择标签添加到表单中,以便用户能够通过将 ngModel 绑定到“主题”来选择他们想要的主题

      <select [ngModel]="topic" (ngModelChange)="onChange($event)">
         <option [ngValue]="i" *ngFor="let i of topics">{{i.title}}</option>
      </select>
      
    3. 创建一个 onChange 方法,该方法将根据用户在表单中选择主题来更新 this.selectedTopic

      onChange(newValue) {
        this.selectedTopic = newValue;
        console.log(this.selectedTopic);
        console.log(this.selectedTopic.topicId);
      }
      
    4. 然后在 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
                });
            });
        });
    });
    

    我希望这可以帮助与我遇到同样问题的其他人。

    【讨论】:

      猜你喜欢
      • 2018-06-09
      • 1970-01-01
      • 2014-08-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-12-17
      相关资源
      最近更新 更多