How do I create an input that has options coming from the api?

I need to create a custom component that has a select input where the user selects the product they want, and this list of products loaded through an api, is it possible to do this?

Example:

{
          name: 'product',
          friendlyName: 'Produto',
          enum: [
            {
              label: 'Product 1',
              value: 'product-1',
            },
            {
              label: 'Product 2',
              value: 'product-2',
            },
          ],
          type: 'string',
        }

Remembering: the enum options need to come from an api

Hey @yanzaum welcome to Builder Forum.
To create a custom component in Builder.io that loads product options from an API for a select input, you can use a custom component with a dynamic enum property. Here’s how you can achieve this:

Step 1: Define the Custom Component

First, you need to define your custom component in Builder.io. Here is an example of a custom component configuration that fetches products from an API and populates the select input:

import React, { useEffect, useState } from 'react';
import { Builder } from '@builder.io/react';

// Custom component definition
const ProductSelect = (props) => {
  const [products, setProducts] = useState([]);

  useEffect(() => {
    // Replace with your actual API URL
    fetch('https://api.example.com/products')
      .then(response => response.json())
      .then(data => {
        const productOptions = data.map(product => ({
          label: product.name,
          value: product.id
        }));
        setProducts(productOptions);
      });
  }, []);

  return (
    <div>
      <label>{props.friendlyName}</label>
      <select
        name={props.name}
        value={props.value}
        onChange={e => props.onChange(e.target.value)}
      >
        {products.map(product => (
          <option key={product.value} value={product.value}>
            {product.label}
          </option>
        ))}
      </select>
    </div>
  );
};

Step 2: Register the Custom Component in Builder.io

Make sure to register the component with Builder.io in your application entry point:

import { Builder } from '@builder.io/react';
import ProductSelect from './components/ProductSelect';

Builder.registerComponent(ProductSelect, {
  name: 'ProductSelect',
  inputs: [
    {
      name: 'name',
      type: 'string',
      friendlyName: 'Name',
    },
    {
      name: 'friendlyName',
      type: 'string',
      friendlyName: 'Friendly Name',
    },
    {
      name: 'value',
      type: 'string',
      friendlyName: 'Value',
    },
  ],
});

Step 3: Use the Custom Component in Builder.io Editor

Now, you can use this custom component in the Builder.io editor. Drag and drop the ProductSelect component into your page and configure the name and friendlyName properties as needed.

This approach allows you to dynamically load the options for the select input from an API, making your component highly flexible and adaptable to changes in your product list.

Example API Response

Ensure your API returns data in the following format for this example to work correctly:

[
  {
    "id": "product-1",
    "name": "Product 1"
  },
  {
    "id": "product-2",
    "name": "Product 2"
  }
]

By following these steps, you can create a dynamic product selection component in Builder.io that fetches product data from an API and populates a select input accordingly.

Thank you for your answer, but my intention is to create a select style custom input that takes it through an api and displays it as an option in this select, so that I can use it when creating a custom component as shown in the attached image.

Hey @yanzaum here is the updated code that creates the custom component with enum fetching the values from your API endpoint-

//product.tsx
import React, { useEffect, useState } from 'react';

interface Product {
  value: number;
  label: string;
}

interface ProductProps {
  productItem?: Product[];
}

const Product: React.FC<ProductProps> = ({ productItem = [] }) => {
  const [products, setProducts] = useState<Product[]>(productItem);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    const fetchProducts = async () => {
        try {
          const response = await fetch('Your API endpoint');
          if (!response.ok) {
            throw new Error('Network response was not ok');
          }
          const data: Product[] = await response.json();
          setProducts(data);
          setLoading(false);
        } catch (error) {
          setError((error as Error).message);
          setLoading(false);
        }
      };

    fetchProducts();
  }, []);

  if (loading) {
    return <div>Loading...</div>;
  }

  if (error) {
    return <div>Error: {error}</div>;
  }

  return (
    <div>
      <select>
        {products.map((product, index) => (
          <option key={index} value={product.value}>
            {product.label}
          </option>
        ))}
      </select>
    </div>
  );
};

export default ProductApi;

The registration would look something like this -

name: 'Product',
  inputs: [
    {
      name: 'Product',
      type: 'enum',
      enum: [], // This can remain as an empty array if you don't need static products
      defaultValue: [],
    },
  ],

Let me know if this works for you.

It’s still not enough, I need to use my custom component as an input for another component, that is, instead of receiving the productId via text, I want there to be a select for the user to select the product,

Hey @yanzaum, here is our doc on Custom types with component inputs for a detailed guide on how you can achieve this.