Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Json To Form Laravel Package

ambelz/json-to-form

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps to First Use

  1. Install the Package

    composer require ambelz/json-to-form
    

    Add to config/bundles.php:

    Ambelz\JsonToFormBundle\JsonFormBundle::class => ['all' => true],
    
  2. Create a JSON Form Definition Place a JSON file (e.g., config/forms/my-form.json) with the required structure:

    {
      "slug": "my-form",
      "sections": [
        {
          "slug": "user-details",
          "title": "User Details",
          "categories": [
            {
              "slug": "personal",
              "title": "Personal Info",
              "questions": [
                {
                  "key": "name",
                  "type": "text",
                  "label": "Full Name",
                  "required": true
                }
              ]
            }
          ]
        }
      ]
    }
    
  3. Render the Form in a Controller

    use Ambelz\JsonToFormBundle\Service\JsonToFormTransformer;
    
    #[Route('/form', name: 'form')]
    public function showForm(JsonToFormTransformer $transformer): Response
    {
        $json = json_decode(file_get_contents('config/forms/my-form.json'), true);
        $form = $transformer->transform($json, [], $this->createFormBuilder());
        return $this->render('form.html.twig', ['form' => $form->getForm()]);
    }
    
  4. Display the Form in Twig

    {{ form_start(form) }}
        {{ form_widget(form) }}
        <button type="submit">Submit</button>
    {{ form_end(form) }}
    

Implementation Patterns

Workflows

  1. Dynamic Form Generation Use the JsonToFormTransformer service to convert JSON into a Symfony FormBuilder:

    $transformer = $container->get(JsonToFormTransformer::class);
    $form = $transformer->transform($jsonStructure, $initialData, $formBuilder);
    
  2. Live Component Integration Extend ComponentWithFormTrait for real-time updates:

    #[AsLiveComponent('DynamicForm')]
    class DynamicFormComponent extends AbstractController
    {
        use ComponentWithFormTrait;
    
        #[LiveProp]
        public array $jsonStructure;
    
        protected function instantiateForm(): FormInterface
        {
            return $this->jsonToFormTransformer->transform($this->jsonStructure, [], $this->createFormBuilder());
        }
    
        #[LiveAction]
        public function submit()
        {
            $this->submitForm();
            if ($this->getForm()->isValid()) {
                $this->addFlash('success', 'Submitted!');
            }
        }
    }
    
  3. Data Processing Access submitted data via $form->getData():

    $data = $form->getData(); // Returns nested array: ['sectionSlug']['categorySlug']['key'] => value
    

Integration Tips

  • Validation: Leverage Symfony’s constraints in JSON (e.g., "constraints": ["NotBlank", "Length:max=100"]).
  • Custom Field Types: Extend JsonToFormTransformer to support non-standard field types (e.g., custom dropdowns).
  • Translation: Use Symfony’s translation system for labels/errors by referencing translation keys in JSON:
    {
      "label": "app.form.name.label",
      "error_messages": {
        "NotBlank": "app.form.name.error.not_blank"
      }
    }
    

Gotchas and Tips

Pitfalls

  1. JSON Schema Validation The bundle does not validate the JSON structure against STRUCTURE.md. Invalid JSON (e.g., missing sections) will throw runtime errors. Use a validator or lint tool pre-deployment.

  2. Form Data Nesting Submitted data is deeply nested (sectionSlug > categorySlug > key). Flatten it before saving:

    $flatData = array_reduce($data, 'array_merge_recursive', []);
    
  3. Live Component Pitfalls

    • Form Reinitialization: Avoid modifying $jsonStructure after the component mounts; it resets the form.
    • CSRF Tokens: Ensure form_start() includes CSRF protection in non-LiveComponent forms.
  4. Caching The transformer does not cache parsed forms. For large forms, cache the FormInterface instance:

    $form = $cache->get('form_my-form', function() use ($transformer, $json) {
        return $transformer->transform($json, [], $this->createFormBuilder());
    });
    

Debugging

  • Enable Form Debugging Add to config/packages/dev/form.yaml:
    framework:
        form:
            enabled_attributes: true
    
  • Log JSON Errors Wrap transformer calls in a try-catch to log malformed JSON:
    try {
        $form = $transformer->transform($json, [], $builder);
    } catch (\InvalidArgumentException $e) {
        \Log::error("Invalid JSON: " . $e->getMessage());
    }
    

Extension Points

  1. Custom Field Types Override the transformer’s getFieldType() method:

    class CustomJsonToFormTransformer extends JsonToFormTransformer
    {
        protected function getFieldType(array $question): string
        {
            return $question['type'] === 'custom' ? 'text' : parent::getFieldType($question);
        }
    }
    
  2. Post-Transform Hooks Use Symfony’s FormEvent listeners to modify forms after transformation:

    $form->addEventListener(FormEvents::POST_SET_DATA, function (FormEvent $event) {
        $event->getForm()->add('custom_field', TextType::class);
    });
    
  3. Dynamic JSON Loading Fetch JSON from an API or database:

    $json = json_decode($apiClient->request('GET', '/forms/my-form')->getContent(), true);
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle