Search code examples
angularrefactoringcomponents

Angular - How to implement a table component with mixed content (data and form inputs)


I'm trying to create a component which has an input field with typeahead and a table. The component will receive as @Input arguments from the parent the name of the columns and reference to a variable which will contain the data. When an element is selected from the typeahead input field, it will be added to the data array, and thus will be showed in the table.

The thing is that, potentially, some of the columns in the table could be not data from the array, but form fields, like a dropdown-list or a text input. Using ng-content would be a good idea, but since the columns of the table that could show form fields instead of data are not fixed, it's not possible, is it? Any ideas on how to implement this?

EDIT

Since it seems not clear what I'm trying to ask, I'll explain it from another point of view: I have a page which has two tables, they all behave very similarly, so I want to refactor my code, creating a component for this tables. Code of the tables, very simplified:

Table 1:

<table>
<thead>
    <tr>
        <th>Article</th>
        <th>Reason</th>
        <th>Claimed</th>
        <th></th>
    </tr>
</thead>
<tbody>
    <tr *ngFor="let article of amountArticles; let i = index">
        <td>{{ article.name }}</td>
        <td>
            <select>
                <option value="tooMuch">Too much</option>
                <option value="tooFew">Too few</option>
                <option value="notRecieved">Not Recieved</option>
            </select>
        </td>
        <td>
            <input type="number" name="claimed">
        </td>
        <td>
            <button type="button (click)="onDeleteAmountArticle(i)">X</button>
        </td>
    </tr>
</tbody>
</table>

Table 2:

<table class="table mt-4">
<thead>
    <tr>
        <th>Article</th>
        <th>Ordered</th>
        <th>Claimed</th>
        <th>Action</th>
        <th></th>
    </tr>
</thead>
<tbody>
    <tr *ngFor="let article of notOrderedArticles; let i = index">
        <td>{{ article.name }}</td>
        <td>{{ article.amount }}</td>
        <td>
            <input type="number" name="claimed">
        </td>
        <td>
            <select>
                <option value="return">Return</option>
                <option value="keep">Keep</option>
            </select>
        </td>
        <td>
            <button type="button (click)="onDeleteNotOrderedArticle(i)">X</button>
        </td>
    </tr>
</tbody>
</table>

As you can see both tables are very similar, but some of the columns have data from the amountArticles or notOrderedArticles and some other different input form fields. How would you refactor this code creating a table component which receives in some way which columns would have data from the articles object and which have HTML code (form inputs), given to the component in a similar way as ng-content works?


Solution

  • Using Angular templates is the way to make this work. It can get quite complex, here's this article I found that helped me a lot.