Code Monkey home page Code Monkey logo

Comments (16)

antonyoneill avatar antonyoneill commented on June 14, 2024

Hey @hugoalexmartins,

Thanks for reaching out to me via email! We actually stopped using liforms very early on, we hit a couple of stumbling blocks and so abandoned the project.

I do intend to revisit the project at a later date as a pet project, and I'd be more than happy to help you out, if I can!

Please be aware that my PR #22 for serialising CollectionTypes as an array wasn't ever merged in, so unless the owners have changed anything it probably is still serialising as a StdObject.

It'd be useful if you could do a var_dump of the Symfony $form variable and post that here.

from liform.

hugoalexmartins avatar hugoalexmartins commented on June 14, 2024

Hey @antonyoneill ,

Thanks you very much for your reply.

Here is the dump($form)

form_dump.txt

Please rename it to .html and you can see all.

from liform.

antonyoneill avatar antonyoneill commented on June 14, 2024

Thanks for sending that over @hugoalexmartins - I've had a look at that form_dump and it looks like you've got a form that has this kind of structure:

  • visaexpress_wizardbundle_wizard type: WizardQuizzType3:
    • wizard_questions, type: CollectionType:
      • 0, type: WizardQuestionType:
        • A sub type (not shown in the dump)
        • A sub type (not shown in the dump)
      • 1, type: WizardQuestionType:
        • A sub type (not shown in the dump)
        • A sub type (not shown in the dump)
      • 2, type: WizardQuestionType:
        • A sub type (not shown in the dump)
        • A sub type (not shown in the dump)

Those subtypes of WizardQuestionType I assume are the types that are coming out for 0 in the schema above question, and helper.

I think you may mean that you expect 3 here:

It should render 5 rows, but I just get one.

I do think that the CollectionType has actually been serialised into the schema correctly, since it wouldn't make a lot of sense if you were to make a schema for each of the entries in the collection type, since they would all be the same - adding more rows (as would naturally be possible) wouldn't have a schema. (#22 is a different issue that I don't think you're experiencing here - and in hindsight I think it may have been a Symfony issue, not liform)

So! I'm not convinced that the issue is with the serialisation of the Form itself!

Can you give me a bit more detail about how you normalise the data (which is what is powering your wizard), and how you are attempting to render the content? I assume you're using the LiformBundle and Symfony Normalizer to normalise the data? And liform-react to render?

Sorry it took so long to get back to you!

from liform.

antonyoneill avatar antonyoneill commented on June 14, 2024

Depending on the answers to how you normalise and render, I might suggest you move this issue into one of the other projects (though I will continue to help you)

from liform.

hugoalexmartins avatar hugoalexmartins commented on June 14, 2024

Hey @antonyoneill

About the 5 rows to render I told you by mistake, in this case it has 3 rows.

I am using LifromBundle and normalize with:
$this->get('liform')->transform($form)

For this case my json response is like this:

{
    "schema": {
        "title": "visaexpress_wizardbundle_wizard",
        "type": "object",
        "properties": {
            "wizard_questions": {
                "type": "array",
                "title": "wizard_questions",
                "items": {
                    "title": "0",
                    "type": "object",
                    "properties": {
                        "wizard_answers": {
                            "type": "array",
                            "title": "wizard_answers",
                            "items": {
                                "title": "0",
                                "type": "object",
                                "properties": {
                                    "value": {
                                        "type": "string",
                                        "title": "Introduza por favor a sua residência igual à que consta no seu passaporte",
                                        "attr": {
                                            "ng-disabled": "false"
                                        },
                                        "propertyOrder": 1
                                    }
                                },
                                "required": [
                                    "value"
                                ]
                            },
                            "propertyOrder": 1
                        }
                    },
                    "required": [
                        "wizard_answers"
                    ]
                },
                "propertyOrder": 1
            }
        },
        "required": [
            "wizard_questions"
        ]
    }
}

It should output 3 rows of wizard_questions.

If I just render the form using Twig (symfony way) all the rows are rendered well, that's why I think it could be something about Liform.

Also, I am using angular-schema-form to render it.

Many thanks for your help.

from liform.

hugoalexmartins avatar hugoalexmartins commented on June 14, 2024

Also, if I remove the Liform transformer and let FOS User transform the response I have is this:

{
    "children": {
        "wizard_questions": {
            "children": [
                {
                    "children": {
                        "wizard_answers": {
                            "children": [
                                {
                                    "children": {
                                        "value": {}
                                    }
                                }
                            ]
                        }
                    }
                },
                {
                    "children": {
                        "wizard_answers": {
                            "children": [
                                {
                                    "children": {
                                        "value": {}
                                    }
                                }
                            ]
                        }
                    }
                },
                {
                    "children": {
                        "wizard_answers": {
                            "children": [
                                {
                                    "children": {
                                        "value": {}
                                    }
                                }
                            ]
                        }
                    }
                },
                {
                    "children": {
                        "wizard_answers": {
                            "children": [
                                {
                                    "children": {
                                        "value": {}
                                    }
                                }
                            ]
                        }
                    }
                },
                {
                    "children": {
                        "wizard_answers": {
                            "children": [
                                {
                                    "children": {
                                        "value": {}
                                    }
                                }
                            ]
                        }
                    }
                },
                {
                    "children": {
                        "wizard_answers": {
                            "children": [
                                {
                                    "children": {
                                        "value": {}
                                    }
                                }
                            ]
                        }
                    }
                },
                {
                    "children": {
                        "wizard_answers": {
                            "children": [
                                {
                                    "children": {
                                        "value": {}
                                    }
                                }
                            ]
                        }
                    }
                }
            ]
        }
    }
}

from liform.

antonyoneill avatar antonyoneill commented on June 14, 2024

Hey @hugoalexmartins
So remember that the Liform::transform() only produces the 'schema' (what the form should look like) and I wouldn't expect it to contain any data..
You'll need to serialise the initial data for the form as well by using the Symfony Normalizer..

In my example, I use a $pageState that I then dump (using twig) into a JavaScript part of the HTML that I then use to render the form.

        /** @var Liform $liform */
        $liform = $this->get('liform');
        $symfonyNormalizer = $this->get('serializer');
        // ... 
        $pageState->formSchema = $liform->transform($form);
        $pageState->formInitial = $symfonyNormalizer->normalize($form);


        return $this->render(
            'MyBundle:Liform/form.html.twig',
            [
                'initialState' => $this->serialiseObjectToJson($pageState),
                // ...
            ]
        );

Then in twig I have

    var container = document.querySelector('#liformEntry')

    var properties = {
        page: '{{ page }}',
        initialState: {{ initialState | raw }},
        additionalState: {}
    }

    MyLiformEntry.init(container, properties)

Which in my case I then feed initialState into the redux store, then get it out when I render the form using liform-react - so you'll use a slightly different way of doing it.

export const MyLiformWrapper = (props: Props) => (
    <Liform
        schema={props.schema} // this comes from initialState.formSchema
        initialValues={props.initial} // this comes from initialState.formInitial
        onSubmit={props.onSubmit}
        baseForm={BaseForm}
        syncValidation={buildSyncValidation(props.schema)}
    />
)

I'm not familiar with the angular-schema-form library..

You'll need to find a way to set the data on the form using your formInitial equivalent. It might be as simple as "updating sf-form"? then calling a redraw see (Updating Form)[https://github.com/json-schema-form/angular-schema-form/blob/development/docs/index.md#updating-form]. I don't know enough about Angular.. 😬

tl;dr: It's important to remember that \Limenius\Liform\Liform::transform only produces the schema. You'll need to use \Symfony\Component\Serializer\Serializer::normalize to get the data into json form.

Remember what I said above about the collection type only storing a single schema, a (prototype)[https://symfony.com/doc/current/reference/forms/types/collection.html#prototype] if you like, for the entities that it represents.

from liform.

antonyoneill avatar antonyoneill commented on June 14, 2024

Here you can see how the ArrayTransformer selects only the first child to represent the rest of them

from liform.

antonyoneill avatar antonyoneill commented on June 14, 2024

Also take a read of this section, it looks like the schema output by liform matches the schema expected by angular-schema-form!
https://github.com/json-schema-form/angular-schema-form/blob/master/docs/index.md#array

So I think your missing piece of the puzzle is setting that initial data (somehow) on the form.

This example might be helpful! https://azimi.me/angular-json-schema-form/demo/demo.html

from liform.

hugoalexmartins avatar hugoalexmartins commented on June 14, 2024

Hey @antonyoneill
Many thanks for your help.

Now I got a better idea of how Liform works.

At first, in my case I need to use a CollectionType, which in the background is dynamic Form for a Wizard, in which I have Questions and I will have User Answers, how do I need to render multiple Questions, I thought they would come from an array to the Schema.
I think what you told me was that Schema is powered by the initialValues in your case, which then tries to be rendered by the React.

In my case, my initialValues will be rendered by Angular Schema Forms, similar to React.

In the background the Symfony serializer will normalize the Object to the Form, am I correct in this statement?

In the meantime I have made my code for Symfony handle the Object for the Form, but it returns empty, is anything more to escape me?

from liform.

hugoalexmartins avatar hugoalexmartins commented on June 14, 2024

Also, can you tell how do you deal with "select boxes"?
I have a json response with two key's one enum and another enum_titles, liform-react handles both arrays ?

from liform.

antonyoneill avatar antonyoneill commented on June 14, 2024

Hey @hugoalexmartins - I was on holiday last week and sick yesterday. Let me get back to you in a couple of days as I have a lot to catch up with at work.

I think your questions come from entities, right? You use the Form to describe how to render the entities/questions on screen – Think of the schema as a template or scaffolding for your form. It only has knowledge to render. It's the normalised entity data that you set in the angular two-way binding that is then drawn onto the screen. For more help with this you should probably get in contact with the angular-schema-form maintainers.

Provided you've set the entity in your form (which you have, judging by the dump you shared) the normaliser should serialise the form data for you automatically. You may then need to do some manipulation to make it the right 'shape' for angular-schema-form.

This liform-react code might help you understand how React renders the select boxes (named ChoiceType here) https://github.com/Limenius/liform-react/blob/master/src/themes/bootstrap3/ChoiceWidget.js

I'll try to get back to you in a few days if you're still struggling.

from liform.

hugoalexmartins avatar hugoalexmartins commented on June 14, 2024

Hey @antonyoneill, I think I've join all the pieces of my puzzle.
But, in the end, I've facing some issue with DEV and PROD environment, which I don't know whats happening, and this is weird.

I am using a form, which will attach the dump, the same one in DEV and PROD, but in PROD it triggers and error:
"Uncaught PHP Exception Limenius\Liform\Exception\TransformerException: "Liform cannot infer the json-schema representation of a an empty Collection or array-like type without the option "allow_add" (to check the proptotype). Evaluating "wizard_questions"" at /Users/hugomartins/projectos/visaexpress/visaExpress/vendor/limenius/liform/src/Limenius/Liform/Transformer/ArrayTransformer.php line 65 {"exception":"[object] (Limenius\Liform\Exception\TransformerException(code: 0): Liform cannot infer the json-schema representation of a an empty Collection or array-like type without the option "allow_add" (to check the proptotype). Evaluating "wizard_questions" at"

I am using exactly the same form, and this is not making any sense to me...

What issue could be this one ?
dumpPROD.txt
dumpDEV.txt

from liform.

antonyoneill avatar antonyoneill commented on June 14, 2024

Hey @hugoalexmartins sorry for the delay, super busy at work at the moment. Will try to get back to you this week. I suspect that you have different package versions installed on dev/prod or there's some obscure setting somewhere. I don't think it'll be a liform issue but some other difference between your environments. Unfortunately as I'm not familiar with your environments I cannot suggest a place to start

from liform.

hugoalexmartins avatar hugoalexmartins commented on June 14, 2024

Hey @antonyoneill its seems be something with embed data into ColletionType, I use PRE_SET_DATA event, to find out which data should be in CollectionType and add "data" options to CollectionType.
This works perfect in DEV, but in PROD CollectionType has no data (and I don't know why), so Liform throw's the exception correctly, because the CollectionType has no data and therefore has no way to generate Array of Questions.
End the end, I added this workaround to ensure data is added to CollectionType in DEV and PROD.

$form->add('wizard_questions', CollectionType::class, array(
          'entry_type' => WizardQuestionType::class,
          'data' => $choices
 ));
      
      
$form->get('wizard_questions')->setData($choices);

Looking to this, it looks like data is added twice, but this only way I can make this work.

from liform.

nacmartin avatar nacmartin commented on June 14, 2024

Hi, sorry for not paying attention so often :(. I am terribly busy and the section that is using Liform in our project has been stable for some time so I have to find time from my spare time to help with these issues and it is being hard. Thanks a lot @antonyoneill for caring ❤️

Basically one thing is the schema and another are the values. The schema is a json-schema representation https://json-schema.org/ and as such for a collection it describes the type of the item in a collection (an array in json-schema), but not each item itself. The schema describes the "shape" of the data, not the actual values. In a collection, the shape is defined by defined how items should be shaped, but the actual items.

The information about the actual values that populate the form, that should contain the values for each item in the collection, is produced independently by this normalizer https://github.com/Limenius/Liform/blob/master/src/Limenius/Liform/Serializer/Normalizer/InitialValuesNormalizer.php

Using something like this: https://github.com/Limenius/symfony-react-sandbox/blob/master/src/Controller/AdminController.php#L45

The distinction between schema and values can be seen clearly here https://mozilla-services.github.io/react-jsonschema-form/ (the extra options they use in their schema are different than in liform but the general idea applies).

from liform.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.