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

Access nested value of initialValues via attribute #239

Open
vasilich6107 opened this issue Mar 5, 2020 · 12 comments
Open

Access nested value of initialValues via attribute #239

vasilich6107 opened this issue Mar 5, 2020 · 12 comments
Labels
enhancement New feature or request help wanted Extra attention is needed

Comments

@vasilich6107
Copy link

Hi. Thanks for your work.

Is there any chance to have possibility to access nested value in initialValues through the attribute field?

For example if I have deeply nested initialValues I would like to have possibility to set attribute like

items.0.some.value

@danvick
Copy link
Collaborator

danvick commented Mar 9, 2020

Hi @vasilich6107,
I'm glad you find this package useful.

I haven't considered this yet, sounds like an interesting idea worth trying but maybe a bit challenging to implement.

@danvick danvick added the enhancement New feature or request label Mar 9, 2020
@danvick danvick added the help wanted Extra attention is needed label May 7, 2020
@guenth39
Copy link

guenth39 commented Jun 8, 2020

Would be awsome to have this! Maybe have a look into sembast package could help you to implement it. There is a implementation like that for order and filter in a query :)
https://github.com/tekartik/sembast.dart/blob/master/sembast/lib/src/api/field.dart
https://github.com/tekartik/sembast.dart/blob/master/sembast/doc/queries.md#sortingquerying-on-nested-field

@AbdulRafaySiddiqui
Copy link

I am trying to implement this, guide me if I am on the right track.
I have written two methods

  1. Extracts the nested value from the map.
  2. Generates the map according to the given attribute.

Works fine for me, any suggestions?

dynamic getInitialValue(String attribute, dynamic initialValue) {
   var props = attribute.split('.');

   //if property is not nested return its value from map
   if (props.length < 2)
     return (initialValue?.containsKey(attribute) ?? false)
         ? initialValue[attribute]
         : null;

   //iterate to find the nested value

   //to track if current value is a Map or a List
   var isMap = initialValue is Map;

   //holds the map values
   Map<String, dynamic> map = isMap ? initialValue : null;

   //holds the list values
   List list = isMap ? null : initialValue;

   //loop all props
   for (var i = 0; i < props.length - 1; i++) {
     //if prop is key for list we need to convert it to INT
     var key = isMap ? props[i] : int.parse(props[i]);

     //if the next prop is a Map type then assign it to the map variable
     if ((isMap && map[key] is Map) || (!isMap && list[key] is Map)) {
       map = isMap ? map[key] : list[key];
       //this tells if the current value is stored in the map or list variable
       isMap = true;
     }
     //else of its a List type then assign it to the list varaible
     else if ((isMap && map[key] is List) || (!isMap && list[key] is List)) {
       list = isMap ? map[key] : list[key];
       //this tells if the current value is stored in the map or list variable
       isMap = false;
     }
   }

   return isMap ? map[props.last] : list[int.parse(props.last)];
 }

 //recursively generates the map accroding to the attribute
 dynamic getMap(List<String> props, dynamic value, dynamic map) {
   if (props.isEmpty) return value;

   if (props.length == 1) return {...map ?? {}, props.single: value};

   //if the next prop is an integer then we have a list
   var key = int.tryParse(props[1]);
   if (key != null) {
     var list = map == null ? [] : [...(map[props.first] ?? {})];
     //if list is shorter than the provided index append null objects to list till we have the requred length of list
     if (list.length <= key)
       list.addAll(List.generate(key + 1 - list.length, (index) => null));

     list[key] = getMap(props.sublist(2), value, list[key]);
     return {...map ?? {}, props.first: list};
   } else {
     return {
       ...map ?? {},
       props.first:
           getMap(props.sublist(1), value, map == null ? {} : map[props.first])
     };
   }
 }

 Map<String, dynamic> initialValue = {
   "prop1": {
     "list": [
       {"key1": "value1"},
       {"key2": "value2"},
       {"key3": "value3"},
       "value4"
     ]
   },
   "prop2" : {"prop3" : {"prop4": "prop4 Value"}}
 };

 print(getInitialValue("prop1.list.0.key1", initialValue));
 print(getInitialValue("prop2.prop3.prop4", initialValue));

 print(getMap("prop1.list.0.key1".split('.'), "new Value 1", initialValue));
 print(getMap("prop2.prop3.prop4".split('.'), "new porp4 Value", initialValue));

@ekremkenter
Copy link

Any chance this would be implemented or any alternative solution?

@ekremkenter
Copy link

I ended up flattening the map before assigning as initial value, and use innerObject.field as field name. I am assuming we can do that flattening inside framework.

@deandreamatias
Copy link
Collaborator

Hi!
If someone has a solution for this, please feel free to open a PR.
Thanks!

@Hu-Wentao
Copy link
Contributor

Hu-Wentao commented Nov 15, 2022

Consider nested FormBuilder, like this

FormBuilder(
// ...
  FormBuilderTextField(
    name: 'foo', 
    // ...
  ),
  NestedFormBuilder(  // new class
    name: 'inner',
    // ...
    FormBuilderTextField(
      name: 'bar', 
      // ...
    ),
  ),
// ... 
)

value example:

{
  "foo": "some input value",
   "inner":{
      "bar" : "some inner input value"
    }
}

@Hu-Wentao
Copy link
Contributor

Consider nested FormBuilder, like this

FormBuilder(
// ...
  FormBuilderTextField(
    name: 'foo', 
    // ...
  ),
  NestedFormBuilder(  // new class
    name: 'inner',
    // ...
    FormBuilderTextField(
      name: 'bar', 
      // ...
    ),
  ),
// ... 
)

value example:

{
  "foo": "some input value",
   "inner":{
      "bar" : "some inner input value"
    }
}

it work for me, I will PR soon @deandreamatias

@gmisiolek-sbm
Copy link

gmisiolek-sbm commented Mar 17, 2023

Any chance NestedFormBuilder will be added soon?

@Arpit1496

This comment was marked as spam.

@lapin7771n
Copy link

Would be cool to have this feature implemented

@RodolfoSilva
Copy link
Contributor

Try using https://pub.dev/packages/flat, you will have some extra work, but this can solve most cases.

NestedFormBuilder only works for Map, maybe we should add an ArrayFormBuilder too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests