2

I have a JSON data which is being returned when in the Parent component. All you would need to do is type the numbers "12233" or "34567" on the Parent component and you can see on the console the data being printed.

Like in child I want to print the {{firstName}} from using the data from Parent.

Is there a way that data attributes can be passed to the Child component using the routes like in the stackblitz here

Parent: HTML:

<button class="btn-thumbnail">type the secret number to pass</button>
<!-- "number": 12233
or
"number": 34567 -->

TS:

import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';

import data from '../data.json';

@Component({
  selector: 'app-parent',
  templateUrl: './parent.component.html',
  styleUrls: ['./parent.component.css']
})
export class ParentComponent implements OnInit {

  constructor(private router: Router) {
    document.addEventListener('keypress', this.secretNumber);
  }

  typed = '';
  firstName : any = {};

  secretNumber = event =>  {
    this.typed += String.fromCharCode(event.keyCode);
    let eraseData = [];
    let matchedData = {};

    if (this.typed.length == 5) {
      Object.keys(data).length > 0 &&
      data.items && data.items.userdata.map((item, i) => {
        if(item.number == this.typed) {
          matchedData = item;
          console.log(item);
          this.firstName = item.firstName;
          console.log(this.firstName);
          this.goToChild();
          return matchedData;
        }
        if (item.number != this.typed) {
          eraseData.push(item);
        }
        return eraseData;
      });

      if (Object.keys(matchedData).length == 0 && eraseData.length > 0 && this.typed.length == 5) {
        this.typed = '';
      }
    }
  };

  ngOnDestroy() {
    document.removeEventListener('keypress', this.secretNumber);
  }

  ngOnInit() {
  }

  goToChild() {
    this.router.navigate(['/child'], { skipLocationChange: true });
  }

}

Data.JSON:

{
    "items": {
        "userdata": [
            {
                "firstName": "john",
                "lastName": "doe",
        "number": 12233
            },
            {
                "firstName": "mary",
                "lastName": "jane",
        "number": 34567
            }
        ]
    }
}

Child: HTML:

<p>
child works! {{firstName}}
</p>

Stackblitz

Bob
  • 467
  • 6
  • 25

1 Answers1

2

Sure, it works just like in your example.

Send the value as a queryParam like this:

goToChild(firstName) {
  this.router.navigate(['/child'], { skipLocationChange: true, queryParams: {firstName} });
}

And then retrieve it on the child route like this:

public firstName?:string;

constructor(
  private activatedRoute:ActivatedRoute
) { }

ngOnInit() {
  this.activatedRoute.queryParamMap.subscribe(paramMap => this.firstName = paramMap.get('firstName'));
}

Here the working StackBlitz.

Passing Objects

If you want to pass an Object, the best way would be to hold the object in a service and pass only a unique identifier via the above method. If you use a State Management Library, you should hold your Object there instead of the service.

I made another StackBlitz shocasing this with your example (I also cleaned up the code a bit to make it easer to see).

pascalpuetz
  • 5,238
  • 1
  • 13
  • 26
  • @pascalpuetxz thank you so much for your help, would you know how to pass the whole JSON data to the next component like how you passed one of the parameters. What about the whole data ? Could you please help me there. – Bob Dec 30 '19 at 02:56
  • 1
    If you want to pass the whole JSON data, then you should consider holding that data in a Service (@Injectable) or, if you have, your State Management Library (ngxs/ngrx/...). If you want to pass only the part of the data that matches your selected user, then you should consider giving your user an ID, pass that ID through a Query Param or Path Param and add a find method to that said service. – pascalpuetz Dec 30 '19 at 05:46
  • 1
    @Bob Updated my answer with another Stackblitz – pascalpuetz Dec 30 '19 at 06:16
  • Hi @pascalpuetz, not sure if you can still see this message. Do you know how to not return the whole object {{ user$ | async | json }} and just return values separately like user.firstName, user.lastName. – Bob Jan 03 '20 at 16:32
  • sure, if you need it at multiple places, use the map function `firstName$ = this.user$.pipe(map(user => user.firstName))`, in the template then do `{{firstName$ | async}}`. Or, if you use it sparingly, you can do `{{(user$ | async)?.firstName}}` in your template. Combined with `*ngIf`, you could also do `*ngIf="user$ | async as user"` and inside you can then use `{{user.firstName}}`. – pascalpuetz Jan 03 '20 at 17:17
  • 1
    You are just the best and thank you so much and cheers! all the options are working and I will make use of the best one as per the needs. – Bob Jan 03 '20 at 17:23
  • Thank you :) Glad I could help! :) – pascalpuetz Jan 03 '20 at 17:49
  • I am going to ask you one last thing, where I want to transfer the same data we have on Child route to move to Superchild route but this time with the button click instead of typing 12233 or anything. here is the latest https://stackblitz.com/edit/share-data-bw-routes-json. – Bob Jan 03 '20 at 20:46
  • Either by using `queryParamsHandling: 'preserve'` or by passing in the same you got via: `queryParams: this.activatedRoute.snapshot.queryParams`. In the superchild component, the code for getting the `user$` is the same as in child. Here the Stackblitz: https://stackblitz.com/edit/share-data-bw-routes-json-hofeps Also, you forgot to setup superchild component for superchild route in your routing module - in your code /superchild rendered child, not superchild :) – pascalpuetz Jan 03 '20 at 21:07
  • Alternatively, you could also use path variables like this: https://stackblitz.com/edit/share-data-bw-routes-json-bkxoev instead of queryParams – pascalpuetz Jan 03 '20 at 21:21
  • This is perfect and is exactly what I wanted. You have been very helpful, can't thank you enough – Bob Jan 03 '20 at 21:23