### Form Field Rendering Example
Source: https://github.com/piying-org/website/blob/master/tg2-en.md
A conceptual example of how a form field might be rendered using a form library's provided component. It highlights the `name` prop for field identification, with other properties omitted for brevity.
```tsx
```
--------------------------------
### TypeScript: Defining Field Presets in Formly.dev
Source: https://github.com/piying-org/website/blob/master/public/docs/client/ngx-formly-migrate.md
Demonstrates the use of field presets in Formly.dev for creating reusable form field configurations. This example defines presets for 'salutation', 'firstName', and 'lastName', simplifying the creation of forms with common structures. It uses `setComponent` and `setWrappers` for customization.
```typescript
{
schema: v.pipe(
v.strictObject({
salutation: v.pipe(
v.string(),
setComponent('salutation'),
setWrappers(['label', 'validator']),
patchProps({ titlePosition: 'top' })
),
firstName: v.pipe(
v.optional(v.string()),
setComponent('firstName'),
setWrappers(['label', 'validator']),
patchProps({ titlePosition: 'top' })
),
lastName: v.pipe(
v.string(),
setComponent('lastName'),
setWrappers(['label', 'validator']),
patchProps({ titlePosition: 'top' })
),
__helper: v.pipe(NFCSchema, setComponent('formHelper'))
})
)
}
```
--------------------------------
### ngx-formly Introduction Example - TypeScript
Source: https://github.com/piying-org/website/blob/master/public/docs/client/ngx-formly-migrate.md
This TypeScript code snippet illustrates the basic structure and usage of ngx-formly, demonstrating field configurations, validation, and conditional display logic. It utilizes RxJS BehaviorSubject for dynamic field properties. Dependencies include RxJS operators and ngx-formly's validation and component-setting utilities.
```typescript
{
context: {
awesomeIsForced: new BehaviorSubject(false),
},
schema: v.pipe(
v.object({
text: v.pipe(
v.string(),
v.title('Text'),
patchAttributes({ placeholder: 'Formly is terrific!' }),
setWrappers(['label', 'validator']),
patchProps({ titlePosition: 'top' }),
),
nested: v.pipe(
v.optional(
v.object({
story: v.pipe(
v.optional(v.string()),
setWrappers(['label', 'validator']),
patchProps({ titlePosition: 'top' }),
setComponent('textarea'),
v.title('Some sweet story'),
layout({ keyPath: ['..', '..'] }),
patchAttributes({
placeholder:
'It allows you to build and maintain your forms with the ease of JavaScript :-)',
}),
patchAsyncProps({
description: (field) =>
field.context.awesomeIsForced.pipe(
map((value) =>
value ? 'And look! This field magically got focus!' : '',
),
),
}),
patchAsyncDirective((field) => ({
type: FocusDirective,
inputs: { focus: field.context.awesomeIsForced },
})),
),
}),
),
),
awesome: v.pipe(
v.optional(v.boolean()),
setWrappers(['label', 'validator']),
patchProps({ titlePosition: 'right' }),
disableWhen({
listen: (fn, field) => field.context.awesomeIsForced,
}),
setComponent('checkbox'),
patchAsyncProps({
title: (field) =>
field.context.awesomeIsForced.pipe(
map((item) =>
item
? 'Too bad, formly is really awesome...'
: 'Is formly totally awesome? (uncheck this and see what happens)',
),
),
}),
),
whyNot: v.pipe(
v.optional(v.string()),
setComponent('textarea'),
v.title('Why Not?'),
patchAttributes({ placeholder: 'Type in here... I dare you' }),
hideWhen({
disabled: true,
listen: (fn) =>
fn({ list: [['#', 'awesome']] }).pipe(
map(({ list: [value] }) => value),
),
}),
patchAsyncAttributes({
placeholder: (field) =>
field.context.awesomeIsForced.pipe(
map((item) =>
item
? `Too bad... It really is awesome! Wasn't that cool?`
: 'Type in here... I dare you',
),
),
}),
setWrappers(['label', 'validator']),
patchProps({ titlePosition: 'top' }),
),
custom: v.pipe(
v.string(),
setComponent('formly-custom-input-1'),
v.title('Custom inlined'),
setWrappers(['label', 'validator']),
patchProps({ titlePosition: 'top' }),
),
__helper: v.pipe(NFCSchema, setComponent('formHelper')),
}),
setComponent('strict_object'),
),
}
```
--------------------------------
### TypeScript: Implementing File Input Component in Formly
Source: https://github.com/piying-org/website/blob/master/public/docs/client/ngx-formly-migrate.md
Provides a Formly.dev example for creating a file input field. This snippet shows how to use `setComponent('fileInput')` to integrate a file upload mechanism into your forms. It handles basic file input, allowing users to select files.
```typescript
{
schema: v.pipe(
v.strictObject({
file: v.pipe(v.any(), setComponent('fileInput')),
__helper: v.pipe(NFCSchema, setComponent('formHelper'))
})
)
}
```
--------------------------------
### Implement Custom Validation - TypeScript
Source: https://github.com/piying-org/website/blob/master/public/docs/client/ngx-formly-migrate.md
This example shows how to implement custom validation logic within Formly.dev using the `v.check` validator. It also demonstrates integrating custom validators with `formConfig` for more complex scenarios.
```typescript
{
schema: v.pipe(
v.strictObject({
ip: v.pipe(
v.string(),
v.ip(),
v.title('IP Address'),
v.check((value) => {
return true;
}),
formConfig({
validators: [
() => {
return undefined;
},
],
}),
setWrappers(['label', 'validator']),
patchProps({ titlePosition: 'top' }),
),
__helper: v.pipe(NFCSchema, setComponent('formHelper')),
}),
),
}
```
--------------------------------
### Get Configuration Instance in Component (TypeScript)
Source: https://github.com/piying-org/website/blob/master/public/docs/client/difference-solid.md
Demonstrates how to import and use `PI_VIEW_FIELD_TOKEN` from `@piying/view-solid` within a Solid.js component to access configuration instances. This requires the `solid-js` library for `useContext`.
```typescript
import { PI_VIEW_FIELD_TOKEN } from "@piying/view-solid";
import { useContext } from "solid-js";
const field = useContext(PI_VIEW_FIELD_TOKEN);
```
--------------------------------
### Tabs Form Formly.dev TypeScript Example
Source: https://github.com/piying-org/website/blob/master/public/docs/client/ngx-formly-migrate.md
This Formly.dev schema demonstrates a tabbed form interface using the 'tabs' component. Similar to the multi-step form, it groups related fields into distinct tabs: 'Personal data', 'Destination', and 'Day of the trip'. The 'stepsLike: true' option is applied to enhance tab behavior.
```typescript
{
model: {},
schema: v.pipe(
v.strictObject({
steps: v.pipe(
v.intersect([
v.pipe(
v.object({
firstname: v.pipe(
v.string(),
v.title('First name'),
setWrappers(['label', 'validator']),
patchProps({ titlePosition: 'top' }),
),
age: v.pipe(
v.number(),
v.title('Age'),
setWrappers(['label', 'validator']),
patchProps({ titlePosition: 'top' }),
),
}),
v.title('Personal data'),
setComponent('strict_object'),
),
v.pipe(
v.object({
country: v.pipe(
v.string(),
v.title('Country'),
setWrappers(['label', 'validator']),
patchProps({ titlePosition: 'top' }),
),
}),
v.title('Destination'),
setComponent('strict_object'),
),
v.pipe(
v.object({
day: v.pipe(
v.string(),
setComponent('date'),
v.title('Day of the trip'),
setWrappers(['label', 'validator']),
patchProps({ titlePosition: 'top' }),
),
}),
v.title('Day of the trip'),
setComponent('strict_object'),
),
]),
setComponent('tabs'),
patchInputs({
stepsLike: true,
}),
),
__helper: v.pipe(NFCSchema, setComponent('formHelper')),
}),
),
}
```
--------------------------------
### Formly TypeScript: Implement Multi-Select
Source: https://github.com/piying-org/website/blob/master/public/docs/client/ngx-formly-migrate.md
This code example demonstrates how to configure a multi-select input field using Formly in TypeScript. It utilizes an array of picklists and sets a custom component for multi-selection. Dependencies include Formly validation, wrappers, and specific Formly components.
```TypeScript
{
schema: v.pipe(
v.strictObject({
marvel4: v.pipe(
v.array(
v.picklist([
'iron_man',
'captain_america',
'black_widow',
'hulk',
'captain_marvel',
]),
),
asControl(),
componentClass('h-[200px]', true),
v.title('Multi-select'),
setComponent('multiselect'),
patchInputs({
options: [
{ label: 'Iron Man', value: 'iron_man' },
{ label: 'Captain America', value: 'captain_america' },
{ label: 'Black Widow', value: 'black_widow' },
{ label: 'Hulk', value: 'hulk' },
{ label: 'Captain Marvel', value: 'captain_marvel' },
],
}),
setWrappers(['label', 'validator']),
patchProps({ titlePosition: 'top' }),
),
__helper: v.pipe(NFCSchema, setComponent('formHelper')),
}),
),
}
```
--------------------------------
### Multi-Step Form Formly.dev TypeScript Example
Source: https://github.com/piying-org/website/blob/master/public/docs/client/ngx-formly-migrate.md
This Formly.dev schema defines a multi-step form using the 'steps' component. The form is divided into 'Personal data', 'Destination', and 'Day of the trip' sections, each with its own fields and validation rules. It utilizes 'v.intersect' to combine multiple object schemas into a sequential, step-by-step form.
```typescript
{
model: {},
schema: v.pipe(
v.strictObject({
steps: v.pipe(
v.intersect([
v.pipe(
v.object({
firstname: v.pipe(
v.string(),
v.title('First name'),
setWrappers(['label', 'validator']),
),
age: v.pipe(
v.number(),
v.title('Age'),
patchProps({ titlePosition: 'top' }),
),
}),
v.title('Personal data'),
setComponent('strict_object'),
),
v.pipe(
v.object({
country: v.pipe(
v.string(),
v.title('Country'),
setWrappers(['label', 'validator']),
patchProps({ titlePosition: 'top' }),
),
}),
v.title('Destination'),
setComponent('strict_object'),
),
v.pipe(
v.object({
day: v.pipe(
v.string(),
setComponent('date'),
v.title('Day of the trip'),
setWrappers(['label', 'validator']),
patchProps({ titlePosition: 'top' }),
),
}),
v.title('Day of the trip'),
setComponent('strict_object'),
),
]),
setComponent('steps'),
),
__helper: v.pipe(NFCSchema, setComponent('formHelper')),
}),
),
}
```
--------------------------------
### Integrate Piying View Component in Applications
Source: https://github.com/piying-org/website/blob/master/public/docs/client/quick-start.md
Demonstrates how to use the Piying View component within different frontend frameworks, including Angular, Vue, React, Svelte, and Solid. It shows the basic HTML structure and the necessary TypeScript/JavaScript code for setup and data binding.
```html
```
```typescript
import { Component, OnInit } from '@angular/core';
import {
patchInputs,
patchWrappers,
setComponent,
} from '@piying/view-angular-core';
import * as v from 'valibot';
import { PiyingView } from '@piying/view-angular';
@Component({
selector: 'app-piying',
templateUrl: './component.html',
imports: [PiyingView],
})
export class PiyingPage {
schema = v.pipe(
v.object({
text1: v.pipe(v.optional(v.string()), v.title('text1-label'),setWrappers(['label'])),
}),
v.title('form'),
setComponent('fieldset')
);
options = {
fieldGlobalConfig: FieldGlobalConfig,
};
modelChagned(event: any) {
console.log(event);
}
}
```
```html
```
```typescript
import * as v from 'valibot';
import { patchWrappers, setComponent, patchInputs } from '@piying/view-core';
import { PiyingView } from '@piying/view-react';
const schema = v.pipe(
v.object({
text1: v.pipe(v.optional(v.string()), v.title('text1-label'), setWrappers(['label'])),
}),
v.title('form'),
setComponent('fieldset')
);
const options = {
fieldGlobalConfig: FieldGlobalConfig,
};
export function PiyingPage() {
function modelChange(event: any) {
console.log(event);
}
return ;
}
```
```html
```
```typescript
import * as v from 'valibot';
import { patchWrappers, setComponent, patchInputs } from '@piying/view-core';
import { PiyingView } from '@piying/view-solid';
const schema = v.pipe(
v.object({
text1: v.pipe(v.optional(v.string()), v.title('text1-label'), setWrappers(['label'])),
}),
v.title('form'),
setComponent('fieldset')
);
const options = {
fieldGlobalConfig: FieldGlobalConfig,
};
export function PiyingPage() {
function modelChange(event: any) {
console.log(event);
}
return (
<>
>
);
}
```
--------------------------------
### Repeating Section Formly.dev TypeScript Example
Source: https://github.com/piying-org/website/blob/master/public/docs/client/ngx-formly-migrate.md
This Formly.dev schema defines a repeating section for a TODO list. It uses validators and component setters to create a dynamic array input where users can add multiple task entries. The schema specifies string inputs for task names and applies array wrappers for 'label' and 'validator'.
```typescript
{
model: { tasks: [''] },
schema: v.pipe(
v.strictObject({
tasks: v.pipe(
v.optional(
v.array(
v.pipe(
v.string(),
patchAttributes({
placeholder: 'Task name',
}),
),
),
),
v.title('TODO LIST'),
setComponent('array-rw'),
setWrappers(['label', 'validator']),
patchProps({ titlePosition: 'top' }),
),
__helper: v.pipe(NFCSchema, setComponent('formHelper')),
}),
),
}
```
--------------------------------
### TypeScript: Material Field Hint Alignment in Formly
Source: https://github.com/piying-org/website/blob/master/public/docs/client/ngx-formly-migrate.md
Illustrates how to control the alignment of hints (start, end, description) in Material Design form fields using Formly.dev. This allows for precise placement of helpful text or error messages within the form. Supports both string and TemplateRef inputs for hints.
```typescript
{
schema: v.pipe(
v.strictObject({
Input: v.pipe(
v.string(),
v.title('Input with string hints'),
patchAttributes({ placeholder: 'Placeholder' }),
patchProps({
hintStart:
'hintStart accepts strings and TemplateRefs and is aligned to start',
hintEnd:
'hintEnd accepts strings and TemplateRefs and is aligned to end'
}),
setWrappers(['formlyField'])
),
Input2: v.pipe(
v.string(),
v.title('Input with template hints'),
patchAttributes({ placeholder: 'Placeholder' }),
patchProps({
hintStart:
'hintStart accepts strings and TemplateRefs and is aligned to start',
hintEnd:
'hintEnd accepts strings and TemplateRefs and is aligned to end'
}),
setWrappers(['formlyField'])
),
Input3: v.pipe(
v.string(),
v.title('Input with description'),
patchAttributes({
placeholder:
'Description field accepts strings and gets aligned to start'
}),
setWrappers(['formlyField'])
),
__helper: v.pipe(NFCSchema, setComponent('formHelper'))
})
)
}
```
--------------------------------
### JsonSchema with Custom Actions (Test Title)
Source: https://github.com/piying-org/website/blob/master/public/docs/client/jsonschema.md
An example of defining custom actions in a JsonSchema. This schema includes an 'actions' field with a 'testTitle' action that takes an empty array of parameters, demonstrating a custom action registration.
```json
{
"type": "string",
"actions": [
{
"name": "testTitle",
"params": []
}
]
}
```
--------------------------------
### Convert Signal Types to Solid Signal (TypeScript)
Source: https://github.com/piying-org/website/blob/master/public/docs/client/difference-solid.md
Provides examples of using `createSignalConvert` to convert general signal types to Solid.js signals, enabling dynamic value changes. This is useful for properties like inputs, outputs, render configuration, attributes, wrappers, and children fetched from a configuration object.
```typescript
const inputs = createSignalConvert(() => field.inputs());
const outputs = createSignalConvert(() => field.outputs());
const renderConfig = createSignalConvert(() => field.renderConfig());
const attributes = createSignalConvert(() => field.attributes());
const wrappers = createSignalConvert(() => field.wrappers());
const fieldChilren = createSignalConvert(() => field.children?.());
```
--------------------------------
### Unsupported JsonSchema Properties Example
Source: https://github.com/piying-org/website/blob/master/public/docs/client/jsonschema.md
Demonstrates JsonSchema properties that are not supported or are considered 'dead ends' during validation. Specifically, 'propertyNames' set to false and 'required' can lead to validation issues.
```json
{
//👎
"propertyNames": false,
"properties": { "a": { "type": "string" } },
//👎
"required": ["a"]
}
```
--------------------------------
### Implement Label Wrapper Component in Vue
Source: https://github.com/piying-org/website/blob/master/public/docs/client/quick-start.md
This Vue.js component utilizes the Composition API with `
{{ props['title'] }}
```
--------------------------------
### Repeating Section with Length Input Formly.dev TypeScript Example
Source: https://github.com/piying-org/website/blob/master/public/docs/client/ngx-formly-migrate.md
This Formly.dev schema implements a repeating section for investments, dynamically controlled by a length input. The number of investment fields adjusts based on the 'investmentsCount' input. It uses 'patchAsyncInputs' to link the array length to form control value changes, ensuring the array size matches the count.
```typescript
{
model: { investmentsCount: 3 },
schema: v.pipe(
v.strictObject({
investmentsCount: v.pipe(
v.optional(v.number(), 3),
v.minValue(1),
v.title('Investments count'),
setWrappers(['label', 'validator']),
patchProps({ titlePosition: 'top' }),
),
investments: v.pipe(
v.array(
v.pipe(
v.string(),
v.title('Name of Investment:'),
setWrappers(['label', 'validator']),
patchProps({ titlePosition: 'top' }),
),
),
patchAsyncInputs({
fixedLength: (field) => {
return field.get(['#', 'investmentsCount'])?.form.control
?.valueChanges;
},
}),
setComponent('array-rw'),
),
__helper: v.pipe(NFCSchema, setComponent('formHelper')),
}),
),
}
```
--------------------------------
### JsonSchema Object Properties Example
Source: https://github.com/piying-org/website/blob/master/public/docs/client/jsonschema.md
A basic JsonSchema defining properties for an object, including types like string, number, and enum constraints. This represents a standard object structure.
```json
{
"properties": {
"k1": { "type": "string" },
"k2": { "type": "number" },
"k3": { "enum": ["1", "2"] }
}
}
```
--------------------------------
### TypeScript: Material Design Prefix and Suffix in Formly Fields
Source: https://github.com/piying-org/website/blob/master/public/docs/client/ngx-formly-migrate.md
Shows how to add Material Design prefix and suffix elements to Formly fields. This enhances user experience by providing visual cues or input aids directly within the form field. It uses a `joinItem` wrapper for seamless integration.
```typescript
{
schema: v.pipe(
v.strictObject({
input: v.pipe(
v.string(),
v.title('Firstname'),
setWrappers([
'label',
'validator',
{
type: 'joinItem',
inputs: {
prefix: { icon: 'face' },
suffix: { text: '$' }
}
}
]),
patchProps({ titlePosition: 'top' })
),
__helper: v.pipe(NFCSchema, setComponent('formHelper'))
})
)
}
```
--------------------------------
### Vue Fieldset Group Component
Source: https://github.com/piying-org/website/blob/master/public/docs/client/quick-start.md
A Vue.js component for grouping fields, using `
```
--------------------------------
### Matching Two Fields in Formly
Source: https://github.com/piying-org/website/blob/master/public/docs/client/ngx-formly-migrate.md
Shows how to validate that two fields, specifically password and confirm password, have matching values. It uses Formly's `v.forward` and `v.partialCheck` to implement cross-field validation.
```typescript
{
schema: v.pipe(
v.strictObject({
password: v.pipe(
v.string(),
v.title('Password'),
setWrappers(['label', 'validator']),
patchProps({ titlePosition: 'top' }),
patchAttributes({
type: 'password',
placeholder: 'Must be at least 3 characters',
}),
v.minLength(3),
),
passwordConfirm: v.pipe(
v.string(),
v.title('Confirm Password'),
setWrappers(['label', 'validator']),
patchProps({ titlePosition: 'top' }),
patchAttributes({
type: 'password',
placeholder: 'Please re-enter your password',
}),
),
__helper: v.pipe(NFCSchema, setComponent('formHelper')),
}),
v.forward(
v.partialCheck(
[['password'], ['passwordConfirm']],
(input) => input.password === input.passwordConfirm,
'The two passwords do not match.',
),
['passwordConfirm'],
),
),
}
```
--------------------------------
### Get Configuration Instance in Component (TypeScript)
Source: https://github.com/piying-org/website/blob/master/public/docs/client/difference-svelte.md
This snippet demonstrates how to retrieve a configuration instance within a Svelte component using `getContext` and the `PI_VIEW_FIELD_TOKEN`. It is essential for accessing component-specific settings and properties.
```typescript
import { PI_VIEW_FIELD_TOKEN } from "@piying/view-svelte";
import { getContext } from "svelte";
const field = getContext(PI_VIEW_FIELD_TOKEN);
```
--------------------------------
### Implement Built-in Validations - TypeScript
Source: https://github.com/piying-org/website/blob/master/public/docs/client/ngx-formly-migrate.md
This code illustrates the use of various built-in validation rules in Formly.dev, including required fields, minimum and maximum values for numbers, minimum and maximum lengths for strings, and pattern matching for IP addresses.
```typescript
{
schema: v.pipe(
v.strictObject({
name: v.pipe(
v.string(),
v.title('Name (required)'),
setWrappers(['label', 'validator']),
patchProps({ titlePosition: 'top' }),
),
age: v.pipe(
v.number(),
v.title('Age (min= 18, max= 40)'),
v.minValue(18),
v.maxValue(40),
setWrappers(['label', 'validator']),
patchProps({ titlePosition: 'top' }),
),
password: v.pipe(
v.string(),
v.title('Password (minLength = 6)'),
v.minLength(6),
setWrappers(['label', 'validator']),
patchProps({ titlePosition: 'top' }),
),
comment: v.pipe(
v.string(),
setComponent('textarea'),
v.title('Comment (maxLength = 100)'),
v.maxLength(100),
patchAttributes({ rows: 5 }),
setWrappers(['label', 'validator']),
patchProps({ titlePosition: 'top' }),
),
ip: v.pipe(
v.string(),
v.title('IP Address (pattern = /(d{1,3}.){3}d{1,3}/)'),
v.ipv4(),
setWrappers(['label', 'validator']),
patchProps({ titlePosition: 'top' }),
),
__helper: v.pipe(NFCSchema, setComponent('formHelper')),
}),
),
}
```
--------------------------------
### TypeScript: Implement Nested Formly Forms with fieldGroup Wrapper
Source: https://github.com/piying-org/website/blob/master/public/docs/client/ngx-formly-migrate.md
Demonstrates how to create nested forms in Formly.dev using the `fieldGroup` wrapper. This allows for structured and organized form layouts, especially for complex data objects. It utilizes validation pipes and component wrappers for enhanced field behavior.
```typescript
{
schema: v.pipe(
v.strictObject({
firstName: v.pipe(
v.string(),
v.title('First Name'),
setWrappers(['label', 'validator']),
patchProps({ titlePosition: 'top' })
),
address: v.pipe(
v.object({
town: v.pipe(
v.string(),
v.title('Town'),
setWrappers(['label', 'validator']),
patchProps({ titlePosition: 'top' })
)
}),
v.title('Address'),
setWrappers(['panel'])
),
__helper: v.pipe(NFCSchema, setComponent('formHelper'))
})
)
}
```
--------------------------------
### Formly TypeScript: Implement Normal Select
Source: https://github.com/piying-org/website/blob/master/public/docs/client/ngx-formly-migrate.md
This snippet demonstrates how to create a basic select input field using Formly in TypeScript. It defines a picklist of options for a Marvel character selection. Dependencies include Formly's validation and formly wrappers.
```TypeScript
{
schema: v.pipe(
v.strictObject({
marvel1: v.pipe(
v.picklist([
'iron_man',
'captain_america',
'black_widow',
'hulk',
'captain_marvel',
]),
setWrappers(['label', 'validator']),
patchProps({ titlePosition: 'top' }),
v.title('Normal Select'),
patchInputs({
options: [
{ label: 'Iron Man', value: 'iron_man' },
{ label: 'Captain America', value: 'captain_america' },
{ label: 'Black Widow', value: 'black_widow' },
{ label: 'Hulk', value: 'hulk' },
{ label: 'Captain Marvel', value: 'captain_marvel' },
],
}),
),
__helper: v.pipe(NFCSchema, setComponent('formHelper')),
}),
),
}
```
--------------------------------
### TypeScript: Creating Interactive Buttons in Formly.dev
Source: https://github.com/piying-org/website/blob/master/public/docs/client/ngx-formly-migrate.md
Demonstrates how to implement interactive buttons within Formly.dev forms. This includes creating buttons that trigger alerts or update other form fields upon click. It showcases the use of `setComponent('button')` and `mergeOutputs` for handling click events.
```typescript
{
schema: v.pipe(
v.strictObject({
__btn1: v.pipe(
NFCSchema,
setComponent('button'),
patchInputs({ label: 'With Function' }),
mergeOutputs({
clicked: () => {
alert('You clicked me!');
}
})
),
__btn2: v.pipe(
NFCSchema,
setComponent('button'),
patchInputs({ label: 'JSON Only', classStyle: 'btn-info' }),
v.title('Click this guy'),
mergeOutputs({
clicked: (event, field) => {
field.get(['#', 'someInput']).form.control.updateValue('clicked!');
}
}),
patchProps({
description: 'These can have labels and stuff too if you want....'
})
),
someInput: v.pipe(
v.string(),
v.title('Some Input'),
setWrappers(['label', 'validator']),
patchProps({ titlePosition: 'top' })
),
__helper: v.pipe(NFCSchema, setComponent('formHelper'))
})
)
}
```
--------------------------------
### JsonSchema with Custom Actions (Set Component)
Source: https://github.com/piying-org/website/blob/master/public/docs/client/jsonschema.md
Shows how to define custom actions within a JsonSchema item. This example uses the 'actions' field to specify a 'setComponent' action with 'radio' as a parameter, likely for UI component control.
```json
{
"type": "string",
"title": "Select 4: Radio button",
"enum": ["Option 1", "Option 2", "Option 3"],
"actions": [
{
"name": "setComponent",
"params": ["radio"]
}
]
}
```
--------------------------------
### Convert Signal to Ref for Dynamic Updates (TypeScript)
Source: https://github.com/piying-org/website/blob/master/public/docs/client/difference-react.md
Illustrates the usage of the `useSignalToRef` hook to convert signal values into ref objects. This is necessary for signal types to support dynamic updates when interacting with refs, as shown with examples for inputs, outputs, render config, attributes, wrappers, and children.
```typescript
const inputs = useSignalToRef(props.field, (field) => field.inputs());
const outputs = useSignalToRef(props.field, (field) => field.outputs());
const renderConfig = useSignalToRef(props.field, (field) => field.renderConfig());
const attributes = useSignalToRef(props.field, (field) => field.attributes());
const wrappers = useSignalToRef(props.field, (field) => field.wrappers());
const fieldChilren = useSignalToRef(props.field, (field) => field.children?.());
```
--------------------------------
### TypeScript: Configure Model Update Options in Formly.dev
Source: https://github.com/piying-org/website/blob/master/public/docs/client/ngx-formly-migrate.md
Shows how to customize when a form model updates in Formly.dev using `formConfig`. This includes debouncing input, updating on blur, and updating on submit. It demonstrates the use of RxJS operators like `debounceTime` and the `updateOn` option.
```typescript
{
schema: v.pipe(
v.strictObject({
text: v.pipe(
v.string(),
v.title('Debounce'),
formConfig({ pipe: { toModel: pipe(debounceTime(2000)) } }),
setWrappers(['label', 'validator']),
patchProps({ titlePosition: 'top' }),
),
updateOnBlur: v.pipe(
v.string(),
formConfig({ updateOn: 'blur' }),
v.title('`updateOn` on Blur'),
setWrappers(['label', 'validator']),
patchProps({ titlePosition: 'top' }),
),
updateOnSubmit: v.pipe(
v.string(),
formConfig({ updateOn: 'submit' }),
v.title('`updateOn` on Submit'),
setWrappers(['label', 'validator']),
patchProps({ titlePosition: 'top' }),
),
__helper: v.pipe(
NFCSchema,
setComponent('formHelper'),
patchInputs({ forceEnableSubmit: true }),
),
}),
),
}
```
--------------------------------
### 安装 Plying ORM 和 Valibot
Source: https://github.com/piying-org/website/blob/master/public/docs/orm/quick-start.md
使用 npm 安装 Plying ORM 和 Valibot 库。这些是开始使用 Plying ORM 所必需的基础依赖。
```bash
npm i valibot
npm i @piying/orm
```
--------------------------------
### i18n with ngx-translate in TypeScript
Source: https://github.com/piying-org/website/blob/master/public/docs/client/ngx-formly-migrate.md
This snippet demonstrates how to configure internationalization using ngx-translate within a TypeScript Formly setup. It defines language contexts and dynamically updates field titles based on the selected language. Dependencies include Formly and ngx-translate.
```typescript
{
context: {
lang: {
en: {
'FORM.LANG': 'Change language',
'FORM.NAME': 'Name',
},
fr: { 'FORM.LANG': 'Changer la langue', 'FORM.NAME': 'Nom' },
},
},
schema: v.pipe(
v.strictObject({
lang: v.pipe(
v.picklist(['fr', 'en']),
patchInputs({
options: [
{ label: 'fr', value: 'fr' },
{ label: 'en', value: 'en' },
],
}),
valueChange((fn, field) => {
fn().subscribe(({ list: [value] }) => {
if (!value) {
return;
}
v.setGlobalConfig({ lang: value });
});
}),
patchAsyncProps({
title: (field) => {
return field.form.control?.valueChanges.pipe(
map((item) => {
if (!item) {
return;
}
return field.context.lang[item]['FORM.LANG'];
}),
);
},
}),
setWrappers(['label', 'validator']),
patchProps({ titlePosition: 'top' }),
),
name: v.pipe(
v.string(),
patchAsyncProps({
title: (field) => {
return field.get(['#', 'lang'])?.form.control?.valueChanges.pipe(
map((item) => {
if (!item) {
return;
}
return field.context.lang[item]['FORM.NAME'];
}),
);
},
}),
setWrappers(['label', 'validator']),
patchProps({ titlePosition: 'top' }),
),
__helper: v.pipe(NFCSchema, setComponent('formHelper')),
}),
),
}
```
--------------------------------
### Form Initialization with useForm Hook
Source: https://github.com/piying-org/website/blob/master/tg2-en.md
Illustrates the initialization of a form using a `useForm` hook, likely from a form management library. It shows setting default values and defining an asynchronous submission handler.
```typescript
const form = useForm({
defaultValues: {
firstName: "default",
},
onSubmit: async ({ value }) => {
console.log(value);
},
});
```
--------------------------------
### Disable Submit Button in Formly
Source: https://github.com/piying-org/website/blob/master/public/docs/client/ngx-formly-migrate.md
Provides an example of how to disable a submit button based on the validity of a required text field. It uses a simple check to ensure the text field has a value before enabling the submit action.
```typescript
{
schema: v.pipe(
v.strictObject({
text: v.pipe(
v.string(),
v.check((a) => !!a),
v.title('Text'),
setWrappers(['label', 'validator']),
patchProps({ titlePosition: 'top' }),
patchAttributes({ placeholder: 'This is required!' }),
),
__helper: v.pipe(NFCSchema, setComponent('formHelper')),
}),
),
}
```
--------------------------------
### TypeScript: Reset Form Model in Formly.dev
Source: https://github.com/piying-org/website/blob/master/public/docs/client/ngx-formly-migrate.md
Provides an example of how to define a form schema in Formly.dev that supports resetting the model. This involves defining fields with their respective validators, titles, and input options, allowing for a clean state.
```typescript
{
schema: v.strictObject({
text: v.pipe(
v.string(),
v.title('Some awesome text'),
patchAttributes({
placeholder: 'Some sweet text',
}),
setWrappers(['label', 'validator']),
patchProps({ titlePosition: 'top' }),
),
candy: v.pipe(
v.optional(v.picklist(['snickers', 'baby_ruth', 'milky_way'])),
patchInputs({
options: [
{ label: 'Snickers', value: 'snickers' },
{ label: 'Baby Ruth', value: 'baby_ruth' },
{ label: 'Milky Way', value: 'milky_way' },
],
}),
setWrappers(['label', 'validator']),
patchProps({ titlePosition: 'top' }),
v.title('Multiple Options'),
),
}),
}
```
--------------------------------
### TypeScript: Conditionally Hide Fields in Formly.dev
Source: https://github.com/piying-org/website/blob/master/public/docs/client/ngx-formly-migrate.md
Illustrates how to hide form fields dynamically in Formly.dev based on other field values. This example uses the `hideWhen` configuration, which takes a condition based on field values to determine visibility.
```typescript
{
schema: v.pipe(
v.object({
name: v.pipe(
v.optional(v.string()),
setWrappers(['label', 'validator']),
patchProps({ titlePosition: 'top' }),
v.title('Name'),
patchAttributes({
placeholder: 'Type in here to display the hidden field',
}),
),
iLikeTwix: v.pipe(
v.optional(v.boolean()),
setWrappers(['label', 'validator']),
patchProps({ titlePosition: 'right' }),
setComponent('checkbox'),
v.title('I like twix'),
hideWhen({
disabled: true,
listen: (fn) => {
return fn({ list: [['#', 'name']] }).pipe(
map(({ list: [value] }) => !value),
);
},
}),
),
__helper: v.pipe(NFCSchema, setComponent('formHelper')),
}),
setComponent('strict_object'),
),
}
```
--------------------------------
### Register Components with Piying Framework (TypeScript)
Source: https://github.com/piying-org/website/blob/master/public/docs/client/quick-start.md
Defines global configuration for component registration, supporting lazy loading. This configuration object specifies the types and wrappers for components that will be used within the Piying framework.
```typescript
export const FieldGlobalConfig = {
types: {
string: {
type: InputFCC,
},
fieldset: {
type: FieldsetFGC,
},
},
wrappers: {
label: {
type: LabelWC,
},
},
} as PiViewConfig;
```
--------------------------------
### Applying Wrappers for Field Enhancements
Source: https://github.com/piying-org/website/blob/master/tg2-en.md
Shows how to attach metadata like labels or validation hints to schema fields using the `setWrappers` function in conjunction with schema definitions.
```typescript
v.pipe(v.number(), v.title("k2-label"), setWrappers(["label"]));
```
--------------------------------
### Formly TypeScript: Implement Grouped Select
Source: https://github.com/piying-org/website/blob/master/public/docs/client/ngx-formly-migrate.md
This example shows how to create a select input with grouped options in Formly using TypeScript. It categorizes Marvel characters into 'Male' and 'Female' groups. This requires Formly's validation and wrapper functionalities.
```TypeScript
{
schema: v.pipe(
v.strictObject({
marvel2: v.pipe(
v.picklist([
'iron_man',
'captain_america',
'black_widow',
'hulk',
'captain_marvel',
]),
setWrappers(['label', 'validator']),
patchProps({ titlePosition: 'top' }),
v.title('Grouped Select'),
patchInputs({
options: [
{
label: 'Male',
type: 'group',
children: [
{ label: 'Iron Man', value: 'iron_man' },
{ label: 'Captain America', value: 'captain_america' },
{ label: 'Hulk', value: 'hulk' },
],
},
{
label: 'Female',
type: 'group',
children: [
{ label: 'Black Widow', value: 'black_widow' },
{ label: 'Captain Marvel', value: 'captain_marvel' },
],
},
],
}),
),
__helper: v.pipe(NFCSchema, setComponent('formHelper')),
}),
),
}
```
--------------------------------
### 定义 TypeORM 实体和 ORM 实例 (TypeScript)
Source: https://github.com/piying-org/website/blob/master/public/docs/orm/quick-start.md
使用 Valibot 定义 TypeORM 实体,并将其转换为 Plying ORM 的数据源实例。此示例展示了如何声明 'Account' 实体,包括主键、创建/更新日期、用户名等字段,并配置 SQLite 数据源。
```typescript
import { convert, column, columnPrimaryKey } from "@piying/orm/typeorm";
import * as v from 'valibot';
export const Account = v.pipe(
v.object({
id: v.pipe(v.string(), columnPrimaryKey({ generated: "uuid" })),
createdAt: v.pipe(v.date(), column({ createDate: true })),
updateAt: v.pipe(v.date(), column({ updateDate: true })),
username: v.pipe(v.string(), v.title("用户名"), column({ length: 50 })),
}),
);
const instance = convert(
{
Account,
},
{
dataSourceOptions: {
type: "better-sqlite3",
database: path.join(process.cwd(), ".tmp", "data.sqlite"),
synchronize: false,
logging: true,
},
},
);
await instance.dataSource.initialize();
result.object.Account;
```
--------------------------------
### Render Valibot Schemas with PiyingView in Angular
Source: https://context7.com/piying-org/website/llms.txt
Demonstrates rendering a Valibot schema as an interactive Angular form using the PiyingView component. It includes custom component settings, input configurations, and validation logic. Dependencies include '@piying/view-angular' and 'valibot'.
```typescript
import { Component } from '@angular/core';
import { PiyingView } from '@piying/view-angular';
import { FieldGlobalConfig } from './component/define';
import { CustomNgBuilder } from './component/form/custom.builder';
import * as v from 'valibot';
import { setComponent, setInputs, patchAttributes } from '@piying/view-angular-core';
@Component({
selector: 'app-registration',
standalone: true,
imports: [PiyingView],
template: '
'
})
export class RegistrationFormComponent {
schema = v.pipe(
v.object({
salutation: v.pipe(
v.string(),
v.title('Salutation'),
setComponent('dropdown'),
setInputs({
options: [
{ label: 'Mr.', value: 'mr' },
{ label: 'Ms.', value: 'ms' },
{ label: 'Dr.', value: 'dr' }
]
})
),
firstName: v.pipe(
v.string(),
v.title('First Name'),
v.minLength(2, 'Minimum 2 characters')
),
lastName: v.pipe(
v.string(),
v.title('Last Name'),
v.minLength(2, 'Minimum 2 characters')
),
email: v.pipe(
v.string(),
v.email('Invalid email format'),
v.title('Email Address')
),
phone: v.pipe(
v.string(),
v.title('Phone Number'),
patchAttributes({
type: 'tel',
placeholder: '+1 (555) 123-4567'
})
),
birthdate: v.pipe(
v.string(),
v.title('Date of Birth'),
setComponent('date')
),
newsletter: v.pipe(
v.boolean(),
v.title('Subscribe to newsletter'),
setComponent('toggle')
)
}),
setComponent('fieldset')
);
model = {
newsletter: false
};
options = {
fieldGlobalConfig: FieldGlobalConfig,
builder: CustomNgBuilder
};
onModelChange(newModel: any) {
console.log('Form values changed:', newModel);
// Handle form submission or validation
if (this.isValidModel(newModel)) {
this.submitForm(newModel);
}
}
isValidModel(model: any): boolean {
try {
v.parse(this.schema, model);
return true;
} catch (error) {
return false;
}
}
async submitForm(model: any) {
try {
const response = await fetch('/api/register', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(model)
});
const data = await response.json();
console.log('Registration successful:', data);
} catch (error) {
console.error('Registration failed:', error);
}
}
}
```