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-inputs-add

v0.2.356-1

Published

> Component cho phép thêm/xóa nhiều input fields động với validation và customization đầy đủ

Readme

@libs-ui/components-inputs-add

Component cho phép thêm/xóa nhiều input fields động với validation và customization đầy đủ

Version: 0.2.355-14

Giới thiệu

LibsUiComponentsInputsAddComponent là một standalone Angular component để quản lý danh sách các input fields động. Component cho phép người dùng thêm/xóa fields, validate từng field riêng biệt, và kiểm tra duplicate values.

Tính năng

  • ✅ Thêm/xóa input fields động
  • ✅ Validation cho từng field riêng biệt
  • ✅ Kiểm tra duplicate values
  • ✅ Min/Max items configuration
  • ✅ Custom button configuration
  • ✅ OnPush Change Detection
  • ✅ Angular Signals
  • ✅ Two-way binding với items array

Khi nào sử dụng

  • Cần nhập nhiều giá trị cùng loại (emails, phone numbers, URLs...)
  • Cho phép người dùng thêm/xóa fields động
  • Cần validation cho từng field riêng biệt
  • Quản lý danh sách inputs với min/max items
  • Cần kiểm tra duplicate values giữa các fields

Important Notes

⚠️ fieldNameBind Required: Phải truyền fieldNameBind để xác định property name trong items array.

⚠️ items Model: items là model (two-way binding), component tự động cập nhật array khi add/remove.

⚠️ Validation Timing: Validation chạy sau 250ms debounce khi value change hoặc remove item.

⚠️ ignoreValidEmptyField: Khi true, chỉ cần ít nhất 1 field có giá trị là valid (không bắt buộc tất cả).

Cài đặt

# npm
npm install @libs-ui/components-inputs-add

# yarn
yarn add @libs-ui/components-inputs-add

Import

import { LibsUiComponentsInputsAddComponent, IInputAdd, IInputAddFunctionControlEvent } from '@libs-ui/components-inputs-add';

@Component({
  standalone: true,
  imports: [LibsUiComponentsInputsAddComponent],
  // ...
})
export class YourComponent {}

Ví dụ

Basic

<libs_ui-components-inputs-add
  [fieldNameBind]="'email'"
  [(items)]="emailItems"
  [placeholder]="'Nhập email'"
  [labelConfig]="{
    labelLeft: 'Email addresses',
    required: true
  }" />
export class ExampleComponent {
  emailItems = signal<Array<IInputAdd>>([{ email: '' }]);
}

Min/Max Items

<libs_ui-components-inputs-add
  [fieldNameBind]="'phone'"
  [(items)]="phoneItems"
  [minItems]="2"
  [maxItems]="10"
  [placeholder]="'Nhập số điện thoại'" />

With Validation & Duplicate Check

<libs_ui-components-inputs-add
  [fieldNameBind]="'url'"
  [(items)]="urlItems"
  [placeholder]="'https://example.com'"
  [validRequired]="{
    isRequired: true,
    message: 'URL is required'
  }"
  [validDuplicate]="{
    message: 'URL already exists'
  }"
  (outValueChange)="onValueChange($event)"
  (outFunctionsControl)="onFunctionsControl($event)" />
export class ExampleComponent {
  urlItems = signal<Array<IInputAdd>>([{ url: '' }]);
  functionControls = signal<IInputAddFunctionControlEvent | null>(null);

  onValueChange(event: IEmitValueChange) {
    console.log('Value changed:', event.value, event.item);
  }

  async validateAll() {
    const isValid = await this.functionControls()?.checkIsValid();
    console.log('Is valid:', isValid);
  }
}

Custom Button & Ignore Empty Field Validation

<libs_ui-components-inputs-add
  [fieldNameBind]="'tag'"
  [(items)]="tagItems"
  [maxItems]="8"
  [ignoreValidEmptyField]="true"
  [addItemButtonConfig]="{
    type: 'button-primary',
    label: 'Add Tag',
    classIconLeft: 'libs-ui-icon-add'
  }"
  [validRequired]="{
    isRequired: true,
    message: 'At least one tag is required'
  }" />

API

libs_ui-components-inputs-add

Inputs

| Property | Type | Default | Description | | ---------------------------------- | -------------------------------- | ----------------------------------------- | ----------------------------------------- | | [acceptNegativeValue] | boolean | false | Cho phép giá trị âm (với dataType number) | | [addItemButtonConfig] | IButton | undefined | Cấu hình button "Add New" | | [autoAddZeroLessThan10InTypeInt] | boolean | false | Tự động thêm số 0 nếu < 10 (kiểu int) | | [autoRemoveEmoji] | boolean | false | Tự động loại bỏ emoji khỏi input | | [backgroundNone] | boolean | false | Sử dụng background trong suốt | | [borderError] | boolean | false | Hiển thị border màu đỏ khi có lỗi | | [classContainerBottomInput] | string | undefined | Class CSS cho container dưới input | | [classContainerInput] | string | undefined | Class CSS cho container bao quanh input | | [classInclude] | string | undefined | Class CSS cho container chính | | [classIncludeInput] | string | undefined | Class CSS cho mỗi input field | | [classMessageErrorInclude] | string | undefined | Class CSS cho message lỗi | | [configItemAddToItems] | IInputAdd | undefined | Template config khi add item mới | | [configUnitLeft] | IInputValidUnitConfig | { fieldKey: "id", fieldLabel: "label" } | Cấu hình hiển thị unit bên trái | | [configUnitRight] | IInputValidUnitConfig | { fieldKey: "id", fieldLabel: "label" } | Cấu hình hiển thị unit bên phải | | [dataType] | TYPE_DATA_TYPE_INPUT | undefined | Loại dữ liệu: text, number, email... | | [defaultHeight] | number | undefined | Chiều cao mặc định | | [disable] | boolean | false | Disable tất cả inputs | | [emitEmptyInDataTypeNumber] | boolean | false | Emit giá trị rỗng khi dataType là number | | [fieldNameBind] | string | required | Tên property trong items array | | [fixedFloat] | number | undefined | Số lượng số lẻ sau dấu phẩy | | [focusTimeOut] | number | undefined | Thời gian delay focus | | [formInputSpacing] | number | 8 | Khoảng cách giữa các input (px) | | [functionValid] | TYPE_FUNCTION_INPUT_VALID | undefined | Hàm validate tùy chỉnh | | [ignoreAddItem] | boolean | false | Ẩn button "Add New" | | [ignoreRemove] | boolean | false | Ẩn button remove | | [ignoreShowError] | boolean | false | Ẩn hiển thị lỗi | | [ignoreStopPropagationEvent] | boolean | false | Không chặn sự kiện lan truyền | | [ignoreUnitRightClassReadOnly] | boolean | false | Bỏ class readonly cho unit phải | | [ignoreValidEmptyField] | boolean | false | Chỉ cần ít nhất 1 field có giá trị | | [ignoreWidthInput100] | boolean | false | Bỏ width 100% cho input | | [isBaselineStyle] | boolean | false | Căn chỉnh baseline items | | [items] | Array<IInputAdd> | required | Array items (model binding) | | [keepPlaceholderOnly] | boolean | false | Chỉ giữ placeholder | | [keySelectedUnitLeft] | any | undefined | Key unit trái đang chọn | | [keySelectedUnitRight] | any | undefined | Key unit phải đang chọn | | [labelConfig] | ILabel | undefined | Cấu hình label cho component | | [leftTemplateItems] | ITemplateRightLeftItem | undefined | Template item bên trái | | [maxItems] | number | 5 | Số lượng items tối đa | | [maxLength] | number | undefined | Độ dài tối đa cho input | | [maxLengthNumberCount] | number | undefined | Max length cho number count | | [maxValueNumber] | number | undefined | Giá trị số tối đa | | [minItems] | number | 1 | Số lượng items tối thiểu | | [minValueNumber] | number | undefined | Giá trị số tối thiểu | | [noBorder] | boolean | false | Không hiển thị border | | [onlyAcceptNegativeValue] | boolean | false | Chỉ chấp nhận số âm | | [paddingRightCustomSpecific] | number | undefined | Custom padding phải | | [placeholder] | string | undefined | Placeholder cho inputs | | [positionMessageErrorStartInput] | boolean | false | Hiển thị lỗi bắt đầu từ input | | [readonly] | boolean | false | Readonly tất cả inputs | | [resetAutoCompletePassword] | boolean | false | Reset autocomplete password | | [resize] | 'auto' \| 'none' | undefined | Khả năng resize | | [rightTemplateItems] | ITemplateRightLeftItem | undefined | Template item bên phải | | [showCount] | boolean | false | Hiển thị đếm ký tự | | [tagInput] | TYPE_TAG_INPUT | undefined | Tag input (textarea, input...) | | [templateLeftBottomInput] | TemplateRef<TYPE_TEMPLATE_REF> | undefined | Template dưới trái input | | [templateLeftOutlet] | TemplateRef<TYPE_TEMPLATE_REF> | undefined | Template outlet bên trái | | [templateRightBottomInput] | TemplateRef<TYPE_TEMPLATE_REF> | undefined | Template dưới phải input | | [templateRightOutlet] | TemplateRef<TYPE_TEMPLATE_REF> | undefined | Template outlet bên phải | | [typeInput] | TYPE_INPUT | undefined | Loại input (text, password...) | | [unitsLeft] | Array<any> | undefined | Danh sách units bên trái | | [unitsRight] | Array<any> | undefined | Danh sách units bên phải | | [useColorModeExist] | boolean | false | Sử dụng color mode có sẵn | | [validDuplicate] | IMessageTranslate | undefined | Message khi có giá trị duplicate | | [validMaxValue] | IMessageTranslate | undefined | Validate giá trị tối đa | | [validMaxLength] | IMessageTranslate | undefined | Validate độ dài tối đa | | [validMinLength] | IValidLength | undefined | Validate độ dài tối thiểu | | [validMinValue] | IMessageTranslate | undefined | Validate giá trị tối thiểu | | [validPattern] | Array<IValidPattern> | undefined | Validate theo pattern regex | | [validRequired] | IValidRequired | undefined | Validation required | | [valuePatternShowError] | boolean | false | Hiển thị lỗi pattern | | [valueUpDownNumber] | number | undefined | Bước nhảy tăng giảm số |

Outputs

| Property | Type | Description | | ----------------------- | ------------------------------- | -------------------------------- | | (outAddItem) | IInputAdd | Emit khi thêm item mới | | (outClickButtonLabel) | IButton | Emit khi click button trên label | | (outFunctionsControl) | IInputAddFunctionControlEvent | Emit function controls | | (outLabelLeftClick) | MouseEvent | Emit khi click label trái | | (outLabelRightClick) | boolean | Emit khi click label phải | | (outRemove) | IInputAdd | Emit khi xóa item | | (outSwitchEventLabel) | ISwitchEvent | Emit sự kiện switch trên label | | (outValueChange) | IEmitValueChange | Emit khi giá trị thay đổi |

FunctionsControl Methods

| Method | Description | | -------------------------- | --------------------------------------------------------- | | checkIsValid() | Kiểm tra validation tất cả items, trả về Promise | | setMessageError(message) | Set error message cho tất cả items |

Types & Interfaces

interface IInputAdd extends Record<string, any> {
  uniqKey?: string;
  disable?: boolean;
  readonly?: boolean;
  ignoreRemove?: boolean;
  labelConfig?: ILabel;
  placeholder?: string;
  maxValueNumber?: number;
  minValueNumber?: number;
  maxLength?: number;

  unitsLeft?: Array<any>;
  configUnitLeft?: IInputValidUnitConfig;
  keySelectedUnitLeft?: any;

  unitsRight?: Array<any>;
  configUnitRight?: IInputValidUnitConfig;
  keySelectedUnitRight?: any;

  templateLeftOutlet?: TemplateRef<TYPE_TEMPLATE_REF>;
  templateRightOutlet?: TemplateRef<TYPE_TEMPLATE_REF>;
  functionControl?: IInputValidFunctionControlEvent;

  [key: string]: any;
}

interface IInputAddFunctionControlEvent {
  checkIsValid: () => Promise<boolean>;
  setMessageError: (message: string) => Promise<void>;
}

interface IEmitValueChange {
  value: string | number;
  item: IInputAdd;
}

Công nghệ

| Technology | Version | Purpose | | --------------- | ------- | ---------------- | | Angular | 18+ | Framework | | Angular Signals | - | State management | | TailwindCSS | 3.x | Styling | | OnPush | - | Change Detection |

Demo

npx nx serve core-ui

Truy cập: http://localhost:4500/inputs/add

Unit Tests

# Chạy tests
npx nx test components-inputs-add

# Coverage
npx nx test components-inputs-add --coverage

# Watch mode
npx nx test components-inputs-add --watch

License

MIT