[Angular] Using ngOnChanges lifeCycle hook to break object reference
What could be the issue, for example we have two list:
Parent component:
@Component({
  selector: 'passenger-dashboard',
  styleUrls: ['passenger-dashboard.component.scss'],
  template: `
    <div>
      <passenger-count
        [items]="passengers">
      </passenger-count>
      <div *ngFor="let passenger of passengers;">
        {{ passenger.fullname }}
      </div>
      <passenger-detail
        *ngFor="let passenger of passengers;"
        [detail]="passenger"
        (edit)="handleEdit($event)"
        (remove)="handleRemove($event)">
      </passenger-detail>
    </div>
  `
})
export class PassengerDashboardComponent implements OnInit {
  passengers: Passenger[];
  constructor() {}
  ngOnInit() {
    this.passengers = [{
      id: ,
      fullname: 'Stephen',
      checkedIn: true,
      checkInDate: ,
      children: null
    }, {
      id: ,
      fullname: 'Rose',
      checkedIn: false,
      checkInDate: null,
      children: [{ name: 'Ted', age:  },{ name: 'Chloe', age:  }]
    }, {
      id: ,
      fullname: 'James',
      checkedIn: true,
      checkInDate: ,
      children: null
    }, {
      id: ,
      fullname: 'Louise',
      checkedIn: true,
      checkInDate: ,
      children: [{ name: 'Jessica', age:  }]
    }, {
      id: ,
      fullname: 'Tina',
      checkedIn: false,
      checkInDate: null,
      children: null
    }];
  }
  handleEdit(event: Passenger) {
    this.passengers = this.passengers.map((passenger: Passenger) => {
      if (passenger.id === event.id) {
        passenger = Object.assign({}, passenger, event);
      }
      return passenger;
    });
  }
  handleRemove(event: Passenger) {
    this.passengers = this.passengers.filter((passenger: Passenger) => {
      return passenger.id !== event.id;
    });
  }
}
Child component:
@Component({
  selector: 'passenger-detail',
  styleUrls: ['passenger-detail.component.scss'],
  template: `
    <div>
      <span class="status" [class.checked-in]="detail.checkedIn"></span>
      <div *ngIf="editing">
        <input
          type="text"
          [value]="detail.fullname"
          (input)="onNameChange(name.value)"
          #name>
      </div>
      <div *ngIf="!editing">
        {{ detail.fullname }}
      </div>
      <div class="date">
        Check in date:
        {{ detail.checkInDate ? (detail.checkInDate | date: 'yMMMMd' | uppercase) : 'Not checked in' }}
      </div>
      <div class="children">
        Children: {{ detail.children?.length ||  }}
      </div>
      <button (click)="toggleEdit()">
        {{ editing ? 'Done' : 'Edit' }}
      </button>
      <button (click)="onRemove()">
        Remove
      </button>
    </div>
  `
})
export class PassengerDetailComponent implements OnInit {
  @Input()
  detail: Passenger;
  @Output()
  edit: EventEmitter<any> = new EventEmitter();
  @Output()
  remove: EventEmitter<any> = new EventEmitter();
  editing: boolean = false;
  constructor() {}
  ngOnInit() {
    console.log('ngOnInit');
  }
  onNameChange(value: string) {
    this.detail.fullname = value;
  }
  toggleEdit() {
    if (this.editing) {
      this.edit.emit(this.detail);
    }
    this.editing = !this.editing;
  }
  onRemove() {
    this.remove.emit(this.detail);
  }
}
They both display list of "passengers".
What will happens that when we change the "passenger" value in 'passenger-detail' component. It will using '(edit)' event to update parent component's 'passengers' variable.
Both changes happens in the same time.
But what we really want is, until child component click "Done" button then parent component get udpate.
So what we can do is using 'ngOnChanges' in child component to break Javascript object reference (this.detail, which marked in yellow background).
export class PassengerDetailComponent implements OnChanges, OnInit {
  constructor() {}
  ngOnChanges(changes) {
    if (changes.detail) {
      this.detail = Object.assign({}, changes.detail.currentValue);
    }
    console.log('ngOnChanges');
  }
  onNameChange(value: string) {
    this.detail.fullname = value;
  }
  ...
}
We use 'Object.assign' to create a new 'this.detail' object reference.
And because of this new creation, it actually breaks the reference of 'this.detail'.
And only when click "Done" button, the deatial will be sent to the parent component.
[Angular] Using ngOnChanges lifeCycle hook to break object reference的更多相关文章
- [React] Update State Based on Props using the Lifecycle Hook getDerivedStateFromProps in React16.3
		
getDerivedStateFromProps is lifecycle hook introduced with React 16.3 and intended as a replacement ...
 - [React] Capture values using the lifecycle hook getSnapshotBeforeUpdate in React 16.3
		
getSnapshotBeforeUpdate is a lifecycle hook that was introduced with React 16.3. It is invoked right ...
 - [MST] Loading Data from the Server using lifecycle hook
		
Let's stop hardcoding our initial state and fetch it from the server instead. In this lesson you wil ...
 - ArcGIS AddIN异常之:object reference not set to an instance of an object
		
异常出现在 frmDownload frd = new frmDownload(); frd.ShowDialog(); 在ArcMap中能正常弹出窗体,点击按钮时显示此异常:object refer ...
 - Java中对不变的 data和object reference 使用 final
		
Java中对不变的 data和object reference 使用 final 许多语言都提供常量数据的概念,用来表示那些既不会改变也不能改变的数据,java关键词final用来表示常量数据.例如: ...
 - Attempt to write to field 'android.support.v4.app.FragmentManagerImpl android.support.v4.app.Fragment.mFragmentManager' on a null object reference
		
E/AndroidRuntime﹕ FATAL EXCEPTION: mainProcess: org.example.magnusluca.drawertestapp, PID: 3624java. ...
 - Azure Sphere–“Object reference not set to an instance of an object” 解决办法
		
在开发Azure Sphere应用时,如果出现项目无法编译,出现“Object reference not set to an instance of an object”时,必须从下面两个方面进行检 ...
 - Visual Studio 2015打开ASP.NET MVC的View提示"Object reference not set to an instance of an object"错误的解决方案
		
使用Visual Studio 2013打开没有问题,但Visual Studio 2015打开cshtml就会提示"Object reference not set to an insta ...
 - Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.app.ActionBar.setDisplayShowHomeEnabled(boolean)' on a null object reference
		
/********************************************************************************* * Caused by: java ...
 
随机推荐
- vue移动端上拉加载更多
			
LoadMore.vue <template> <div class="load-more-wrapper" @touchstart="touchSta ...
 - vue踩坑记- Cannot find module 'wrappy'
			
找不到模块"包装" 当你维护别人的项目代码的时候,在自己这里电脑上运行,打开一个项目cnpm run dev的时候,报错如下 Cannot find module 'wrappy' ...
 - 【习题 7-10 Uva11214】Guarding the Chessboard
			
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 迭代加深搜索. 可以想见最后深度不会很深吧.. 然后皇后之间互相攻击到是允许的.. 就这样 [代码] /* 1.Shoud it u ...
 - Redis  .Net客户端源码
			
1.简单介绍 当前NoSql使用已经极为普遍,无论是Java生态圈,还是.net生态圈.大大小小的Web站点在追求高性能高可靠性方面,不由自主都选择了NoSQL技术作为优先考虑的方面.主流的技术有:H ...
 - [Python] Different ways to test multiple flags at once in Python
			
x, y, z = 0, 1, 0 if x == 1 or y == 1 or z == 1: print('passed') if 1 in (x, y, z): print('passed') ...
 - 12. ZooKeeper之Java客户端API使用—创建会话。
			
转自:https://blog.csdn.net/en_joker/article/details/78686649 客户端可以通过创建一个ZooKeeper(org.apache.zookeeper ...
 - 设置Maven默认的JDK为1.7,解决Update Maven Project默认为1.5和Maven打包报错2个问题
			
1.之前,一直遇到这个问题. Update Maven Project的时候,JDK变成了1.5的. 如果项目中有使用"@overdide",程序就会报错,需要手动修改JRE ...
 - 【Codeforces Round #432 (Div. 2) B】Arpa and an exam about geometry
			
[链接]h在这里写链接 [题意] 给你3个点A,B,C 问你能不能将纸绕着坐标轴上的一点旋转.使得A与B重合,B与C重合 [题解] 这3个点必须共圆. 则A,B,C不能为一条直线.否则无解. 共圆之后 ...
 - [D3] Add label text
			
If we want to add text to a node or a image // Create container for the images const svgNodes = svg ...
 - Dcloud课程7 单例模式一般用在什么场景
			
Dcloud课程7 单例模式一般用在什么场景 一.总结 一句话总结:连接数据库,这样就保证了和数据之间只有一个连接,从而能够不占用多余资源,这样就极大的减少了资源浪费,减少了mysql或者说服务器压力 ...