여러 구성 요소간에 양방향 바인딩하는 것은 프리미티브가 아닌 객체로 만드는 것이 좋습니다.
16813 단어 ngModelAngular양방향 데이터 바인딩
문제
angular 버전
부모-자식 관계에 있는 child-conponent와 parent-component가 있고, parent-component와 부모-자식 관계에 있는 grand-parent가 있다고 가정합니다.
이 3개 컴포넌트간에 프리미티브형의 데이터를 양방향 바인딩하는 경우, child 컴포넌트의 데이터의 변화가 grand-parent 컴포넌트까지 전해지지 않는다는 현상이 발생했습니다.
child-component.ts
import { Component, EventEmitter, Input, Output } from '@angular/core';
@Component({
selector: 'app-child',
template: `<input type="checkbox" [(ngModel)]="flag"> <p>child: {{flag}}</p>`,
})
export class ChildComponent {
@Input() flag: boolean;
@Output() flagChange: EventEmitter<boolean> = new EventEmitter();
}
parent-component.ts
import { Component, EventEmitter, Input, Output } from '@angular/core';
@Component({
selector: 'app-parent',
template: `<app-child [(flag)]="flag"></app-child> <p>parent: {{flag}}</p>`,
})
export class ParentComponent {
@Input() flag: boolean;
@Output() flagChange: EventEmitter<boolean> = new EventEmitter();
}
grand-parent-component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-grand-parent',
template: `<app-parent [(flag)]="flag"></app-parent> <p>grandParent: {{flag}}</p>`,
})
export class GrandParentComponent {
flag: boolean = false;
}
다음과 같이 flagChange를 emit하면 parent 구성 요소까지 전달됩니다.
child-component.ts
import { Component, EventEmitter, Input, Output } from '@angular/core';
@Component({
selector: 'app-child',
template: `<input type="checkbox" [(ngModel)]="flag" (click)="onFlagChange()"> <p>child: {{flag}}</p>`,
})
export class ChildComponent {
@Input() flag: boolean;
@Output() flagChange: EventEmitter<boolean> = new EventEmitter();
onFlagChange() {
this.flag = !this.flag;
this.flagChange.emit(this.flag);
}
}
parent-component.ts
import { Component, EventEmitter, Input, Output } from '@angular/core';
@Component({
selector: 'app-parent',
template: `<app-child [(flag)]="flag"></app-child> <p>parent: {{flag}}</p>`,
})
export class ParentComponent {
@Input() flag: boolean;
@Output() flagChange: EventEmitter<boolean> = new EventEmitter();
}
grand-parent-component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-grand-parent',
template: `<app-parent [(flag)]="flag"></app-parent> <p>grandParent: {{flag}}</p>`,
})
export class GrandParentComponent {
flag: boolean = false;
}
그러나 이 방법에서는 grand-parent-component까지는 데이터가 전해지지 않습니다.
해결책
프리미티브형이 아닌 오브젝트의 프로퍼티로서 프리미티브형을 건네준다.
즉 이렇게 한다.
child-component.tsimport { Component, EventEmitter, Input, Output } from '@angular/core';
import { Flag } from 'src/app/flag';
@Component({
selector: 'app-child',
template: `<input type="checkbox" [(ngModel)]="flag.isSelected"> <p>child: {{flag.isSelected}}</p>`,
})
export class ChildComponent {
@Input() flag: Flag;
@Output() flagChange: EventEmitter<boolean> = new EventEmitter();
}
parent-component.tsimport { Component, EventEmitter, Input, Output } from '@angular/core';
import { Flag } from 'src/app/flag';
@Component({
selector: 'app-parent',
template: `<app-child [(flag)]="flag"></app-child> <p>parent: {{flag.isSelected}}</p>`,
})
export class ParentComponent {
@Input() flag: Flag;
@Output() flagChange: EventEmitter<boolean> = new EventEmitter();
}
grand-parent-component.tsimport { Component } from '@angular/core';
import { Flag } from 'src/app/flag';
@Component({
selector: 'app-grand-parent',
template: `<app-parent [(flag)]="flag"></app-parent> <p>grandParent: {{flag.isSelected}}</p>`,
})
export class GrandParentComponent {
flag: Flag = { isSelected: false };
}
왜 이런 현상이 일어나는가
여기 의 기사에서는 angularjs입니다만 같은 문제를 해설하고 있어, javascript 의 평가 전략(어떤 식을 어떠한 순서로 평가하는지의 규칙)이 관계하고 있다고 말하고 있습니다.
javascript의 평가 전략에서는 premitive형의 변수는 참조원으로부터 건네받는 것이 아니라, 같은 변수를 다시 만들어 버립니다. 개체만 참조 소스에서 전달됩니다.
여기 의 기사에서도 ngModel 는 primitive 형의 데이터는 아니고 오브젝트에 바인드 하는 것을 추천 하고 있습니다.
Reference
이 문제에 관하여(여러 구성 요소간에 양방향 바인딩하는 것은 프리미티브가 아닌 객체로 만드는 것이 좋습니다.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/kozy10/items/9c27ce92f38085ad634c
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { Flag } from 'src/app/flag';
@Component({
selector: 'app-child',
template: `<input type="checkbox" [(ngModel)]="flag.isSelected"> <p>child: {{flag.isSelected}}</p>`,
})
export class ChildComponent {
@Input() flag: Flag;
@Output() flagChange: EventEmitter<boolean> = new EventEmitter();
}
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { Flag } from 'src/app/flag';
@Component({
selector: 'app-parent',
template: `<app-child [(flag)]="flag"></app-child> <p>parent: {{flag.isSelected}}</p>`,
})
export class ParentComponent {
@Input() flag: Flag;
@Output() flagChange: EventEmitter<boolean> = new EventEmitter();
}
import { Component } from '@angular/core';
import { Flag } from 'src/app/flag';
@Component({
selector: 'app-grand-parent',
template: `<app-parent [(flag)]="flag"></app-parent> <p>grandParent: {{flag.isSelected}}</p>`,
})
export class GrandParentComponent {
flag: Flag = { isSelected: false };
}
여기 의 기사에서는 angularjs입니다만 같은 문제를 해설하고 있어, javascript 의 평가 전략(어떤 식을 어떠한 순서로 평가하는지의 규칙)이 관계하고 있다고 말하고 있습니다.
javascript의 평가 전략에서는 premitive형의 변수는 참조원으로부터 건네받는 것이 아니라, 같은 변수를 다시 만들어 버립니다. 개체만 참조 소스에서 전달됩니다.
여기 의 기사에서도 ngModel 는 primitive 형의 데이터는 아니고 오브젝트에 바인드 하는 것을 추천 하고 있습니다.
Reference
이 문제에 관하여(여러 구성 요소간에 양방향 바인딩하는 것은 프리미티브가 아닌 객체로 만드는 것이 좋습니다.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/kozy10/items/9c27ce92f38085ad634c텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)