# Functional Components

```ts
import { createFunctionalComponent } from 'cx/ui';
```



Functional components provide a simple way to create reusable structures composed of CxJS widgets. Use `createFunctionalComponent` to define a CxJS functional component:

```tsx
import { createModel } from "cx/data";
import type { AccessorChain } from "cx/ui";
import { bind, createFunctionalComponent } from "cx/ui";
import { Button } from "cx/widgets";

interface PageModel {
  count1: number;
  count2: number;
}

const m = createModel<PageModel>();

interface CounterProps {
  value: AccessorChain<number>;
  label: string;
}

const Counter = createFunctionalComponent(({ value, label }: CounterProps) => (
  <div class="flex items-center gap-3 p-3 border rounded">
    <span class="font-medium">{label}:</span>
    <span class="text-lg font-bold" text={bind(value, 0)} />
    <Button
      onClick={(e, { store }) => store.update(value, (v) => (v || 0) + 1)}
    >
      +
    </Button>
    <Button
      onClick={(e, { store }) => store.update(value, (v) => (v || 0) - 1)}
    >
      -
    </Button>
  </div>
));

export default (
  <div class="flex flex-col gap-4">
    <Counter value={m.count1} label="Counter A" />
    <Counter value={m.count2} label="Counter B" />
  </div>
);

```

The `Counter` component can be reused with different props, each instance maintaining its own state through different store bindings.

## Example 2

Functional components are useful for creating reusable chart configurations:

```tsx
import { createFunctionalComponent } from "cx/ui";
import { Svg } from "cx/svg";
import { Chart, Gridlines, LineGraph, NumericAxis } from "cx/charts";

interface LineChartProps {
  data: { x: number; y: number }[];
  chartStyle?: string;
  lineStyle?: string;
  areaStyle?: string;
}

const LineChart = createFunctionalComponent(
  ({ data, chartStyle, lineStyle, areaStyle }: LineChartProps) => (
    <Svg style={chartStyle}>
      <Chart
        offset="20 -20 -40 40"
        axes={{
          x: { type: NumericAxis },
          y: { type: NumericAxis, vertical: true },
        }}
      >
        <Gridlines />
        <LineGraph
          data={data}
          lineStyle={lineStyle}
          area={areaStyle != null}
          areaStyle={areaStyle}
          smooth
          smoothingRatio={0.2}
        />
      </Chart>
    </Svg>
  ),
);

export default (
  <div class="flex flex-col gap-4">
    <LineChart
      chartStyle="height: 200px; background: white; border: 1px solid lightgray"
      lineStyle="stroke: red; stroke-width: 1"
      areaStyle="fill: rgba(255, 0, 0, 0.3)"
      data={Array.from({ length: 50 }, (_, x) => ({
        x,
        y: 75 - 50 * Math.random(),
      }))}
    />
    <LineChart
      chartStyle="height: 200px; background: #1a1a2e; color: gray;"
      lineStyle="stroke: lightgreen; stroke-width: 2"
      data={Array.from({ length: 50 }, (_, x) => ({
        x,
        y: 75 - 50 * Math.random(),
      }))}
    />
    <LineChart
      chartStyle="height: 200px; background: #2e2e4c; color: rgba(255, 255, 255, 0.7);"
      lineStyle="stroke: currentColor; stroke-width: 2"
      data={Array.from({ length: 50 }, (_, x) => ({
        x,
        y: 75 - 50 * Math.random(),
      }))}
    />
  </div>
);

```

The same `LineChart` component renders three different chart styles by passing different props.

## Conditional Logic

Functional components can contain conditional logic:

```tsx
import { createModel } from "cx/data";
import {
  createFunctionalComponent,
  LabelsLeftLayout,
  LabelsTopLayout,
} from "cx/ui";
import { TextField } from "cx/widgets";

interface PageModel {
  form: {
    firstName: string;
    lastName: string;
  };
}

const m = createModel<PageModel>();

interface MyFormProps {
  vertical?: boolean;
}

const MyForm = createFunctionalComponent(({ vertical }: MyFormProps) => {
  let layout = !vertical
    ? LabelsLeftLayout
    : { type: LabelsTopLayout, vertical: true };
  return (
    <div layout={layout}>
      <TextField value={m.form.firstName} label="First Name" />
      <TextField value={m.form.lastName} label="Last Name" />
    </div>
  );
});

export default (
  <div class="flex gap-8 items-center">
    <MyForm />
    <MyForm vertical />
  </div>
);

```

The `vertical` prop changes the layout at render time.

## Reserved Properties

These properties are handled by the framework and should not be used inside the function body:

| Property      | Type         | Description                                                                              |
| ------------- | ------------ | ---------------------------------------------------------------------------------------- |
| `visible`     | `boolean`    | If `false`, the component won't render and its controller won't initialize. Alias: `if`. |
| `controller`  | `Controller` | Controller that will be initialized with the component.                                  |
| `layout`      | `Layout`     | Inner layout applied to child elements.                                                  |
| `outerLayout` | `Layout`     | Outer layout that wraps the component.                                                   |
| `putInto`     | `string`     | Content placeholder name for outer layouts. Alias: `contentFor`.                         |