2

My parent angular component has a nested child component. That child component is a list of buttons. When one button is clicked a value is passed to the child component. That child component is then updated accordingly to an id. I have implemented some change detection to the child. When child register an update comming from the parent, it runs the ngOnChanges hook. Here i call my backend and data returns

My code is working fine, but it seems like a hack. As you can see in the following code, I detach the changeDetection object. In the ngOnChanges - in the subscribe section I reattach the cd again. I dont like

Can you guys give me some pointers on this?

@Component({
  selector: 'app-challenge',
  templateUrl: './challenge.component.html',
  styleUrls: ['./challenge.component.css']
})
export class ChallengeComponent implements OnInit {
  @Input() focusedChallenge: string;

  eventId = {};
  challenge: Challenge;
  userSelection;

  constructor(
    public snackBar: MatSnackBar,
    private eventService: EventService,
    private activeRoute: ActivatedRoute,
    private cd: ChangeDetectorRef
  ) {  
this.cd.detach()
}

  ngOnInit() {
    this.eventId = this.activeRoute.snapshot.params.id;
  }

  ngOnChanges() {
    this.eventService.getChallenge(this.focusedChallenge)
      .subscribe(
        res => {
          this.cd.reattach();
          console.log(res)
          this.challenge = res
        },
        err => { console.log(err) }
      )
      challengeSelected.currentValue.toUpperCase();
  }

Update in response to answer

It does actually give me the result that I want with ngOnChanges(changes: SimpleChanges). But it gives we an error still. Saying that it is undefined.

enter image description here

The options array is a nested array on Challenge

The object returned from db

{_id: "5b86dc5bfb6fc03893e55001", shortEventId: "d2d3", organization: "Brædstrup", name: "1. december", winner: "", …}
born: "1. decemberplus andet"
endDate: "2018-10-06T23:59:00.000Z"
id: "5b86dc5bfb6fc03893e55001"
name: "1. december"
options: Array(4)
0: {name: "Matas", isCorrect: true, description: "Matas er den førende skib", image: "https://cityxpstorage.blob.core.windows.net/images/Matas.png", id: null}
1: {name: "Føtex", isCorrect: false, description: "Føtex er en dejlig butik", image: "https://cityxpstorage.blob.core.windows.net/images/Føtex.png", id: null, …}
2: {name: "Kvickly", isCorrect: false, description: "Kvickly er en dejlig butik", image: "https://cityxpstorage.blob.core.windows.net/images/Matas.png", id: null, …}
3: {name: "MC Jørgensen", isCorrect: false, description: "MC Jørgensen er en dejlig butik", image: "https://cityxpstorage.blob.core.windows.net/images/Matas.png", id: null}
length: 4
__proto__: Array(0)
organization: "Brædstrup"
shortEventId: "d2d3"
startDate: "2018-10-06T00:00:00.000Z"
winner: ""
_id: "5b86dc5bfb6fc03893e55001"
__proto__: Object
12
  • You shouldn't need to do anything with the ChangeDetectorRef. Any time that focusedChallenge is changed, it should fire ngOnChanges Commented Oct 13, 2018 at 8:11
  • The problem is that my view is updated first - but is has no values to attach. It gives me a [object] is undefined error. So it seems that I need to detach the view first in order to suppres errors. Commented Oct 13, 2018 at 8:30
  • You can just handle the case of it being undefined, by performing an if check on it. You can use something like if (suchAndSuch != null), or if it's in the template, you can use suchAndSuch?.myProp, where the ? will prevent it from trying to read myProp is suchAndSuch is null or undefined Commented Oct 13, 2018 at 8:36
  • Could you give me an example? Where should I make the check? Commented Oct 13, 2018 at 9:01
  • Which is the variable is undefined? Can you post the actual error message please? Commented Oct 13, 2018 at 9:06

1 Answer 1

2

Since you are using string type input, you don't need to capture any ChangeDetection. So better you remove the ChangeDetectorRef and let the angular fire the ngOnChanges method whenever the @Input value is getting changed.

Your code should be as -

@Component({
  selector: 'app-challenge',
  templateUrl: './challenge.component.html',
  styleUrls: ['./challenge.component.css']
})
export class ChallengeComponent implements OnInit {
  @Input() focusedChallenge: string;

  eventId = {};
  challenge: Challenge;
  userSelection;

  constructor(
    public snackBar: MatSnackBar,
    private eventService: EventService,
    private activeRoute: ActivatedRoute
  ) {  
}

  ngOnInit() {
    this.eventId = this.activeRoute.snapshot.params.id;
  }

ngOnChanges(changes: SimpleChanges) {

    let newFocusedChallenge  = changes["focusedChallenge"].currentValue;

    this.eventService.getChallenge(newFocusedChallenge)
      .subscribe(
        res => {
          console.log(res)
          this.challenge = res;
          //challengeSelected.currentValue.toUpperCase(); //not sure if is required
        },
        err => { console.log(err) }
      )
  }
}
Sign up to request clarification or add additional context in comments.

2 Comments

What is this syntax? changes["focusedChallenge"];.currentValue
It is changes["focusedChallenge"].currentValue;. Corrected in answer as well.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.