Angular 表达式ChangedTerithasBeenCheckedError-针对角度v4求解
这里的问题是:我的应用程序是否有更好的架构,这样我就可以避免Angular Docs中的解决方案,这看起来像是一个黑客。(对不起,我爱你!) 这个错误让程序员们发疯,作为一名编程新手,我一天中的大部分时间都很迷茫。有很多建议和奇怪的黑客让它消失,至少对noobs来说很奇怪。因此,我将在一个比我了解得多的人的要求下发布我的解决方案 对于我发现的这个错误,最好的解释是Maxim Koretskyi: 然而,我被甩出了轨道,损失了更多的时间。如果你向下滚动到“可能的修复”,他似乎建议不要使用这两种解决方案,我们应该重新设计我们的应用程序。虽然我同意他的观点,但我不知道该怎么做,因为我找不到具体的重新架构解决方案,所以我最终选择了他提到的两个“可能的修复”的“异步更新” 这是可行的,但确实感觉像是一个黑客。这是在Angular文档中作为解决方案的,尽管我很难弄清楚这个例子是如何应用到我的应用程序中的 重新设计似乎更专业,但我在网上找不到有用的例子。许多堆栈溢出帖子不包含整个组件,只包含noob难以学习的神秘部分。我常常不得不猜测这些部件是什么。令人困惑 下面是我的应用程序组件和解决方案的相关部分。我希望它能为其他新手节省很多时间 所有项目.component.html在html中,当用户想要编辑项目时,会出现一个单击事件Angular 表达式ChangedTerithasBeenCheckedError-针对角度v4求解,angular,observable,Angular,Observable,这里的问题是:我的应用程序是否有更好的架构,这样我就可以避免Angular Docs中的解决方案,这看起来像是一个黑客。(对不起,我爱你!) 这个错误让程序员们发疯,作为一名编程新手,我一天中的大部分时间都很迷茫。有很多建议和奇怪的黑客让它消失,至少对noobs来说很奇怪。因此,我将在一个比我了解得多的人的要求下发布我的解决方案 对于我发现的这个错误,最好的解释是Maxim Koretskyi: 然而,我被甩出了轨道,损失了更多的时间。如果你向下滚动到“可能的修复”,他似乎建议不要使用这两种解
<md-list-item class="items" *ngFor="let project of projects">
<li fxFlex="30" class="badge" (click)="goToDetailPage(project)">
<span> {{ project.projectName }} </span>
</li>
<li fxFlex="20" class="item"> {{ project.projectOwner }} </li>
...
编辑project.component.ts在ngOnInit中,这就是问题所在。我试过ngAfterViewInit,但没用。马克西姆解释了这个问题是如何在Angular的生命周期钩子中出现的。在setTimeout中包装函数调用给了计算机更多的时间来处理更改并修复了问题
import { Component, AfterViewInit, ViewChild } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { ProjectsAdminService } from './project-admin.service';
import { Project } from './project-admin.model';
import { AddEditFormComponent } from './add-edit-form.component';
import { SuccessService } from '../../../shared/success.service';
@Component({
selector: 'app-edit-project',
templateUrl: './edit-project.component.html'
})
export class EditProjectComponent implements AfterViewInit {
project: Project;
@ViewChild(AddEditFormComponent)
private addEditForm: AddEditFormComponent;
private projectId: string;
private projectData;
private success() {
this.successService
.openDialog('Database updated as you wished!');
}
constructor(
private projectsAdminService: ProjectsAdminService,
private successService: SuccessService,
private route: ActivatedRoute,
private router: Router
) {}
// Need to load the data after the form is rendered so ngOnInit didn't work.
ngAfterViewInit() {
setTimeout(() => {
this.fetchProject();
});
}
// Parse the URL for the project id number or $key.
fetchProject() {
this.route.params.forEach((urlParameters) => {
this.projectId = urlParameters['id'];
});
// Display the data retrieved from the data model to the form model.
this.projectsAdminService.getProjectById(this.projectId)
.subscribe(dataLastEmittedFromObserver => {
this.projectData = dataLastEmittedFromObserver;
this.addEditForm.addEditProjectForm.setValue({
projectOwner: this.projectData.projectOwner,
projectOwnerKey: this.projectData.projectOwnerKey,
setupDate: this.projectData.setupDate,
...
});
});
}
// Add error handling and success message linked to Firebase results.
update() {
this.project = this.prepareSaveProject();
this.projectsAdminService.updateProject(this.projectId, this.project);
this.reset();
this.success();
this.router.navigate(['/loggedin/admin/projectsAdmin/searchProjects']);
}
prepareSaveProject(): Project {
const formModel = this.addEditForm.addEditProjectForm.value;
// return updated `Project` object
const updatedProject: Project = {
projectOwner: formModel.projectOwner as string,
projectOwnerKey: formModel.projectOwnerKey as string,
setupDate: formModel.setupDate as string,
...
};
return updatedProject;
}
reset() {
this.addEditForm.addEditProjectForm.reset();
}
cancel() {
this.router.navigate(['/loggedin/admin/projectsAdmin/searchProjects']);
}
}
每个请求的edit.project.component.html,于2017年7月24日添加:
<md-card class="form-card">
<h2 fxLayoutAlign="space-around center">Edit Project Form</h2><br>
<app-add-edit-form></app-add-edit-form>
<div fxLayout="row" fxLayoutAlign="space-around center">
<button [disabled]="!addEditForm.addEditProjectForm.valid" md-raised-button (click)="update(addEditForm.addEditProjectForm.value)">Save Edits</button>
<button md-raised-button (click)="cancel()">Cancel Edit</button>
</div>
</md-card>
<section>
<H4>Search members to add owners</H4>
<app-add-owner
(onSelected)="onSelected($event)">
</app-add-owner>
</section>
<form [formGroup]="addEditProjectForm"
(ngSubmit)="onSubmit(addEditProjectForm.value)"
[class.error]="!addEditProjectForm.valid && addEditProjectForm.touched">
<ul class="items">
<li>
<label>Project owner: </label><br><br>
<input class="inputField" type="text" id="projectOwner" formControlName="projectOwner" required>
</li>
<li class="hiddenField">
<label>Project owner key: </label><br><br>
<input class="inputField" type="text" id="projectOwnerKey" formControlName="projectOwnerKey" required>
</li>
<li>
<label>Setup Date (Year/Month/Day):</label><br><br>
<input class="inputField" type="text" id="setupDate" formControlName="setupDate" required>
</li>
<div>
<li>
<label>Check if new project - 95% equity available: </label><br><br>
<input #newProject type="checkbox" id="newProject" formControlName="newProject">
</li>
<li *ngIf="newProject.checked == false">
<label>If partially complete project, percent of project equity available: </label><br><br>
<input class="percentField" type="text" id="percentAvailable" formControlName="percentAvailable"> %
</li>
</div>
<li>
<label>Project name: </label><br><br>
<input class="inputField" type="text" id="projectName" formControlName="projectName" required>
</li>
<li><label>Put project in stealth mode?</label><br><br>
<label><input type="radio" formControlName="stealthMode" [value]="true"/> Yes</label><br>
<label><input type="radio" formControlName="stealthMode" [value]="false"/> No</label>
</li>
(...)
编辑项目表单
保存编辑结果
取消编辑
为每个请求添加编辑表单.component.html,于2017年7月24日添加:
<md-card class="form-card">
<h2 fxLayoutAlign="space-around center">Edit Project Form</h2><br>
<app-add-edit-form></app-add-edit-form>
<div fxLayout="row" fxLayoutAlign="space-around center">
<button [disabled]="!addEditForm.addEditProjectForm.valid" md-raised-button (click)="update(addEditForm.addEditProjectForm.value)">Save Edits</button>
<button md-raised-button (click)="cancel()">Cancel Edit</button>
</div>
</md-card>
<section>
<H4>Search members to add owners</H4>
<app-add-owner
(onSelected)="onSelected($event)">
</app-add-owner>
</section>
<form [formGroup]="addEditProjectForm"
(ngSubmit)="onSubmit(addEditProjectForm.value)"
[class.error]="!addEditProjectForm.valid && addEditProjectForm.touched">
<ul class="items">
<li>
<label>Project owner: </label><br><br>
<input class="inputField" type="text" id="projectOwner" formControlName="projectOwner" required>
</li>
<li class="hiddenField">
<label>Project owner key: </label><br><br>
<input class="inputField" type="text" id="projectOwnerKey" formControlName="projectOwnerKey" required>
</li>
<li>
<label>Setup Date (Year/Month/Day):</label><br><br>
<input class="inputField" type="text" id="setupDate" formControlName="setupDate" required>
</li>
<div>
<li>
<label>Check if new project - 95% equity available: </label><br><br>
<input #newProject type="checkbox" id="newProject" formControlName="newProject">
</li>
<li *ngIf="newProject.checked == false">
<label>If partially complete project, percent of project equity available: </label><br><br>
<input class="percentField" type="text" id="percentAvailable" formControlName="percentAvailable"> %
</li>
</div>
<li>
<label>Project name: </label><br><br>
<input class="inputField" type="text" id="projectName" formControlName="projectName" required>
</li>
<li><label>Put project in stealth mode?</label><br><br>
<label><input type="radio" formControlName="stealthMode" [value]="true"/> Yes</label><br>
<label><input type="radio" formControlName="stealthMode" [value]="false"/> No</label>
</li>
(...)
搜索成员以添加所有者
-
项目负责人:
-
项目所有者密钥:
-
设置日期(年/月/日):
-
检查新项目-95%股权是否可用:
-
如果部分完成项目,可用项目股权的百分比:
%
-
项目名称:
- 将项目置于隐藏模式?
是
不
(...)
project admin.service.ts因此,我不会让任何人猜测这个问题的另一部分,我将包括我的相关服务,用于对数据库进行CRUDing
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { ProjectsAdminService } from './project-admin.service';
import { ConfirmService } from '../../../shared/confirm.service';
import { Project } from './project-admin.model';
@Component({
selector: 'app-all-projects',
templateUrl: './all-projects.component.html'
})
export class AllProjectsComponent implements OnInit {
projects: Project[];
private selectedId: number;
private result: boolean;
allProjects: Project[];
constructor(
private projectsAdminService: ProjectsAdminService,
private router: Router,
private confirmService: ConfirmService
) {}
ngOnInit() {
this.projectsAdminService.getProjects()
.subscribe(
projects => this.allProjects = this.projects = projects
);
}
// Create the URL param key to be parsed in the edit-project component.
goToDetailPage(selectedProject) {
this.router.navigate(['/loggedin/admin/projectsAdmin/editProject', selectedProject.$key]);
};
deleteProject(selectedProject) {
// Call the confirm dialog component
this.confirmService
.confirm('Confirm Delete', 'This action is final. Gone forever!')
.do(res => {if (res === true) {this.projectsAdminService.deleteProject(selectedProject.$key);
}})
.subscribe(res => this.result = res, err => err);
}
}
import { AngularFireDatabase, FirebaseListObservable } from 'angularfire2/database';
import { FirebaseApp } from 'angularfire2';
import { Inject, Injectable } from '@angular/core';
import { Project } from './project-admin.model';
import { SuccessService } from '../../../shared/success.service';
@Injectable()
export class ProjectsAdminService {
private projects$: FirebaseListObservable<Project[]>;
constructor(
private af: AngularFireDatabase,
private successService: SuccessService,
@Inject(FirebaseApp) fb) {
this.projects$ = af.list('Projects');
}
// Get all projects.
public getProjects(): FirebaseListObservable<any> {
return this.af.list('Projects', {
query: {
orderByChild: 'projectName'
}
});
}
// Fetch project detail for project list from click event.
public getProjectById(projectId: string) {
return this.af.object('Projects/' + projectId);
}
// Create new project
public addProject(newProject: Project): void {
this.projects$.push(newProject)
.catch(error => this.handleError(error));
}
// Update an existing project
public updateProject(key: string, value: any): void {
this.projects$.update(key, value)
.catch(error => this.handleError(error));
}
// Deletes a single project and calls for success modal window.
public deleteProject(key: string): void {
this.af.object('/Projects/' + key).remove()
.catch(error => this.handleError(error))
.then(_ => this.success());
}
private success() {
this.successService
.openDialog('Database updated as you wished!');
}
// Default error handling for all actions
private handleError(error) {
console.log(error)
}
}
从“angularfire2/数据库”导入{AngularFireDatabase,FirebaseListObservable};
从“angularfire2”导入{FirebaseApp};
从“@angular/core”导入{Inject,Injectable};
从“./Project admin.model”导入{Project};
从“../../../shared/success.service”导入{SuccessService};
@可注射()
导出类ProjectsAdminService{
私人项目$:FirebaseListObservable;
建造师(
私人af:AngularFireDatabase,
私人成功服务:成功服务,
@注入(FirebaseApp)fb){
this.projects$=af.list('projects');
}
//获取所有项目。
public getProjects():FirebaseListObservable{
返回此.af.list('Projects'{
查询:{
orderByChild:“项目名称”
}
});
}
//从单击事件获取项目列表的项目详细信息。
公共getProjectById(projectId:string){
返回此.af.object('Projects/'+projectd);
}
//创建新项目
公共添加项目(新建项目:项目):无效{
此.projects$.push(newProject)
.catch(error=>this.handleError(error));
}
//更新现有项目
公共更新项目(键:字符串,值:任意):void{
此.projects$.update(键,值)
.catch(error=>this.handleError(error));
}
//删除单个项目并调用成功模式窗口。
公共删除项目(键:字符串):无效{
this.af.object('/Projects/'+key).remove()
.catch(错误=>此.handleError(错误))
.然后(=>this.success());
}
私人成功(){
这是成功服务
.openDialog('数据库已按您的意愿更新!');
}
//所有操作的默认错误处理
私有句柄错误(错误){
console.log(错误)
}
}
就这样。也许有办法重新设计这个设置,但我看不到。欢迎任何讨论和更好的解决方案 嘿,你能发布
项目编辑组件.ts
和AddEditFormComponent
代码和模板的模板以及准确的错误描述吗<代码>所有项目。组件在这里似乎是不相关的,因为我知道您正在远离它,它正在被破坏。我添加了html组件Maximus.:-)很好,但我们还需要AddEditFormComponent
代码和精确的错误描述:)