Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is binding to nested field of a list record supported ? #16

Open
albert-kam opened this issue Aug 28, 2020 · 4 comments
Open

Is binding to nested field of a list record supported ? #16

albert-kam opened this issue Aug 28, 2020 · 4 comments

Comments

@albert-kam
Copy link

albert-kam commented Aug 28, 2020

Hi,

Does formio currently support binding a nested list of nestable objects ?

For example i have this mapping:

// MyExample has name and myClasses(List<MyClass>), 
// and MyClass has these fields: name, gender and nestedOnes(List<MyClass>)
FormMapping<MyExample> formMapping = FormUtil.basicBuilder(MyExample.class, "example",
			"name")
		.nested(Forms.basic(MyClass.class, "myClasses", MappingType.LIST)
				.fields("name", "gender")
				.nested(Forms.basic(MyClass.class, "nestedOnes", MappingType.LIST)
							.fields("name", "gender")
							.build())
				.build())
		.build();

And then this tests okay, because it's not trying to bind to the nested props of the list:

@Test
public void testBinding_myClasses() {
	FormData<MyExample> fdata = formMapping.bind(UndertowRequestParams.builder_withBindingPrefix("example")
			.addFormData("name", "Mora Moonsinger")
			.addFormData("myClasses[0]-name", "Kathris Starsong")
			.addFormData("myClasses[0]-gender", "FEMALE")
			.addFormData("myClasses[1]-name", "Adora Nightshade")
			.addFormData("myClasses[1]-gender", "FEMALE")
			.build()
			.debug());
	
	assertEquals(MyExample.builder()
			.withName("Mora Moonsinger")
			.withMyClasses(Lists.newArrayList(
				MyClass.builder()
					.withGender(Gender.FEMALE)
					.withName("Kathris Starsong")
					.build(),
				MyClass.builder()
					.withGender(Gender.FEMALE)
					.withName("Adora Nightshade")
					.build()
			)).build(),
			fdata.getData());
}


But when i try to bind to the nested field of the list record, it fails:

@Test
public void testBinding_myClasses_nestedRecursiveBinding() {
	FormData<MyExample> fdata = formMapping.bind(UndertowRequestParams.builder_withBindingPrefix("example")
			.addFormData("name", "Mora Moonsinger")
			.addFormData("myClasses[0]-name", "Kathris Starsong")
			.addFormData("myClasses[0]-gender", "FEMALE")
			.addFormData("myClasses[0]-nestedOnes[0]-name", "Kathris Starsong Nested")
			.addFormData("myClasses[0]-nestedOnes[0]-gender", "FEMALE")
			.addFormData("myClasses[1]-name", "Adora Nightshade")
			.addFormData("myClasses[1]-gender", "FEMALE")
			.build()
			.debug());
	
	assertEqualsDebug(MyExample.builder()
			.withName("Mora Moonsinger")
			.withMyClasses(Lists.newArrayList(
				MyClass.builder()
					.withGender(Gender.FEMALE)
					.withName("Kathris Starsong")
					.withNestedOnes(Lists.newArrayList(MyClass.builder()
							.withGender(Gender.FEMALE)
							.withName("Kathris Starsong Nested")
							.build()))
					.build(),
				MyClass.builder()
					.withGender(Gender.FEMALE)
					.withName("Adora Nightshade")
					.build()
			)).build(),
			fdata.getData());
}
	

The expected structure is

{
  "name" : "Mora Moonsinger",
  "myClasses" : [ {
    "name" : "Kathris Starsong",
    "gender" : "FEMALE",
    "nestedOnes" : [ {
      "name" : "Kathris Starsong Nested",
      "gender" : "FEMALE",
      "nestedOnes" : [ ]
    } ]
  }, {
    "name" : "Adora Nightshade",
    "gender" : "FEMALE",
    "nestedOnes" : [ ]
  } ]
}

The result structure is this:

{
  "name" : "Mora Moonsinger",
  "myClasses" : [ {
    "name" : "Kathris Starsong",
    "gender" : "FEMALE",
    "nestedOnes" : [ ]
  }, {
    "name" : "Adora Nightshade",
    "gender" : "FEMALE",
    "nestedOnes" : [ ]
  } ]
}

Here is the junit test code. Basically its similar to the above, but with the class and builder definitions.

Any pointers would be greatly appreciated, thank you.

@beranradek
Copy link
Owner

Hi albert-kam, nice to see you again.

I am afraid nesting of lists mapping within another list mapping is not tested with the library but it could be generally possible. As a hint: Please try to first fill your form mapping with data (using FormMapping.fill method) and print the resulting structure using FormMapping.toString to first better understand generated names of nested form fields. And then possibly debug formMapping.bind (particularly BasicListFormMapping.bind).

@albert-kam
Copy link
Author

Hi again !

I tried filling and sysout the filled mapping, and i got this. Maybe there's a tiny bug in it. Please see the YeeHaw in the output to get where it fails.

example : MyExample {
  order : 0,
  fields {
    example-name (value=Mora Moonsinger /count: 1/, order=0)
  }, 
  nested {
    example-myClasses : MyClass {
      order : 1,
      list {
        example-myClasses[0] : MyClass {
          order : 0,
          fields {
            example-myClasses[0]-name (value=Kathris Starsong /count: 1/, order=0),
            example-myClasses[0]-gender (value=FEMALE /count: 1/, order=1)
          }, 
          nested {
            example-myClasses[0]-nestedOnes : MyClass {
              order : 2,
              list {
                // YeeHaw -- should be example-myClasses[0]-nestedOnes[0]
                example-myClasses-nestedOnes[0] : MyClass {
                  order : 0,
                  fields {
                    example-myClasses-nestedOnes[0]-name (value=Kathris Starsong ... /count: 1/, order=0),
                    example-myClasses-nestedOnes[0]-gender (value=FEMALE /count: 1/, order=1)
                  }
                }
              }
            }
          }
        },
        example-myClasses[1] : MyClass {
          order : 1,
          fields {
            example-myClasses[1]-name (value=Adora Nightshade /count: 1/, order=0),
            example-myClasses[1]-gender (value=FEMALE /count: 1/, order=1)
          }, 
          nested {
            example-myClasses[1]-nestedOnes : MyClass {
              order : 2,
            }
          }
        }
      }
    }
  }
}

Any pointers of where the issue might be ?
Thank you !

@albert-kam
Copy link
Author

Hi again, sorry to bump this topic.
Is there going to be a followup for this issue ?

@beranradek
Copy link
Owner

Hi, albert,

I thought that builder.mappingType = MappingType.SINGLE; could be removed from BasicListFormMapping's bind and fillInternal method, but it is not that easy. It is correct when the LIST mapping becomes the SINGLE one with the index field filled up. It needs further investigation/debugging of BasicListFormMapping.bind and BasicFormMapping.getName for your test case. Could you debug BasicFormMapping.getName where the wrong example-myClasses-nestedOnes[0]-name is composed from "property name" of current mapping (with possible index) and name of parent? I don't think I will get to this soon.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants