Angular2 和 Firebase - 如何根据 URL 参数预加载表单输入字段?
Angular2 & Firebase - How to preload form input fields based on URL params?
我得到了什么
- 显示来自 firebase 列表的项目的项目列表(此信息是从引用 firebase 中的节点的项目列表服务中提取的)
- 用于添加新项目的表单 - 这允许我将新数据写入 firebase。 url 看起来像这样:url.com/projects/0/edit
- 当我点击一个项目时,它会将我带到一个项目详细信息页面,其中附加了 url (url.com/projects/-key123456 )(这引用了引用不同 firebase 节点的不同服务)
- 在项目详细信息页面上,我有一个编辑按钮。单击此按钮时,url 如下所示:url.com/projects/-key123456/edit
- 总而言之,添加新项目是可以的。稍后我会写编辑方法。我只需要知道如何根据所选项目预填充表单
不知道怎么实现的
- 我将如何根据所选项目预填充我的编辑表单输入字段?
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
.
中使用 FormGroup
和 FormBuilder
// 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>
我得到了什么
- 显示来自 firebase 列表的项目的项目列表(此信息是从引用 firebase 中的节点的项目列表服务中提取的)
- 用于添加新项目的表单 - 这允许我将新数据写入 firebase。 url 看起来像这样:url.com/projects/0/edit
- 当我点击一个项目时,它会将我带到一个项目详细信息页面,其中附加了 url (url.com/projects/-key123456 )(这引用了引用不同 firebase 节点的不同服务)
- 在项目详细信息页面上,我有一个编辑按钮。单击此按钮时,url 如下所示:url.com/projects/-key123456/edit
- 总而言之,添加新项目是可以的。稍后我会写编辑方法。我只需要知道如何根据所选项目预填充表单
不知道怎么实现的
- 我将如何根据所选项目预填充我的编辑表单输入字段?
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
.
FormGroup
和 FormBuilder
// 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>