最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Angular 2 Passing form data to another component - Stack Overflow

programmeradmin0浏览0评论

I have a form which allows user to create an account, once the user clicks on submit button the user is navigated to another page with the details of that account they have create. The issue I am having is passing that object to the details view.

For example here is my ponent for the form,

import {Component, OnInit, OnDestroy, Input} from '@angular/core';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
import {Customer} from "../model/customer";
import {Router } from '@angular/router';
import {CustomerService} from "../service/customer.service";
import {CustomerProfileComponent} from "../customer-profile/customer-profileponent";

@Component({
  selector: 'app-new-customer',
  templateUrl: './new-customerponent.html',
  styleUrls: ['./new-customerponent.css']
})
export class NewCustomerComponent implements OnInit {

  @Input() customer: Customer;

  //this is only dev data do not use this in prod
  private countries = [];
  private customerSources = [];
  private secondarySources =[];

  //Create the forum group
  public newCustomerForm: FormGroup;
  public submitted: boolean; // keep track on whether form is submitted

  constructor(private fb: FormBuilder, public customerService: CustomerService,private router: Router) {

    this.countries = [
      {value:'UK'},
      {value:'Germany'},
      {value:'Turkey'},
      {value:'Italy'}
      ];

    this.customerSources = [
      {value: 'Through a friend or colleague (not a Client)'},
      {value: 'Through an existing Client'},
      {value: 'Direct Sales (e.g. cold call, direct mail, email)'},
      {value: 'Web Search e.g. Google'}
    ];

    this.secondarySources = [
      {value: '1st Hire'},
      {value: 'A Test Client With A Long Business Name'},
      {value: 'Abbigail West'}
    ];
  }

  ngOnInit() {
    this.newCustomerForm = this.fb.group({
      id:[''],
      pany_name: ['', [<any>Validators.required, <any>Validators.minLength(5)]],
      vat:[''],
      address:[''],
      country:[''],
      first_name:[''],
      surname:[''],
      phone:[''],
      email:['',[<any>Validators.required, <any>Validators.minLength(5)]],
      customer_sources:[''],
      secondary_sources:['']
    });
  }

here is my form html,

 <form [formGroup]="newCustomerForm" novalidate (ngSubmit)="saveNewCustomer(newCustomerForm.value, newCustomerForm.valid)">
    <section>
      <aside>
        <p>Once you've added your new <b>Client</b>, you can e back and allow them access to view their <b>Invoices</b> &amp; <b>Payments</b> - they can also make <b>Payments</b> via Paypal if you have it enabled.</p>
      </aside>


      <input type="hidden" name="id"  formControlName="id"/>

      <h4>New Client Details</h4>
      <md-input-container>
        <input mdInput type="text" name="pany_name" placeholder="Customer Name" formControlName="pany_name" />
        <small [hidden]="newCustomerForm.controlspany_name.valid || (newCustomerForm.controlspany_name.pristine && !submitted)">
          Customer Name is required (minimum 5 characters).
        </small>
      </md-input-container>

      <md-input-container>
        <input mdInput type="text" name="vat"  placeholder="VAT Number" formControlName="vat"/>
      </md-input-container>

      <md-input-container>
        <input mdInput type="text" name="address"  placeholder="Address" formControlName="address" />
      </md-input-container>

      <md-select placeholder="Country" name="country" formControlName="country" >
        <md-option *ngFor="let country of countries" [value]="country.value" >
          {{country.value}}
        </md-option>
      </md-select>

      <h4>Your Primary Contact</h4>
      <div class="left-column">
        <md-input-container>
          <input mdInput type="text" name="first_name"  placeholder="First Name" formControlName="first_name" />
        </md-input-container>
      </div>

      <div class="left-column">
        <md-input-container>
          <input mdInput type="text" name="surname"  placeholder="surname" formControlName="surname" />
        </md-input-container>
      </div>

      <div class="clearfix"></div>

      <div class="left-column">
        <div class="left-column">
          <md-input-container>
            <input mdInput type="text" name="phone"  placeholder="Phone" formControlName="phone"/>
          </md-input-container>
        </div>
      </div>

      <div class="right-column">
        <div class="left-column">
          <md-input-container>
            <input mdInput type="text" name="email"  placeholder="Email" formControlName="email"/>
            <small [hidden]="newCustomerForm.controls.email.valid || (newCustomerForm.controls.email.pristine && !submitted)">
              Email is required (minimum 5 characters).
            </small>
          </md-input-container>
        </div>
      </div>

      <div class="clearfix"></div>
      <h4>Customer Source</h4>
      <div class="left-column">
        <md-select placeholder="How were you introduced to this Client?" formControlName="customer_sources">
          <md-option *ngFor="let cs of customerSources" [value]="cs.value" >
            {{cs.value}}
          </md-option>
        </md-select>
      </div>

      <div class="right-column">
          <md-select placeholder="Which Client introduced you?" formControlName="secondary_sources">
            <md-option *ngFor="let ss of secondarySources" [value]="ss.value" >
              {{ss.value}}
            </md-option>
          </md-select>
      </div>
      <div class="clearfix"></div>
    </section>

    <aside>
      <div class="right-aside">
        <button type="submit" class="cancel">Cancel</button>
        <button type="submit" class="save">Save</button>
      </div>
      <div class="clearfix"></div>
    </aside>
    </form>

Customer service is in my app.module. Here I am saving the data and moving the user on to the new page.

  saveNewCustomer(customer: Customer, isValid: boolean){
    if(isValid){
      this.submitted = true; // set form submit to true
      this.customerService.saveNewCustomer(customer)
        .subscribe(
          res => this.customer,
          error => console.log(<any>error)
        );

      this.router.navigateByUrl('/earning/customers/profile');
    }
  }


} 

And this is the ponent I would like the customer object to use so it be present in the view.

import {Component, OnInit, Input} from '@angular/core';
import {Customer} from "../model/customer";
import {NewCustomerComponent} from "../new-customer/new-customerponent";

@Component({
  selector: 'app-customer-profile',
  templateUrl: './customer-profileponent.html',
  styleUrls: ['./customer-profileponent.css'],
  providers:[NewCustomerComponent]
})
export class CustomerProfileComponent implements OnInit {

 @Input() customer: Customer;

  constructor() {
    console.log(this.customer);
  }

  ngOnInit() {
  }

}

<main>
  <header>
    <h4>&nbsp;</h4>
    <h1><strong><i></i>Customer profile</strong></h1>
    </header>
  <article>
    <section>
      <p></p>

      <p>
        {{customer}}
      </p>
      </section>
    </article>
  </main>

But customer is undefined in the CustomerProfileComponent. I am not sure what I am doing wrong. if anyone can point me in the right direction would be much appreciated.

Update to include service class based on suggestion

import { Injectable } from '@angular/core';
import {Http, Response, Headers, RequestOptions} from '@angular/http';
import {CookieService} from "angular2-cookie/services/cookies.service";

import {Observable, Subject} from "rxjs";
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import {Customer} from "../model/customer";


@Injectable()
export class CustomerService {

  private csrfToken;
  private newCustomerUrl = "/earning/customers/new";
  private customer = new Subject<Object>();

  customer$ = this.customer.asObservable();

  constructor(public http: Http, private cookieService: CookieService) {
    this.getCsrfToken();
  }

  getCsrfToken(){
    this.csrfToken = this.cookieService.get("PLAY_SESSION").substring(this.cookieService.get("PLAY_SESSION").indexOf("csrfToken"));
  }

  saveNewCustomer(customer:Customer): Observable<Customer>{

    let headers = new Headers({
      'Content-Type':'application/json'
    });

    let options = new RequestOptions({ headers: headers });

    return this.http.post(this.newCustomerUrl+"?"+this.csrfToken, customer, options) // ...using post request
      .map((res:Response) => res.json()) // ...and calling .json() on the response to return data
      .catch(this.handleError); //...errors if any
  }

  private handleError (error: Response) {
    return Observable.throw('Internal server error: ' + error);
  }

  emitCustomer(customer) {
    this.customer.next(customer);
  }


}

I have a form which allows user to create an account, once the user clicks on submit button the user is navigated to another page with the details of that account they have create. The issue I am having is passing that object to the details view.

For example here is my ponent for the form,

import {Component, OnInit, OnDestroy, Input} from '@angular/core';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
import {Customer} from "../model/customer";
import {Router } from '@angular/router';
import {CustomerService} from "../service/customer.service";
import {CustomerProfileComponent} from "../customer-profile/customer-profile.ponent";

@Component({
  selector: 'app-new-customer',
  templateUrl: './new-customer.ponent.html',
  styleUrls: ['./new-customer.ponent.css']
})
export class NewCustomerComponent implements OnInit {

  @Input() customer: Customer;

  //this is only dev data do not use this in prod
  private countries = [];
  private customerSources = [];
  private secondarySources =[];

  //Create the forum group
  public newCustomerForm: FormGroup;
  public submitted: boolean; // keep track on whether form is submitted

  constructor(private fb: FormBuilder, public customerService: CustomerService,private router: Router) {

    this.countries = [
      {value:'UK'},
      {value:'Germany'},
      {value:'Turkey'},
      {value:'Italy'}
      ];

    this.customerSources = [
      {value: 'Through a friend or colleague (not a Client)'},
      {value: 'Through an existing Client'},
      {value: 'Direct Sales (e.g. cold call, direct mail, email)'},
      {value: 'Web Search e.g. Google'}
    ];

    this.secondarySources = [
      {value: '1st Hire'},
      {value: 'A Test Client With A Long Business Name'},
      {value: 'Abbigail West'}
    ];
  }

  ngOnInit() {
    this.newCustomerForm = this.fb.group({
      id:[''],
      pany_name: ['', [<any>Validators.required, <any>Validators.minLength(5)]],
      vat:[''],
      address:[''],
      country:[''],
      first_name:[''],
      surname:[''],
      phone:[''],
      email:['',[<any>Validators.required, <any>Validators.minLength(5)]],
      customer_sources:[''],
      secondary_sources:['']
    });
  }

here is my form html,

 <form [formGroup]="newCustomerForm" novalidate (ngSubmit)="saveNewCustomer(newCustomerForm.value, newCustomerForm.valid)">
    <section>
      <aside>
        <p>Once you've added your new <b>Client</b>, you can e back and allow them access to view their <b>Invoices</b> &amp; <b>Payments</b> - they can also make <b>Payments</b> via Paypal if you have it enabled.</p>
      </aside>


      <input type="hidden" name="id"  formControlName="id"/>

      <h4>New Client Details</h4>
      <md-input-container>
        <input mdInput type="text" name="pany_name" placeholder="Customer Name" formControlName="pany_name" />
        <small [hidden]="newCustomerForm.controls.pany_name.valid || (newCustomerForm.controls.pany_name.pristine && !submitted)">
          Customer Name is required (minimum 5 characters).
        </small>
      </md-input-container>

      <md-input-container>
        <input mdInput type="text" name="vat"  placeholder="VAT Number" formControlName="vat"/>
      </md-input-container>

      <md-input-container>
        <input mdInput type="text" name="address"  placeholder="Address" formControlName="address" />
      </md-input-container>

      <md-select placeholder="Country" name="country" formControlName="country" >
        <md-option *ngFor="let country of countries" [value]="country.value" >
          {{country.value}}
        </md-option>
      </md-select>

      <h4>Your Primary Contact</h4>
      <div class="left-column">
        <md-input-container>
          <input mdInput type="text" name="first_name"  placeholder="First Name" formControlName="first_name" />
        </md-input-container>
      </div>

      <div class="left-column">
        <md-input-container>
          <input mdInput type="text" name="surname"  placeholder="surname" formControlName="surname" />
        </md-input-container>
      </div>

      <div class="clearfix"></div>

      <div class="left-column">
        <div class="left-column">
          <md-input-container>
            <input mdInput type="text" name="phone"  placeholder="Phone" formControlName="phone"/>
          </md-input-container>
        </div>
      </div>

      <div class="right-column">
        <div class="left-column">
          <md-input-container>
            <input mdInput type="text" name="email"  placeholder="Email" formControlName="email"/>
            <small [hidden]="newCustomerForm.controls.email.valid || (newCustomerForm.controls.email.pristine && !submitted)">
              Email is required (minimum 5 characters).
            </small>
          </md-input-container>
        </div>
      </div>

      <div class="clearfix"></div>
      <h4>Customer Source</h4>
      <div class="left-column">
        <md-select placeholder="How were you introduced to this Client?" formControlName="customer_sources">
          <md-option *ngFor="let cs of customerSources" [value]="cs.value" >
            {{cs.value}}
          </md-option>
        </md-select>
      </div>

      <div class="right-column">
          <md-select placeholder="Which Client introduced you?" formControlName="secondary_sources">
            <md-option *ngFor="let ss of secondarySources" [value]="ss.value" >
              {{ss.value}}
            </md-option>
          </md-select>
      </div>
      <div class="clearfix"></div>
    </section>

    <aside>
      <div class="right-aside">
        <button type="submit" class="cancel">Cancel</button>
        <button type="submit" class="save">Save</button>
      </div>
      <div class="clearfix"></div>
    </aside>
    </form>

Customer service is in my app.module. Here I am saving the data and moving the user on to the new page.

  saveNewCustomer(customer: Customer, isValid: boolean){
    if(isValid){
      this.submitted = true; // set form submit to true
      this.customerService.saveNewCustomer(customer)
        .subscribe(
          res => this.customer,
          error => console.log(<any>error)
        );

      this.router.navigateByUrl('/earning/customers/profile');
    }
  }


} 

And this is the ponent I would like the customer object to use so it be present in the view.

import {Component, OnInit, Input} from '@angular/core';
import {Customer} from "../model/customer";
import {NewCustomerComponent} from "../new-customer/new-customer.ponent";

@Component({
  selector: 'app-customer-profile',
  templateUrl: './customer-profile.ponent.html',
  styleUrls: ['./customer-profile.ponent.css'],
  providers:[NewCustomerComponent]
})
export class CustomerProfileComponent implements OnInit {

 @Input() customer: Customer;

  constructor() {
    console.log(this.customer);
  }

  ngOnInit() {
  }

}

<main>
  <header>
    <h4>&nbsp;</h4>
    <h1><strong><i></i>Customer profile</strong></h1>
    </header>
  <article>
    <section>
      <p></p>

      <p>
        {{customer}}
      </p>
      </section>
    </article>
  </main>

But customer is undefined in the CustomerProfileComponent. I am not sure what I am doing wrong. if anyone can point me in the right direction would be much appreciated.

Update to include service class based on suggestion

import { Injectable } from '@angular/core';
import {Http, Response, Headers, RequestOptions} from '@angular/http';
import {CookieService} from "angular2-cookie/services/cookies.service";

import {Observable, Subject} from "rxjs";
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import {Customer} from "../model/customer";


@Injectable()
export class CustomerService {

  private csrfToken;
  private newCustomerUrl = "/earning/customers/new";
  private customer = new Subject<Object>();

  customer$ = this.customer.asObservable();

  constructor(public http: Http, private cookieService: CookieService) {
    this.getCsrfToken();
  }

  getCsrfToken(){
    this.csrfToken = this.cookieService.get("PLAY_SESSION").substring(this.cookieService.get("PLAY_SESSION").indexOf("csrfToken"));
  }

  saveNewCustomer(customer:Customer): Observable<Customer>{

    let headers = new Headers({
      'Content-Type':'application/json'
    });

    let options = new RequestOptions({ headers: headers });

    return this.http.post(this.newCustomerUrl+"?"+this.csrfToken, customer, options) // ...using post request
      .map((res:Response) => res.json()) // ...and calling .json() on the response to return data
      .catch(this.handleError); //...errors if any
  }

  private handleError (error: Response) {
    return Observable.throw('Internal server error: ' + error);
  }

  emitCustomer(customer) {
    this.customer.next(customer);
  }


}
Share Improve this question edited Mar 3, 2017 at 14:54 Limpep asked Mar 3, 2017 at 11:37 LimpepLimpep 4993 gold badges11 silver badges22 bronze badges 4
  • post the related template code – Avinash Raj Commented Mar 3, 2017 at 11:39
  • Either paste your html code, or set up a service which municates between ponents a shown here: angular.io/docs/ts/latest/cookbook/… – Code Ratchet Commented Mar 3, 2017 at 11:50
  • @AvinashRaj I have pasted in my html code. Thanks – Limpep Commented Mar 3, 2017 at 13:28
  • @CodeRatchetI have pasted in my html code. Thanks – Limpep Commented Mar 3, 2017 at 13:29
Add a ment  | 

1 Answer 1

Reset to default 3

As mentioned a shared service would be a good option. the following example is sharing the Object between the ponents via service:

Your service:

public sharedCustomer = {};

And the ponent, after that you have received your customer from the api, push the customer to the service:

  this.customerService.saveNewCustomer(customer)
    .subscribe(res => {
       this.customer = res;
       this.customerService.sharedCustomer = this.customer;
       this.router.navigateByUrl('/earning/customers/profile');
    });
  }

Notice that I'm emitting the customer inside the subscription, as well as the navigation, to ensure that the customer gets stored in the service properly, as well as not navigating away from page before that.

Then in your detail page:

ngOnInit() {
  this.customer = this.customerService.sharedCustomer;
}
发布评论

评论列表(0)

  1. 暂无评论