Angular - przekazywanie szablonu do komponentu

0

Witam,

Zadanie: generator tabeli.
Problem: komórki zawierają nie tylko wartości, ale labele i buttony, które powinny być generowane w zależności od wartości danych w komórce, a ich kliknięcie powinno odpalać określoną funkcję. Dlatego powinna być możliwość przekazywania szablonu dla kolumny - tak (lub w zbliżony sposób), jak ma np. angular-material: https://material.angular.io/components/table/overview
Tak, wiem że mogę po prostu skorzystać z materiala, ale nie o to chodzi - chcę się dowiedzieć, jak to działa i się tego nauczyć.

Prosiłbym o wyjaśnienie albo - najlepiej - linka do tutoriala/filmu poruszającego te zagadnienia.
Te, które znalazłem, uczą wykorzystywania i różnic między ng-container i ng-template, ale z żadnego nie dowiedziałem się tego, czego potrzebuję;

0

Dziękuję wszystkim za chęci, ale już sobie poradziłem.
Oczywiście - już zamieszczam rozwiązanie, na wypadek gdyby ktoś potrzebował.

users-list.component.ts:

import { Component, OnInit } from '@angular/core';
import { UsersService } from "../../../services/api/users-service";
import { TableResponse } from "../../../models/data-table/table-response";
import { map } from "rxjs/operators";
import { TableSettings } from "../../../models/data-table/table-settings";
import { User } from "../../../models/user";

@Component({
    selector: 'app-users-list',
    templateUrl: './users-list.component.html',
    styleUrls: ['./users-list.component.scss']
})
export class UsersListComponent implements OnInit {
    
    public items: Array<User> = [];

    public tableSettings: TableSettings = new TableSettings();

    constructor(
        private usersService: UsersService
    ) {}

    ngOnInit(): void {
        this.fetch();
    }

    private fetch() {
        this.items = [];

        this.usersService.getUsersList(this.tableSettings).pipe(
            map((response) => new TableResponse(response))
        ).subscribe((tableResponse: TableResponse) => {
            if (tableResponse.items.length > 0) {
                for (let item of tableResponse.items) {
                    this.items.push(new User(item));
                }
            }

            console.log(this.items);
        });
    }

    public testFunction(action: string) {
        alert(action);
    }

}

users-list.component.html -> tutaj wrzucam tabelę:

<div class="row">
    <div class="col-lg-12">
        <section class="card">
            <div class="card-body">
                <app-data-table [items]="items">
                    <ng-template #rowHeaderDefinition>
                        <tr>
                            <th>#</th>
                            <th>Login</th>
                            <th>Imię i nazwisko</th>
                            <th>Typ</th>
                            <th>Akcje</th>
                        </tr>
                    </ng-template>

                    <ng-template #rowDefinition let-item="item">
                        <tr>
                            <td>#</td>
                            <td>{{ item.login }}</td>
                            <td>{{ item.personals() }}</td>
                            <td>{{ item.type }}</td>
                            <td class="actions">
                                <a [routerLink]="null" (click)="testFunction('editor' + item.identifier)">
                                    <i class="fas fa-pencil-alt"></i>
                                </a>
                                <a [routerLink]="null" class="delete-row" (click)="testFunction('delete'  + item.identifier)">
                                    <i class="far fa-trash-alt"></i>
                                </a>
                            </td>
                        </tr>
                    </ng-template>
                </app-data-table>
            </div>
        </section>
    </div>
</div>

data-table.component.ts:

import { Component, ContentChild, Input, OnInit, Output } from '@angular/core';

@Component({
    selector: 'app-data-table',
    templateUrl: './data-table.component.html',
    styleUrls: ['./data-table.component.scss']
})
export class DataTableComponent {

    @Input() items: Array<any>;

    @Output() onChange;

    @ContentChild('rowHeaderDefinition') rowHeaderDef;
    @ContentChild('rowDefinition') rowDef;

    constructor() {}

}

data-table.component.html:

<table class="table table-responsive-md table-bordered mb-0">
    <thead>
        <ng-template *ngTemplateOutlet="rowHeaderDef"></ng-template>
    </thead>
    <tbody>
        <ng-template *ngFor="let item of items" [ngIf]="true">
            <ng-template *ngTemplateOutlet="rowDef; context: {item: item}"></ng-template>
        </ng-template>
    </tbody>
</table>

Jak widać - w szablonach #rowHeaderDefinition oraz #rowDefinition wrzucam strukturę wierszy. Co ważne, zawierają one zmienne i struktury html-owe (tutaj: buttony).

Dlaczego tak to rozwiązałem? Bo szukałem rozwiązania typu datatables, które można szybko i łatwo umieścić w X komponentach bez powielania stert kodu. Problemem było to, że tabele oprócz różnej struktury mają zawierać rozmaity dynamicznie generowany kod HTML. Gotowe rozwiązania typu angular-datatables wymagały zabawy z definiowaniem headerów, danych, a do generowania buttonów - zabawy z templateRef. Jak to zobaczyłem i spróbowałem, to podziękowałem.

Oczywiście na tym nie koniec - muszę dołożyć paginację, sortowanie etc., ale cel zasadniczy został osiągnięty.

1 użytkowników online, w tym zalogowanych: 0, gości: 1