{"_id":"@alokyn/kyn-form","_rev":"2-2d5aef408af3786acc0acc9130873048","name":"@alokyn/kyn-form","dist-tags":{"latest":"0.1.5"},"versions":{"0.1.0":{"name":"@alokyn/kyn-form","version":"0.1.0","keywords":["angular","form","material","components","library"],"author":{"name":"Alokyn"},"license":"MIT","_id":"@alokyn/kyn-form@0.1.0","maintainers":[{"name":"alokyn","email":"nikol4pantovic@gmail.com"}],"dist":{"shasum":"04a9e3e7fdbcfed65f99ba45f80a32e5811ef6ef","tarball":"https://registry.npmjs.org/@alokyn/kyn-form/-/kyn-form-0.1.0.tgz","fileCount":6,"integrity":"sha512-C+RrmYfxdbn3LwxpJNHUn8jFmsNk33Q2JY02CGVFTIC0thKjWJ/6H9REl7Pa/Nth244Oz+hFGm9saKXnGQHMUw==","signatures":[{"sig":"MEQCIQCT8xrL8z2okdYygqhi2mTA7/bGQt/lnC0fjKTGASMSNAIfYipf8E/yK0i+h5ooqm7GR4wdPbPuEzhigWEsmG0ybA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":76237},"module":"fesm2022/alokyn-kyn-form.mjs","exports":{".":{"types":"./index.d.ts","default":"./fesm2022/alokyn-kyn-form.mjs"},"./package.json":{"default":"./package.json"}},"gitHead":"e92558857012a0bab30befe9e5dbe5f5ca50ba1e","typings":"index.d.ts","_npmUser":{"name":"alokyn","email":"nikol4pantovic@gmail.com"},"_npmVersion":"10.9.2","description":"Angular form components library with Material Design","directories":{},"sideEffects":false,"_nodeVersion":"22.16.0","dependencies":{"tslib":"^2.3.0","ngx-mat-select-search":"^8.0.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"peerDependencies":{"@angular/core":"^20.1.0","@angular/common":"^20.1.0","@angular/material":"^20.1.2"},"_npmOperationalInternal":{"tmp":"tmp/kyn-form_0.1.0_1753264751949_0.380474046983893","host":"s3://npm-registry-packages-npm-production"}},"0.1.5":{"name":"@alokyn/kyn-form","version":"0.1.5","description":"Angular form components library with Material Design","keywords":["angular","form","material","components","library"],"author":{"name":"Alokyn"},"license":"MIT","peerDependencies":{"@angular/common":"^20.1.0","@angular/core":"^20.1.0","@angular/material":"^20.1.2"},"dependencies":{"ngx-mat-select-search":"^8.0.2","tslib":"^2.3.0"},"publishConfig":{"access":"public"},"sideEffects":false,"module":"fesm2022/alokyn-kyn-form.mjs","typings":"index.d.ts","exports":{"./package.json":{"default":"./package.json"},".":{"types":"./index.d.ts","default":"./fesm2022/alokyn-kyn-form.mjs"}},"_id":"@alokyn/kyn-form@0.1.5","gitHead":"eec630a9877b2516ed733e6658baaabf2b008a28","_nodeVersion":"22.14.0","_npmVersion":"10.9.2","dist":{"integrity":"sha512-MOBYyRyeWCcV1v8/ZaGbcI2ZTHGEvLTNoZ+ZTLU5gcXbFqlZ4b9mshxOfHqd0phdcTJBwGkilgXXSvJOQ4sfWQ==","shasum":"c4dd65b5316384f3e862cb28c880a76138d4fa30","tarball":"https://registry.npmjs.org/@alokyn/kyn-form/-/kyn-form-0.1.5.tgz","fileCount":6,"unpackedSize":86863,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDcbyKZCS7jT7sXdJUms+s191kLO+Cxbv77fGkbRm2ZbwIgH0FxRxh8CSUJDCW1BVavhA4BUxqA7q1nlhHjuT2BgbY="}]},"_npmUser":{"name":"alokyn","email":"nikol4pantovic@gmail.com"},"directories":{},"maintainers":[{"name":"alokyn","email":"nikol4pantovic@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/kyn-form_0.1.5_1753287513243_0.1708566106493956"},"_hasShrinkwrap":false}},"time":{"created":"2025-07-23T09:59:11.844Z","modified":"2025-07-23T16:18:33.622Z","0.1.0":"2025-07-23T09:59:12.130Z","0.1.5":"2025-07-23T16:18:33.414Z"},"author":{"name":"Alokyn"},"license":"MIT","keywords":["angular","form","material","components","library"],"description":"Angular form components library with Material Design","maintainers":[{"name":"alokyn","email":"nikol4pantovic@gmail.com"}],"readme":"# Dynamic Form Generation with kyn-form\n\nThis guide explains how to dynamically generate forms in your Angular application using the `<kyn-form>` component. The core principle is to define the form structure, validation, and data within an injectable service. This approach keeps your components lean and focused on business logic, promoting reusability and separation of concerns.\n\n---\n\n## Step 1: Create a Form Configuration Service\n\nThe foundation of a dynamic form is an Angular service that implements the `KynFormConfig` interface. This service must contain a `configureForm()` method, which is responsible for providing the form's entire configuration as an `Observable` stream of form items (`Observable<KynFormItemBase<string>[]>`).\n\nThis architecture seamlessly supports both static form definitions and dynamic configurations populated with data from an API.\n\n## `KynFormItemBase<T>` Configuration Properties\n\nEach object passed into the `formItems` array is an instance of a class that extends `KynFormItemBase<T>`. This base class defines the common properties for all form controls.\n\n| Property | Type | Description |\n| :--- | :--- | :--- |\n| **`key`** | `string` | **Required.** The unique identifier for the form control. This is used as the `formControlName`. |\n| **`label`** | `string` | **Required.** The text label displayed above or next to the form control. |\n| `value` | `T` | The initial value of the form control. |\n| `order` | `number` | A number that determines the display order of the control within the form. Lower numbers appear first. Defaults to `1`. |\n| `controlType` | `string` | The type of control (e.g., 'textbox', 'select'). This is typically set automatically by the specific class you instantiate. |\n| `type` | `string` | The native HTML `type` attribute for an input element (e.g., 'text', 'password', 'email', 'number'). |\n| `placeholder` | `string` | The placeholder text to display inside the input field when it is empty. |\n| `validators` | `any[]` | An array of Angular validator objects (e.g., `{ key: 'minlength', validatorFunc: Validators.minLength(8), message: 'Too short!' }`). |\n| `tooltip` | `string` | Optional text to display in a tooltip icon next to the form control's label for extra guidance. |\n| `className` | `string` | An optional CSS class to apply to the wrapper element of the form control for custom styling. |\n| `templateName` | `string` | The name of a custom template to use for rendering this specific control, allowing for advanced customizations. |\n| `formStyle` | `MatFormFieldAppearance` | Sets the appearance of the Material Form Field. Can be `'outline'`, `'fill'`, `'standard'`, or `'legacy'`. Defaults to `'outline'`. |\n\n---\n\n## `KynFormItemSelect` Configuration Properties\n\nIn addition to the common properties from `KynFormItemBase<T>`, the `KynFormItemSelect` class accepts the following options to customize its behavior.\n\n| Property | Type | Description |\n| :--- | :--- | :--- |\n| **`options`** | `{ key: string; value: string }[]` | **Required.** An array of objects to populate the select dropdown. Each object must have a `key` (the value) and a `value` (the display text). |\n| `multi` | `boolean` | If `true`, allows the user to select multiple options. Defaults to `false`. |\n| `all` | `boolean` | If `multi` is `true`, this adds a \"Select All\" checkbox at the top of the options list. Defaults to `false`. |\n| `allText` | `string` | In multi-select mode, this is the text displayed in the input field when all options are selected. Defaults to `'All'`. |\n| `allTriggerText` | `string` | The label for the \"Select All\" checkbox in the options panel. Defaults to `'Select All'`. |\n| `selectAllByDefault` | `boolean` | If `multi` is `true`, this will pre-select all available options when the form initializes. Defaults to `true`. |\n| `searchDisplayLength`| `number` | If the number of items in `options` exceeds this value, a search bar will be displayed within the select panel to filter options. |\n\n### Example 1: Static Form Configuration\n\nFor forms with fixed fields, such as login or contact forms, you can define the configuration directly within the service. The service creates an array of form control configurations (e.g., `KynFormItemText`, `KynFormItemPassword`, `KynFormItemSelect`) and returns it as an observable using RxJS `of()`.\n\n```typescript\n@Injectable()\nexport class ExampleOneFormService implements KynFormConfig {\n\n  constructor() {}\n\n  configureForm(): Observable<KynFormItemBase<string>[]> {\n    const formItems: KynFormItemBase<string>[] = [\n      // --- Text Input for Email ---\n      new KynFormItemText({\n        key: 'email',\n        label: 'Email',\n        placeholder: 'example@mail.com',\n        validators: [\n          { key: 'email', validatorFunc: Validators.email, message: 'Please enter a valid email address!' },\n          { key: 'required', validatorFunc: Validators.required, message: 'This field is required!' }\n        ],\n        order: 1,\n      }),\n\n      // --- Password Input ---\n      new KynFormItemPassword({\n        key: 'password',\n        label: 'Password',\n        validators: [\n          { key: 'required', validatorFunc: Validators.required, message: 'This field is required!' }\n        ],\n        order: 2,\n      }),\n\n      // --- Select Input with static options ---\n      new KynFormItemSelect({\n        key: 'role',\n        label: 'Role',\n        options: [\n          { key: 'support', value: 'Support' },\n          { key: 'manager', value: 'Manager' },\n          { key: 'owner', value: 'Owner' },\n        ],\n        order: 3,\n      }),\n    ];\n\n    // Return the items sorted by the 'order' property\n    return of(formItems.sort((a, b) => a.order - b.order));\n  }\n}\n```\n### Example 2: Dynamic Form Configuration from a Server\n\nFor more complex scenarios, you can fetch data from an API to dynamically populate form controls.\n\nThis example injects a data service (MockProductService) and uses RxJS operators like pipe and map to transform the fetched data into options for a KynFormItemSelect before constructing the final form configuration.\n\n```typescript\n@Injectable()\nexport class ExampleTwoFormService implements KynFormConfig {\n  private mockProductsService = inject(MockProductService);\n\n  constructor() {}\n\n  configureForm(): Observable<KynFormItemBase<string>[]> {\n    return this.mockProductsService.getProducts().pipe(\n      map((products: Product[]) => {\n        // Transform the API response into options for the select input\n        const productOptions: KynFormItemOptions[] = products.map(product => ({\n          key: product.id,\n          value: product.name\n        }));\n\n        const formItems: KynFormItemBase<string>[] = [\n          new KynFormItemText({\n            key: 'email',\n            label: 'Email',\n            placeholder: 'example@mail.com',\n            validators: [\n              { key: 'email', validatorFunc: Validators.email, message: 'Please enter a valid email address!' },\n              { key: 'required', validatorFunc: Validators.required, message: 'This field is required!' }\n            ],\n            order: 1,\n          }),\n\n          // --- Select Input populated with server data ---\n          new KynFormItemSelect({\n            key: 'products',\n            label: 'Products',\n            placeholder: 'Search product...',\n            multi: true,\n            all: true,\n            selectAllByDefault: true,\n            options: productOptions, // Assign the dynamic options\n            order: 2,\n          })\n        ];\n\n        return formItems.sort((a, b) => a.order - b.order);\n      })\n    );\n  }\n}\n```\n\n## Step 2: Implement the Form in a Component\nAfter creating the service, you can integrate the form into any component with a few simple steps:\n\nProvide the Service: Add your form configuration service to the providers array of your component.\n\nInject the Service: Inject the service instance and call the configureForm() method to get the configuration Observable.\n\nBind to Template: Pass the configuration Observable to the [formItems] input of the <kyn-form> component in your template, using the async pipe to manage the subscription.\n```typescript\n@Component({\n  selector: 'app-some-component',\n  standalone: true,\n  imports: [CommonModule, KynForm],\n  providers: [ExampleOneFormService], // 1. Provide the service\n  templateUrl: './some.component.html',\n})\nexport class SomeComponent {\n  // 2. Inject the service and get the form configuration\n  protected form$ = inject(ExampleOneFormService).configureForm();\n\n  // Define buttons for form actions\n  buttons: KynFormButton[] = [\n    { label: 'Confirm', color: 'primary', action: 'submit' }\n  ];\n\n  // Method to handle the form submission event\n  onSubmit(formValue: any) {\n    console.log('Form Submitted:', formValue);\n    // Add your submission logic here (e.g., API call)\n  }\n}\n\n```\n\n```html\n<h1>Dynamic Form Example</h1>\n\n<div class=\"kyn-container\">\n  <kyn-form\n    className=\"generic-form\"\n    [triggerOnInit]=\"true\"\n    [buttons]=\"buttons\"\n    [formItems]=\"form$ | async\"\n    (onFormSubmit)=\"onSubmit($event)\"\n  />\n</div>\n```\n\n## <kyn-form> Component API\n\nThis section provides an overview of all public `@Input` (Properties) and `@Output` (Events) for the `<kyn-form>` component.\n\n### Properties (`@Input`)\n\n| Property        | Type                                  | Description                                                                                                       |\n| :-------------- | :------------------------------------ | :---------------------------------------------------------------------------------------------------------------- |\n| **`formItems`** | `KynFormItemBase<string>[] \\| null`    | **Required.** An array of configuration objects that defines the form's structure and fields.                     |\n| `buttons`       | `KynFormButton[]`                     | An array of button configuration objects. A button with `action: 'submit'` enables form submission mode.          |\n| `className`     | `string`                              | An optional CSS class added to the form's container `<div>` for custom styling.                                   |\n| `triggerOnInit` | `boolean`                             | If `true`, it will automaticaly emit values. Defaults to `false`.         |\n\n\n\n### Events (`@Output`)\n\n| Event                  | Payload | Description                                                                                                     |\n| :--------------------- | :------ | :-------------------------------------------------------------------------------------------------------------- |\n| `onFormSubmit`         | `any`   | Emits the complete form value when the user clicks a button with `action: 'submit'`.                              |\n| `onFormValueChanges`   | `any`   | Emits the complete form value whenever any field's value changes. This is the default mode if no submit button is provided. |****\n\n---\n\n## ❗ Important Installation Step: Styling\n\nFor the components, especially the custom select dropdown, to be styled correctly, you **must** import the necessary SCSS file into your project's main stylesheet.\n\nAdd the following line to your global `styles.scss` file:\n\n```scss\n// In your main styles.scss file\n\n@use \"@alokyn/kyn-form/src/styles/components/select\";\n","readmeFilename":"README.md"}