p-marco
p-marco

Reputation: 59

Create sub-components in angular?

I would like to know what are the possibilities to create little components in angular, which can be shown up when the data will be parsed. Let's say that we have a file (for example in json):

[{
  "name":"John",
  "surname:"Doe",
  "references":[{
     "surname": "One"},{
     "surname": "Two"}]
}]

So, I would like to create a component which targets the "surname" node, despite its depth into the tree. Can you suggest a way to implement it? Thanks in advance!

Upvotes: 2

Views: 688

Answers (2)

Federico Galfione
Federico Galfione

Reputation: 1109

To solve this problem I created a component which works with any key you need (not only surname).

key.component.ts

import {
  Component,
  ContentChild,
  Input,
  OnChanges,
  TemplateRef
} from "@angular/core";

@Component({
  selector: "key-component",
  templateUrl: "./key.component.html"
})
export class KeyComponent implements OnChanges {
  @Input() json: Object;
  @Input() key: string;
  @ContentChild(TemplateRef)
  template: TemplateRef<any>;
  items: Array<any>;

  ngOnChanges() {
    // If the key or the JSON change, revaluate items
    if (this.key && this.json)
      this.items = this.getElementsWithSelectedKey(
        this.objectDeepKeys(this.json)
      );
  }

  // Get all the values that has the key given by Input
  getElementsWithSelectedKey(keys: Array<String>) {
    return keys
      .filter((x: String) => x.endsWith(`.${this.key}`) || x === this.key)
      .map(x => {
        let currValue = this.json;
        for (let str of x.split(".")) {
          currValue = currValue[str];
        }
        return currValue;
      });
  }

  // Finds all the keys for every sub-objects in depth
  objectDeepKeys(obj: Object) {
    return Object.keys(obj)
      .filter(key => obj[key] instanceof Object)
      .map(key => this.objectDeepKeys(obj[key]).map(k => `${key}.${k}`))
      .reduce((x, y) => x.concat(y), Object.keys(obj));
  }
}

key.component.html

<ng-container *ngTemplateOutlet="template; context: { $implicit: items }"></ng-container>

This component gets a json to check (in your case the whole array) and a key to seek (in your case "surname"). It checks for each key inside the json and save into the property items an array with all the values it has found, with the given key.

Now you just have to choose your template (you have to write an ng-template between the key.component's tags) and get the context (let-items creates a variable items with the elements from the property items into key.component) to change your view as you wish.

Example: app.component.html

<key-component [json]="myJSON" key="surname">
    <ng-template let-items>
        <surname-component *ngFor="let item of items" [surname]="item">
        </surname-component>
    </ng-template>
</key-component>

You can see the whole code with a couple of JSON to test on this Stackblitz

Upvotes: 1

playerone
playerone

Reputation: 1127

I don't know what do you mean by ' little components in angular' but if you want to map responses from json file you can use class:

export class People {
    name: string,
    surname: string,
    references: othersurname[]
}

export class othersurname {
    surname: string
}

Upvotes: 0

Related Questions