Angular2 和 Firebase - 如何根据 URL 参数预加载表单输入字段?

Angular2 & Firebase - How to preload form input fields based on URL params?

我得到了什么

不知道怎么实现的

ProjectEditComponent.html

<h2>
  projects-edit works!
</h2>


<input #newTitle type='text' placeholder='project title'/>
<input #newReference type='text' placeholder='project reference'/>
<input #newDate type='date' placeholder='project date'/>

<button (click)="submitForm(newTitle.value, newReference.value, newDate.value, newAuditorName.value, newCompanyName.value); newTitle.value=''; newReference.value=''; newDate.value=''; newAuditorName.value=''; newCompanyName.value=''"> 
  Save 
</button>

<a [routerLink]="['/projects']"> Cancel </a>

ProjectEditComponent.ts

import { Component, OnInit } from '@angular/core';
import * as firebase from 'firebase/app';
import { AuthService } from '../auth.service';
import { Router } from '@angular/router';

@Component({
  selector: 'app-projects-edit',
  templateUrl: './projects-edit.component.html',
  styleUrls: ['./projects-edit.component.css']
})
export class ProjectsEditComponent implements OnInit {

  constructor(
    private authService: AuthService,
    private router: Router
  ) { }

  ngOnInit() {
    
  }


  submitForm(title: string, reference: string, date: string, auditorName: string, newCompanyName: string) {


  }

}

如有任何帮助,我们将不胜感激。

编辑: 下面是根据@msmolcic 的进展所做的编辑!

ProjectEditComponent.ts

import { Component, OnInit } from '@angular/core';
import * as firebase from 'firebase/app';
import { AuthService } from '../auth.service';
import { Router } from '@angular/router';
import { ActivatedRoute, Params } from '@angular/router';

import { FormGroup, FormBuilder } from '@angular/forms';
import { ProjectResolver } from './projects-resolver.service';



@Component({
  selector: 'app-projects-edit',
  templateUrl: './projects-edit.component.html',
  styleUrls: ['./projects-edit.component.css']
  
})
export class ProjectsEditComponent implements OnInit {

  formName: FormGroup;

  constructor(
    private authService: AuthService,
    private router: Router,
    private activeRoute: ActivatedRoute,

    private formBuilder: FormBuilder
  ) { }



  ngOnInit(): void {
    this.activeRoute.data
      .subscribe(routeData => {
        // Notice that name of the field 'projectData' matches
        // the one you set as alias of the data resolved from
        // the ProjectResolver inside your routing module.
        let projectData = routeData.projectData;

        // Do whatever you want with project data...
        this.formName = this.formBuilder.group({
          // someProperty1 - name of the formControl
          // projectData.someProperty1 - value of your object property
          someProperty1: projectData.project_title
        });
      });


  }

  submitForm(title: string, reference: string, date: string, auditorName: string, newCompanyName: string) {}

}

ProjectsResolver.ts

我以前从未创建过其中一个,所以请原谅我的愚蠢(我只学习 angular 一个半星期)。如果我注释掉我的 return 数据,页面加载并且我可以导航。当我包含 return 行时,我的分页符没有错误。

import { Injectable } from '@angular/core';
import { AngularFireDatabase, FirebaseListObservable, FirebaseObjectObservable } from 'angularfire2/database';
import * as firebase from 'firebase/app';
import { Observable } from 'rxjs/Observable';
import { AuthService } from '../auth.service';
import { ActivatedRoute, Params, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';

@Injectable()

export class ProjectResolver {
    projectsDetails: FirebaseListObservable<any[]>;
    user: Observable<firebase.User>;
    userID;

    constructor(
        private database: AngularFireDatabase,
        private authService: AuthService,
    ) {
        this.authService.user.subscribe(user => {
            if (user) {
                this.userID = user.uid;
            } else {
                console.log('not signed in apparently');
            }
        });
    }

    resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
        // Notice that name of the parameter 'id' matches the /:id from routing module
        let projectId = route.params['projectId'];

        // Insert the correct fetch logic here, it will then return
        // data to the component after it's resolved.

        //return this.firebaseDb.getProjectById(projectId);
        //return this.projectsDetailsService.getProjectById(projectId);
       // 
       return this.database.list('/project/' + this.userID + '/' + projectId);

    }

}

路由

// Modules
import { ModuleWithProviders }  from '@angular/core';
import { Routes, RouterModule } from '@angular/router';

// Components
import { LoginPageComponent } from './login-page/login-page.component';
import { ProjectsListComponent } from './projects-list/projects-list.component';
import { ProjectsDetailsComponent } from './projects-details/projects-details.component';
import { ProjectsEditComponent } from './projects-edit/projects-edit.component';
import { IssuesListComponent } from './issues-list/issues-list.component';
import { IssuesDetailsComponent } from './issues-details/issues-details.component';

import { ProjectResolver } from './projects-edit/projects-resolver.service';



// Including const before declaring a property or variable makes something a constant. A constant is a value that other code in our application cannot change. It's a read-only reference that cannot be redefined.
const appRoutes: Routes = [ 
    { path:'login', component: LoginPageComponent },
    { path:'projects', component: ProjectsListComponent },
    { path:'projects/:projectId', component: ProjectsDetailsComponent },
    { path:'projects/0/edit', component: ProjectsEditComponent },
    { path:'projects/:projectId/edit', component: ProjectsEditComponent, resolve: { projectData: ProjectResolver } },
    { path:'projects/:projectId/i', component: IssuesListComponent },
    { path:'projects/:projectId/i/:issueId', component: IssuesDetailsComponent },
    { path: '', redirectTo: 'login', pathMatch: 'full' },
    { path: '**', redirectTo: 'login', pathMatch: 'full' }
];

// Next, our file needs to export our routes to the rest of the application
export const routing: ModuleWithProviders = RouterModule.forRoot(appRoutes);

项目编辑HTMl

<form [formGroup]="formName">
    <input type="text" formControlName="someProperty1" />
</form>

感谢您一直以来的努力。现在感觉更近了! :)

您需要做的是从 url 中获取参数,然后使用这些参数值构建表单。

import {FormGroup, FormBuilder, Validators} from "@angular/forms";
import {ActivatedRoute} from "@angular/router";

export class ProjectsEditComponent implements OnInit {
private myForm: FormGroup; 
constructor(private activeRoute : ActivatedRoute,  private fb: FormBuilder) {}

ngOnInit() {

       let title = this.activeRoute.snapshot.params['title'];
       let reference = this.activeRoute.snapshot.params['reference'];
       let date = this.activeRoute.snapshot.params['date']; // should fetch the param named as date

       this.myForm = this.fb.group({
            title: [title, Validators.required],
            reference: [reference, Validators.required],
            date: [date, Validators.required],
       });
 }
}

模板文件

<form [formGroup]="myForm">
    <input #newTitle type='text' formControlName= 'title' placeholder='project title'/>
    <input #newReference type='text' formControlName= 'reference' placeholder='project reference'/>
    <input #newDate type='date' formControlName= 'date' placeholder='project date'/>
</form>

您可能想要创建一个 Resolver 以在开始初始化 Component 之前从 Firebase 获取数据。

在您的 RoutingModule 中,您应该为 edit 路线设置:

{
    path: '/project/:id/edit',
    component: ProjectEditComponent,
    data: {
        title: 'Edit project' // Optional page title
    },
    resolve: {
        // projectData - alias of the data resolved within a resolver
        // ProjectResolver - resolver handling the fetch logic for your Component
        projectData: ProjectResolver
    }
}

之后,您必须在某处创建 ProjectResolver

@Injectable()
export class ProjectResolver {

    constructor(
        private firebaseDb: NotSureWhatIsTheName
    ) { }

    resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
        // Notice that name of the parameter 'id' matches the /:id from routing module
        let projectId = route.params['id'];

        // Insert the correct fetch logic here, it will then return
        // data to the component after it's resolved.
        return this.firebaseDb.getProjectById(projectId);
    }
}

最后,在您的 Component 中,您应该获取该数据并将其分配到您想要的任何位置。

// Inside the component
constructor(
    private route: ActivatedRoute
) { }

ngOnInit(): void {
    this.route.data
        .subscribe(routeData => {
            // Notice that name of the field 'projectData' matches
            // the one you set as alias of the data resolved from
            // the ProjectResolver inside your routing module.
            let projectData = routeData.projectData;

            // Do whatever you want with project data...
        });
}

编辑:

为了将这些值绑定到您的表单,您需要在 ComponentModule.

中从 @angular/forms 导入 ReactiveFormsModule
// If you don't have multiple modules, this should be placed inside your 'app.module.ts'
// Otherwise, place it into your project.module.ts or whatever it's called.

// Import the Module from @angular/forms
import { ReactiveFormsModule } from '@angular/forms';

@NgModule({
    declarations: [ ... ], // Whatever you have here
    imports: [ ..., ReactiveFormsModule ], // <- insert ReactiveFormsModule
    ... // Other stuff

导入 ReactiveFormsModule 后,您可以在 ProjectEditComponent.

中使用 FormGroupFormBuilder
// Inside your component
// Import FormGroup and FormBuilder from @angular/forms
import { FormGroup, FormBuilder } from '@angular/forms';

...
formName: FormGroup;

constructor(
    private formBuilder: FormBuilder
) { }

ngOnInit(): void {
    // Lets say you fetched data from the resolver into
    // projectData object as shown before.

    this.formName = this.formBuilder.group({
        // someProperty1 - name of the formControl
        // projectData.someProperty1 - value of your object property
        someProperty1: projectData.someProperty1
    });
}

之后,您可以将 FormGroup 绑定到 html 中的 <form> 元素。

<form [formGroup]="formName">
    <input type="text" formControlName="someProperty1" />
</form>