Enrich data in Angular

50 Views Asked by At

it's my first post here ! (so please be nice ^^')

It's been a couple of days that I search for the best way to enrich data from a http backend in Angular. Here's my problem:

I have an http backend which provides me the content of a database. The result can be modelized by theses three interfaces:

interface interfaceA {
id: number,
value1: string,
value2: number
}

interface interfaceB {
id: number,
value3: number,
value4: number
}

interface interfaceAB {
id: number,
interfaceA: interfaceA,
interfaceB: interfaceB
}

interface x {
...
...
}

And I have components which take the interfaces and display it in the UI. For now, the components show only the value of the data from the backend api.

I would like add more data in the interfaces (interfaceA, interfaceB and interfaceAB) to precise how to show the values into the component (with sub components using ng-container and *ngComponentOutlet): show a text? A link? in different color or underlined etc...

It woud be something like this:

interface interfaceA {
{id: number, component:any, componentInput: {}},
{value1: string, component: any, componentInput: {}},
{value2: string, component: any, componentInput: {}}
}

For now I tried to implement some classes which contain the interfaces, the components and the components inputs

abstract class data<T> {
  data: T; //InterfaceA, interfaceB, interfaceAB
  abstract components: {};
  abstract componentsInputs: {}
}
export type interfaceA = {
  id: number,
  value1: string,
  value2: number
}

export var interfaceAComponents = {
  id: LinkComponent,
  value1: TextCOmponent,
  value2: Coloredcomponent
}

export class DataClass extends AngularData<DataType> {
  override components = DataComponents;
  override componentsInput: { [key: string]: {[key: string]: any} } = {
    id: {input: this.data.id, link: "https://randomurl?id=" + this.data.id},
    value1: {text: this.data.value1},
    value2: {text: this.data.value2, color: red}
  }

Which allow us to get data in the component like this:

interface Item {
  key: string,
  componentInput: any,
  component: Type<any>
}

class RandomCOmponent implements OnChange{
  @Input() data!: data<any>;
  items: Item[];
  
  ngOnChange(): void {
     if (!this.data) {
      console.log("data is empty: ", this.data);
      return;
    }
    this.items = this.parseItem(this.data);
  }
  
    parseItem(data: AngularData<{[key: string]: any}>, dataList: Item[] = [], root: string = '') {
    let keys = Object.keys(data.data);
    for (let key of keys) {
      let value = data.data[key];
      let component = data.components[key];
      let componentInput = data.componentInput[key];
      if (!component) {
        component = TextComponent;
      }
      if (value instanceof Object) {
        dataList = this.parseItemBis(value, dataList, root + key + ".");
      }else {
        dataList.push({
          key: root + key,
          component: component,
          componentInput: componentInput
        });
      }
    }
    return dataList;
  }
}
<table>
  <tr>
    <th *ngFor="let column of items">
      {{column.key}}
    </th>
  </tr>
  <tr">
    <td *ngFor="let column of items">
      <ng-container *ngComponentOutlet="column.component; inputs: column.componentInput"/>
    </td>
  </tr>
</table>

But someone said me using classes to manage static data and is a bad practice and that it is better interfaces.

So, do you think my solution is correct ? what is the best way for you to enrich the data I get from the api ? Knowing I will in the future add new data in these interfaces, or create similar interfaces to match with other tables in my database.

I hope my question is clear, Thanks in advance for your answers :)

1

There are 1 best solutions below

0
sverbach On

To me this is a bit hard to follow, I am not sure what exactly the goal is here. I'll try to answer some of the questions:

But someone said me using classes to manage static data and is a bad practice and that it is better interfaces.

  • Yes, I'd always use interfaces or types to represent data structure. Otherwise you cannot even specify the type of an object and end up using any everywhere. Which kind of defeats the purpose of TypeScript

So, do you think my solution is correct ? what is the best way for you to enrich the data I get from the api ?

  • In general, I'd try to first use as little abstraction and inheritance as possible (contrary to backend development). Formulate your goals and then try to implement it as simple and declarative as possible. For example, if your goal is to simply render a different component based on some property value, maybe using a simple ngSwitch instead might be the better option.