双向服务未更新 Angular 中的数据 2
Bi-directional service not updating data in Angular 2
我正在尝试使双向服务正常工作,但无法弄清楚我在哪里遗漏了一个步骤或者做错了什么。控制台中没有错误,但是当我尝试时没有任何反应通过它发送数据。(Here's) 对我目前所拥有的来说是个笨蛋。
我要完成的过程是这样的
将此数据主体加载到 app.ts
并使用 input.copmonent.ts
进行迭代。 (成功完成).
{
"questions":[
{
"question": "How tall are you?",
"name": "height",
"id": "heightCtrl",
"template": "smInput"
},
{
"question": "What is your favorite color?",
"name": "color",
"id": "colorCtrl",
"template": "smInput"
},
{
"question": "What kind of car do you drive?",
"name": "car",
"id": "carCtrl",
"template": "smInput"
}
]
}
将数据加载到新变量并在模板中使用 ngModel
更新用户响应。 (成功完成)
//Input Component (omitted for relevance)
@Component({
template:`
<ng-container *ngIf="Qdata.template == 'smInput'">
<p>{{Qdata.question}}</p>
<input type="text"
id="Qdata.id"
name="Qdata.name"
[(ngModel)]="Response.response"
>
</ng-container>
`
})
export class InputComponent implements OnInit{
@Input() Qdata: any; //from app.ts
Response: FormResponse={}; // new variable
ngOnInit(){ this.prepResponse(); }
prepResponse(){
let a = this.Qdata;
let b = this.Response;
b.question = a.question;
b.id = a.id;
b.name = a.name;
}
}
// Note: FormResponse is a custom class I made that's shaped the same as
// the json data with the addition of a "response:string='';" field.
创建服务以从 input.component.ts
中的 Response
变量接收数据并可供 app.ts
订阅。 (成功完成....我认为...大部分)
//Imports Observable and Subject from proper places
@Injectable()
export class AnswerService {
private FormList = new Subject<FormResponse[]>(); // so far I think this is contributing
to the problem somehow.
addResponse(data:FormResponse){
this.FormList.next(data);
}
getFormList(): Observable<FormResponse[]>{
return this.FormList.asObservable();
}
}
在 Input.component.ts
中创建函数以将数据发送到服务中的 addResponse()
函数。 (成功完成....我认为)
import { AnswerService } from './answer.service';
@Component({
template:`
<ng-container *ngIf="Qdata.template == 'smInput'">
<!--previous HTML -->
<button (click)="sendResponse()">send</button>
<!-- plan to ultimately use OnChanges, using this to test -->
</ng-container>
`,
providers: [AnswerService]
})
export class InputComponent implements OnInit{
@Input() Qdata: any;
Response: FormResponse={};
constructor( private _ans : AnswerService ) {}
ngOnInit(){ ... } prepResponse(){...}
sendResponse(): void{
let a = this.Response;
let grp = new FormResponse({
question:a.question,
response:a.response,
id:a.id,
name:a.name
});
this._ans.addResponse(grp);
}
}
在 app.ts
中创建对 FormList
的订阅。 (成功完成)
//app.ts (omitted for relevance)
import { AnswerService } from './answer.service';
@Component({
providers: [ AnswerService ]
})
export class App implements OnInit{
FormData: Array<FormResponse>=[];
constructor( private _ans : AnswerService ){}
ngOnInit(){
this._ans.getFormList().subscribe( list => { list = this.FormData; });
}
}
到达这一点后,一切都正常加载,没有任何错误,但是当我在输入字段中键入内容并单击发送时,我在 app.ts
模板中创建的绑定中没有任何内容显示新对象被添加到数组中。当我尝试不同的方法时,例如 push()
而不是 next()
,我收到错误提示 this.FormList.push() is not a function
。我需要做什么才能让它发挥作用?
我还想指出,我在 input.copmonent.ts
文件中是 "copying data" 的原因是因为在现实世界中这个 Qdata
变量的用法有很多不仅仅是 4 个属性,尽管它只会将这 4 个属性发送到 Response
变量以发送回父组件。
从现在开始,我计划使用 FormData
变量来迭代带有隐藏的预填充输入的模板驱动表单,类似于这样
<form #myForm="ngForm">
<div *ngFor="let a of FormData">
<div [attr.data-blank]="a.id" class="form-group">
<!-- To force Angular to iterate a wrapper for each group -->
<input type="hidden" class="form-control"
[attr.name]="a.id" [(ngModel)]="a.question"
>
<input type="hidden" class="form-control"
[attr.name]="a.name" [(ngModel)]="a.response"
>
</div>
</div>
</form>
我尝试这样做的原因是因为我制作的问卷类型有大量可选问题嵌套在多层 which you can see here 的问题中。我希望这将是收集用户答案并将它们全部放在一个地方而不会让人头疼的好方法。只要将 answer.service
导入到 input.component
中,它就始终能够 send/update 列表,无论用户朝哪个方向以及需要何种输入情况。我需要做什么才能确保 answer.service
可以交付用于此用途?
这里有一些问题,第一个问题是您的 child component
也将 answer service
标记为提供者,因此它获得了 AnswerService[= 的新实例35=] 而不是获取与父服务相同的服务实例。
@Component({
selector: 'input-component',
templateUrl: 'src/input.component.html'
// No providers
})
export class InputComponent implements OnInit{
// ...
/** Gets same instance of AnswerService as the parent component */
constructor(private _ans: AnswerService){}
sendResponse(): void{
this._ans.addResponse(this.Response);
}
}
此外,您的 FormList
的 getter
不正确,我建议使用 official example 中的这种方法。
您的服务应如下所示。
@Injectable()
export class AnswerService {
private _formList = new Subject<any>();
public FormList = this._formList.asObservable();
addResponse(event: FormResponse){
this._formList.next(event);
}
}
现在,在您的 app.component
上,您需要像这样订阅事件:
@Component({
selector: 'my-app',
templateUrl:'src/app.html',
providers: [ QuestionService, AnswerService ]
})
export class App implements OnInit{
FormData: FormResponse[] = [];
// ...
answerSubscription = this._ans.FormList.subscribe(a => {
console.log('gets here '+JSON.stringify(a, null, '\t') )
this.FormData.push(a)
})
// ...
}
请注意,在订阅中我将结果附加到 FormData
数组。
QuestionService
代码可能需要一些修改,但你明白了。
这里是 plunker 工作!
我正在尝试使双向服务正常工作,但无法弄清楚我在哪里遗漏了一个步骤或者做错了什么。控制台中没有错误,但是当我尝试时没有任何反应通过它发送数据。(Here's) 对我目前所拥有的来说是个笨蛋。
我要完成的过程是这样的
将此数据主体加载到 app.ts
并使用 input.copmonent.ts
进行迭代。 (成功完成).
{
"questions":[
{
"question": "How tall are you?",
"name": "height",
"id": "heightCtrl",
"template": "smInput"
},
{
"question": "What is your favorite color?",
"name": "color",
"id": "colorCtrl",
"template": "smInput"
},
{
"question": "What kind of car do you drive?",
"name": "car",
"id": "carCtrl",
"template": "smInput"
}
]
}
将数据加载到新变量并在模板中使用 ngModel
更新用户响应。 (成功完成)
//Input Component (omitted for relevance)
@Component({
template:`
<ng-container *ngIf="Qdata.template == 'smInput'">
<p>{{Qdata.question}}</p>
<input type="text"
id="Qdata.id"
name="Qdata.name"
[(ngModel)]="Response.response"
>
</ng-container>
`
})
export class InputComponent implements OnInit{
@Input() Qdata: any; //from app.ts
Response: FormResponse={}; // new variable
ngOnInit(){ this.prepResponse(); }
prepResponse(){
let a = this.Qdata;
let b = this.Response;
b.question = a.question;
b.id = a.id;
b.name = a.name;
}
}
// Note: FormResponse is a custom class I made that's shaped the same as
// the json data with the addition of a "response:string='';" field.
创建服务以从 input.component.ts
中的 Response
变量接收数据并可供 app.ts
订阅。 (成功完成....我认为...大部分)
//Imports Observable and Subject from proper places
@Injectable()
export class AnswerService {
private FormList = new Subject<FormResponse[]>(); // so far I think this is contributing
to the problem somehow.
addResponse(data:FormResponse){
this.FormList.next(data);
}
getFormList(): Observable<FormResponse[]>{
return this.FormList.asObservable();
}
}
在 Input.component.ts
中创建函数以将数据发送到服务中的 addResponse()
函数。 (成功完成....我认为)
import { AnswerService } from './answer.service';
@Component({
template:`
<ng-container *ngIf="Qdata.template == 'smInput'">
<!--previous HTML -->
<button (click)="sendResponse()">send</button>
<!-- plan to ultimately use OnChanges, using this to test -->
</ng-container>
`,
providers: [AnswerService]
})
export class InputComponent implements OnInit{
@Input() Qdata: any;
Response: FormResponse={};
constructor( private _ans : AnswerService ) {}
ngOnInit(){ ... } prepResponse(){...}
sendResponse(): void{
let a = this.Response;
let grp = new FormResponse({
question:a.question,
response:a.response,
id:a.id,
name:a.name
});
this._ans.addResponse(grp);
}
}
在 app.ts
中创建对 FormList
的订阅。 (成功完成)
//app.ts (omitted for relevance)
import { AnswerService } from './answer.service';
@Component({
providers: [ AnswerService ]
})
export class App implements OnInit{
FormData: Array<FormResponse>=[];
constructor( private _ans : AnswerService ){}
ngOnInit(){
this._ans.getFormList().subscribe( list => { list = this.FormData; });
}
}
到达这一点后,一切都正常加载,没有任何错误,但是当我在输入字段中键入内容并单击发送时,我在 app.ts
模板中创建的绑定中没有任何内容显示新对象被添加到数组中。当我尝试不同的方法时,例如 push()
而不是 next()
,我收到错误提示 this.FormList.push() is not a function
。我需要做什么才能让它发挥作用?
我还想指出,我在 input.copmonent.ts
文件中是 "copying data" 的原因是因为在现实世界中这个 Qdata
变量的用法有很多不仅仅是 4 个属性,尽管它只会将这 4 个属性发送到 Response
变量以发送回父组件。
从现在开始,我计划使用 FormData
变量来迭代带有隐藏的预填充输入的模板驱动表单,类似于这样
<form #myForm="ngForm">
<div *ngFor="let a of FormData">
<div [attr.data-blank]="a.id" class="form-group">
<!-- To force Angular to iterate a wrapper for each group -->
<input type="hidden" class="form-control"
[attr.name]="a.id" [(ngModel)]="a.question"
>
<input type="hidden" class="form-control"
[attr.name]="a.name" [(ngModel)]="a.response"
>
</div>
</div>
</form>
我尝试这样做的原因是因为我制作的问卷类型有大量可选问题嵌套在多层 which you can see here 的问题中。我希望这将是收集用户答案并将它们全部放在一个地方而不会让人头疼的好方法。只要将 answer.service
导入到 input.component
中,它就始终能够 send/update 列表,无论用户朝哪个方向以及需要何种输入情况。我需要做什么才能确保 answer.service
可以交付用于此用途?
这里有一些问题,第一个问题是您的 child component
也将 answer service
标记为提供者,因此它获得了 AnswerService[= 的新实例35=] 而不是获取与父服务相同的服务实例。
@Component({
selector: 'input-component',
templateUrl: 'src/input.component.html'
// No providers
})
export class InputComponent implements OnInit{
// ...
/** Gets same instance of AnswerService as the parent component */
constructor(private _ans: AnswerService){}
sendResponse(): void{
this._ans.addResponse(this.Response);
}
}
此外,您的 FormList
的 getter
不正确,我建议使用 official example 中的这种方法。
您的服务应如下所示。
@Injectable()
export class AnswerService {
private _formList = new Subject<any>();
public FormList = this._formList.asObservable();
addResponse(event: FormResponse){
this._formList.next(event);
}
}
现在,在您的 app.component
上,您需要像这样订阅事件:
@Component({
selector: 'my-app',
templateUrl:'src/app.html',
providers: [ QuestionService, AnswerService ]
})
export class App implements OnInit{
FormData: FormResponse[] = [];
// ...
answerSubscription = this._ans.FormList.subscribe(a => {
console.log('gets here '+JSON.stringify(a, null, '\t') )
this.FormData.push(a)
})
// ...
}
请注意,在订阅中我将结果附加到 FormData
数组。
QuestionService
代码可能需要一些修改,但你明白了。
这里是 plunker 工作!