npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@libs-ui/components-component-outlet

v0.2.357-7

Published

> ⚠️ **DEPRECATED** — Base component cũ để chuẩn hóa input cho dynamic component trong Table/List. Không sử dụng trong code mới.

Readme

@libs-ui/components-component-outlet

⚠️ DEPRECATED — Base component cũ để chuẩn hóa input cho dynamic component trong Table/List. Không sử dụng trong code mới.


⚠️ Deprecation Notice

LibsUiComponentsComponentOutletComponent đã bị deprecated và không nên sử dụng trong code mới.

Hàm getDataComponentOutlet trong cấu hình Table/List hiện đã hỗ trợ truyền input tùy chỉnh trực tiếp vào component mà không cần extend base component. Pattern mới linh hoạt hơn, type-safe hơn và không phụ thuộc vào base class này.


Giới thiệu

LibsUiComponentsComponentOutletComponent là một Angular standalone base component với input duy nhất [item]: TYPE_OBJECT. Trước đây, các custom component dùng trong Table/List cần extend class này để nhận dữ liệu từ getDataComponentOutlet. Kể từ khi getDataComponentOutlet hỗ trợ truyền input tùy chỉnh theo từng component, base class này không còn cần thiết nữa.

Package cũng export type TYPE_COMPONENT_OUTLET_DATA = WritableSignal<TYPE_OBJECT> dùng cho reactive data binding.

Tính năng

  • ✅ Base component với input chuẩn hóa [item] kiểu TYPE_OBJECT
  • ✅ Template rỗng — component con tự định nghĩa template
  • ✅ Standalone component, không cần NgModule
  • ✅ Export TYPE_COMPONENT_OUTLET_DATA type alias

Khi nào sử dụng

🚫 Không sử dụng trong code mới. Xem phần Migration Guide bên dưới.

Lib này chỉ còn giá trị khi:

  • Duy trì code cũ đang extend LibsUiComponentsComponentOutletComponent và chưa có kế hoạch migrate.
  • Cần tham chiếu type TYPE_COMPONENT_OUTLET_DATA từ package này.

Cài đặt

npm install @libs-ui/components-component-outlet

Import

import { LibsUiComponentsComponentOutletComponent } from '@libs-ui/components-component-outlet';
import { TYPE_COMPONENT_OUTLET_DATA } from '@libs-ui/components-component-outlet';

Migration Guide

Cách cũ — Extend base component (❌ Deprecated)

import { Component } from '@angular/core';
import { LibsUiComponentsComponentOutletComponent } from '@libs-ui/components-component-outlet';

// ❌ KHÔNG làm như này trong code mới
@Component({
  selector: 'app-product-cell',
  standalone: true,
  template: `
    <div>
      <strong>{{ item().name }}</strong>
      <span>{{ item().price }}</span>
    </div>
  `,
})
export class ProductCellComponent extends LibsUiComponentsComponentOutletComponent {
  // Kế thừa input 'item: TYPE_OBJECT' từ base component
}
// ❌ getDataComponentOutlet trả về item nguyên xi (không type-safe)
configTemplateText: signal({
  fieldKey: 'id',
  getComponentOutlet: () => of(ProductCellComponent),
  getDataComponentOutlet: (item: any) => item,
})

Cách mới — Standalone component + getDataComponentOutlet (✅ Recommended)

import { Component, input } from '@angular/core';
import { of } from 'rxjs';

// ✅ Standalone component với input tùy chỉnh, KHÔNG extend base
@Component({
  selector: 'app-product-cell',
  standalone: true,
  changeDetection: ChangeDetectionStrategy.OnPush,
  template: `
    <div>
      <strong>{{ product().name }}</strong>
      <span>{{ product().price }}</span>
    </div>
  `,
})
export class ProductCellComponent {
  // Input tùy chỉnh — tên và type hoàn toàn tự do
  readonly product = input.required<{ name: string; price: number }>();
}
// ✅ getDataComponentOutlet map đúng input name và type
configTemplateText: signal({
  fieldKey: 'id',
  getComponentOutlet: () => of(ProductCellComponent),
  getDataComponentOutlet: (item: any) => ({
    product: {
      name: item.productName,
      price: item.salePrice,
    },
  }),
})

Lợi ích của cách mới:

  • Input name tùy chỉnh (product thay vì item) — đặt tên rõ nghĩa theo domain
  • Type-safe với interface cụ thể thay vì TYPE_OBJECT
  • Không phụ thuộc vào base class
  • Dễ test hơn (standalone component thuần)

Ví dụ sử dụng

Ví dụ 1 — Custom status component trong List (Cách mới)

import { Component, input, ChangeDetectionStrategy } from '@angular/core';
import { of } from 'rxjs';

// Bước 1: Tạo standalone component tùy chỉnh
@Component({
  selector: 'app-status-cell',
  standalone: true,
  changeDetection: ChangeDetectionStrategy.OnPush,
  template: `
    <span [class]="statusClass()">{{ label().text }}</span>
  `,
})
export class StatusCellComponent {
  readonly label = input.required<{ text: string; color: string }>();

  protected statusClass = computed(() => {
    const color = this.label().color;
    return color === 'green' ? 'text-green-600 font-medium' : 'text-gray-400';
  });
}

// Bước 2: Dùng trong List config
@Component({
  selector: 'app-order-list',
  standalone: true,
  changeDetection: ChangeDetectionStrategy.OnPush,
  imports: [LibsUiComponentsListComponent],
  template: `
    <libs_ui-components-list [config]="listConfig()" />
  `,
})
export class OrderListComponent {
  protected listConfig = signal({
    type: 'text',
    configTemplateText: signal({
      fieldKey: 'orderId',
      getComponentOutlet: () => of(StatusCellComponent),
      getDataComponentOutlet: (item: any) => ({
        label: {
          text: item.statusText,
          color: item.statusColor,
        },
      }),
    }),
  });
}

Ví dụ 2 — Custom action component trong Table (Cách mới)

import { Component, input, output, ChangeDetectionStrategy } from '@angular/core';
import { of } from 'rxjs';

// Bước 1: Tạo component với output event
@Component({
  selector: 'app-action-cell',
  standalone: true,
  changeDetection: ChangeDetectionStrategy.OnPush,
  template: `
    <button class="text-blue-500 hover:underline" (click)="handlerView($event)">
      Xem {{ row().name }}
    </button>
  `,
})
export class ActionCellComponent {
  readonly row = input.required<{ id: string; name: string }>();
  readonly outView = output<{ id: string; name: string }>();

  protected handlerView(event: Event): void {
    event.stopPropagation();
    this.outView.emit(this.row());
  }
}

// Bước 2: Dùng trong Table config
@Component({
  selector: 'app-user-table',
  standalone: true,
  changeDetection: ChangeDetectionStrategy.OnPush,
  imports: [LibsUiComponentsTableComponent],
  template: `
    <libs_ui-components-table [config]="tableConfig()" />
  `,
})
export class UserTableComponent {
  protected tableConfig = signal({
    columns: signal([
      {
        key: 'action',
        title: 'Thao tác',
        getComponentOutlet: () => of(ActionCellComponent),
        getDataComponentOutlet: (item: any) => ({
          row: { id: item.userId, name: item.fullName },
        }),
      },
    ]),
  });
}

Ví dụ 3 — Duy trì code cũ đang extend base (Legacy)

Chỉ dùng khi chưa kịp migrate. Đặt task refactor sang cách mới.

import { Component } from '@angular/core';
import { LibsUiComponentsComponentOutletComponent } from '@libs-ui/components-component-outlet';
import { of } from 'rxjs';

// Code cũ — vẫn hoạt động nhưng không nên dùng trong code mới
@Component({
  selector: 'app-legacy-cell',
  standalone: true,
  template: `
    <div class="flex items-center gap-2">
      <strong>{{ item().name }}</strong>
      <span class="text-xs text-gray-500">{{ item().id }}</span>
    </div>
  `,
})
export class LegacyCellComponent extends LibsUiComponentsComponentOutletComponent {
  // Kế thừa: readonly item = input.required<TYPE_OBJECT>()
}

// Sử dụng trong List
listConfig = signal({
  configTemplateText: signal({
    fieldKey: 'id',
    getComponentOutlet: () => of(LegacyCellComponent),
    getDataComponentOutlet: (item: any) => item,
  }),
});

@Input()

| Input | Type | Default | Mô tả | Ví dụ | |---|---|---|---|---| | [item] | TYPE_OBJECT | required | Data object truyền vào component. Là required signal input kế thừa từ base. | [item]="rowData()" |

@Output()

Component này không có output. Nếu cần emit event từ dynamic component, khai báo output() trực tiếp trong component tùy chỉnh (không phụ thuộc vào base class).


Types & Interfaces

import { TYPE_COMPONENT_OUTLET_DATA } from '@libs-ui/components-component-outlet';
import { WritableSignal } from '@angular/core';
import { TYPE_OBJECT } from '@libs-ui/interfaces-types';

// TYPE_COMPONENT_OUTLET_DATA là alias cho WritableSignal<TYPE_OBJECT>
// Dùng khi cần typed signal chứa generic object
const data: TYPE_COMPONENT_OUTLET_DATA = signal({ id: 1, name: 'Item A' });

| Type | Definition | Mô tả | |---|---|---| | TYPE_COMPONENT_OUTLET_DATA | WritableSignal<TYPE_OBJECT> | Signal có thể ghi chứa generic object, dùng cho reactive data binding | | TYPE_OBJECT | (từ @libs-ui/interfaces-types) | Generic object type, cho phép truyền bất kỳ cấu trúc object nào |


Lưu ý quan trọng

⚠️ DEPRECATED: Component này đã bị deprecated và sẽ bị xóa trong phiên bản tương lai. Không sử dụng trong code mới.

⚠️ Template rỗng: Base component có template: '' — không render bất kỳ UI nào. Chỉ có tác dụng khi được extend bởi component con tự định nghĩa template.

⚠️ Input bắt buộc: [item]input.required<TYPE_OBJECT>() — phải truyền giá trị khi dùng, nếu không sẽ báo lỗi runtime.

⚠️ Chỉ extend, không dùng trực tiếp: Nếu render <libs_ui-components-component_outlet [item]="data()"> trực tiếp, component sẽ không hiển thị gì cả do template rỗng.


Demo

npx nx serve core-ui

Truy cập: http://localhost:4500/components/component-outlet