Form icon indicating copy to clipboard operation
Form copied to clipboard

[Question] How does your GroupHeaders keep track of their collapsed state upon dequeue?

Open jasper-ch-chan opened this issue 7 years ago • 8 comments

I'm trying to trace the logic of how your group headers keep track of their collapsed state. The scenario would be like so:

  1. Collapse a group
  2. Scroll down so the group disappears from screen
  3. Scroll back up so it gets re-instantiated for view

I'm failing to figure out where you guys figure out if it should be collapsed or not. I only see the part where you assign if it is collapsible.

Thanks

jasper-ch-chan avatar Jun 22 '17 17:06 jasper-ch-chan

Hi @jasper-ch-chan! Did you get it working?

3lvis avatar Jun 22 '17 20:06 3lvis

Hi @3lvis I think I have an understanding of what is happening, however, I'm not sure why it was designed that way. It seems like for every group header, you register a new FORMGroupHeaderView class with a new identifier. Why is that? Why not just re-use the same identifier?

jasper-ch-chan avatar Jun 22 '17 20:06 jasper-ch-chan

In order to support element-independent styles, the reuse identifiers must be unique. Otherwise, all elements would get the same styling -- which isn't always desired.

jeffleeismyhero avatar Jun 22 '17 21:06 jeffleeismyhero

hi @jeffleeismyhero I see. And could you kindly point to me how you guys are re-assigning the collapsed state of the group header itself? I can't seem to find that anywhere.

jasper-ch-chan avatar Jun 22 '17 21:06 jasper-ch-chan

@jasper-ch-chan I'm not able to replicate the issue you've described. Nevertheless, you can look for three different collapsed-related terms/keywords in the code:

  1. collapsed (the default state)
  2. collapse (the action/method used to actually collapse)
  3. collapsible (whether a group can be collapsed

https://github.com/hyperoslo/Form/search?utf8=%E2%9C%93&q=collapse&type=Code

If you can post the JSON you're using, we might be able to point you to the issue faster.

Here's the JSON I'm using in the Basic-ObjC demo application:

{
  "groups":[
    {
      "id":"personal-details",
      "title":"Personal Details",
      "collapsed":true,
      "sections":[
        {
          "id":"personal-details-0",
          "fields":[
            {
              "id":"first_name",
              "title":"First name",
              "accessibility_label":"First Name Accessibility Label",
              "info":"Fornavn",
              "type":"name",
              "disabled":true,
              "size":{
                "width":30,
                "height":1
              },
              "validations":{
                "required":true,
                "min_length":2
              }
            },
            {
              "id":"last_name",
              "title":"Last name",
              "type":"name",
              "info":"Family name",
              "size":{
                "width":30,
                "height":1
              },
              "validations":{
                "required":true,
                "min_length":2
              }
            },
            {
              "id":"display_name",
              "title":"Display name",
              "info":"This is the name that is going to be used across the application.",
              "placeholder": "Display name",
              "type":"text",
              "size":{
                "width":40,
                "height":1
              },
              "formula":"first_name last_name"
            }
          ]
        },
        {
          "id":"personal-details-1",
          "fields":[
            {
              "id":"address",
              "title":"Address",
              "type":"text",
              "size":{
                "width":50,
                "height":1
              }
            },
            {
              "id":"email",
              "title":"E-post",
              "info":"bork\nbork\nbork",
              "type":"email",
              "size":{
                "width":25,
                "height":1
              },
              "validations":{
                "format":"[\\w._%+-]+@[\\w.-]+\\.\\w{2,}",
                "required":true
              }
            },
            {
              "id":"phone",
              "title":"Phone number",
              "type":"text",
              "input_type":"number",
              "size":{
                "width":25,
                "height":1
              }
            },
            {
              "id":"image",
              "type":"image",
              "size":{
                "width":100,
                "height":1.7
              },
              "hidden":true
            }
          ]
        }
      ]
    },
    {
      "id":"employment",
      "title":"Employment",
      "sections":[
        {
          "id":"employment-0",
          "fields":[
            {
              "id":"start_date",
              "title":"Start date",
              "info":"The day of employment",
              "type":"date",
              "size":{
                "width":25,
                "height":1
              }
            },
            {
              "id":"start_time",
              "title":"Start time",
              "type":"time",
              "size":{
                "width":25,
                "height":1
              }
            },
            {
              "id":"end_date",
              "title":"End date",
              "type":"date",
              "validations":{
                "compare_to":"start_date",
                "compare_rule":">"
              },
              "size":{
                "width":25,
                "height":1
              }
            },
            {
              "id":"end_time",
              "title":"End time",
              "type":"time",
              "size":{
                "width":25,
                "height":1
              },
              "validations":{
                "required":true,
                "min_length":2
              }
            },
            {
              "id":"contract_type",
              "title":"Contract type",
              "info":"Type of contract\n Permanent or temporary",
              "type":"select",
              "size":{
                "width":50,
                "height":1
              },
              "values":[
                {
                  "id":0,
                  "title":"Permanent",
                  "info":"Regular employee",
                  "default":true,
                  "targets":[
                    {
                      "id":"end_date",
                      "type":"field",
                      "action":"show"
                    },
                    {
                      "id":"end_time",
                      "type":"field",
                      "action":"show"
                    },
                    {
                      "id":"employment-1",
                      "type":"section",
                      "action":"show"
                    }
                  ]
                },
                {
                  "id":1,
                  "title":"Temporary",
                  "targets":[
                    {
                      "id":"end_date",
                      "type":"field",
                      "action":"hide"
                    },
                    {
                      "id":"end_time",
                      "type":"field",
                      "action":"hide"
                    },
                    {
                      "id":"employment-1",
                      "type":"section",
                      "action":"hide"
                    }
                  ]
                }
              ]
            }
          ]
        },
        {
          "id":"employment-1",
          "fields":[
            {
              "id":"base_salary",
              "title":"Base salary",
              "type":"select",
              "size":{
                "width":25,
                "height":1
              },
              "values":[
                {
                  "title":"Salary 1",
                  "id":0,
                  "value":100,
                  "targets":[
                    {
                      "id":"total",
                      "type":"field",
                      "action":"update"
                    }
                  ]
                },
                {
                  "title":"Salary 2",
                  "id":1,
                  "value":200,
                  "targets":[
                    {
                      "id":"total",
                      "type":"field",
                      "action":"update"
                    }
                  ]
                },
                {
                  "title":"Salary 3",
                  "id":2,
                  "value":10,
                  "targets":[
                    {
                      "id":"total",
                      "type":"field",
                      "action":"update"
                    }
                  ]
                }
              ]
            },
            {
              "id":"bonus_enabled",
              "title":"Bonus enabled",
              "type":"select",
              "size":{
                "width":25,
                "height":1
              },
              "values":[
                {
                  "id":true,
                  "title":"Ja"
                },
                {
                  "id":false,
                  "title":"Nei"
                }
              ]
            },
            {
              "id":"bonus",
              "title":"Bonus",
              "type":"float",
              "size":{
                "width":25,
                "height":1
              },
              "targets":[
                {
                  "id":"total",
                  "type":"field",
                  "action":"update"
                }
              ],
              "validations":{
                "max_value":100,
                "min_value":10
              }
            },
            {
              "id":"total",
              "title":"Total",
              "type":"float",
              "size":{
                "width":25,
                "height":1
              },
              "disabled":true,
              "formula":"$base_salary + $bonus"
            }
          ]
        },
        {
          "id":"companies",
          "type":"dynamic",
          "action_title":"ADD COMPANY ✛",
          "fields":null
        },
        {
          "id":"contacts",
          "type":"dynamic",
          "action_title":"ADD CONTACT ✛",
          "fields":null
        }
      ]
    },
    {
      "id":"employment2",
      "title":"Employment 2",
      "sections":[
        {
          "id":"employment-0",
          "fields":[
            {
              "id":"start_date",
              "title":"Start date",
              "info":"The day of employment",
              "type":"date",
              "size":{
                "width":25,
                "height":1
              }
            },
            {
              "id":"start_time",
              "title":"Start time",
              "type":"time",
              "size":{
                "width":25,
                "height":1
              }
            },
            {
              "id":"end_date",
              "title":"End date",
              "type":"date",
              "validations":{
                "compare_to":"start_date",
                "compare_rule":">"
              },
              "size":{
                "width":25,
                "height":1
              }
            },
            {
              "id":"end_time",
              "title":"End time",
              "type":"time",
              "size":{
                "width":25,
                "height":1
              },
              "validations":{
                "required":true,
                "min_length":2
              }
            },
            {
              "id":"contract_type",
              "title":"Contract type",
              "info":"Type of contract\n Permanent or temporary",
              "type":"select",
              "size":{
                "width":50,
                "height":1
              },
              "values":[
                {
                  "id":0,
                  "title":"Permanent",
                  "info":"Regular employee",
                  "default":true,
                  "targets":[
                    {
                      "id":"end_date",
                      "type":"field",
                      "action":"show"
                    },
                    {
                      "id":"end_time",
                      "type":"field",
                      "action":"show"
                    },
                    {
                      "id":"employment-1",
                      "type":"section",
                      "action":"show"
                    }
                  ]
                },
                {
                  "id":1,
                  "title":"Temporary",
                  "targets":[
                    {
                      "id":"end_date",
                      "type":"field",
                      "action":"hide"
                    },
                    {
                      "id":"end_time",
                      "type":"field",
                      "action":"hide"
                    },
                    {
                      "id":"employment-1",
                      "type":"section",
                      "action":"hide"
                    }
                  ]
                }
              ]
            }
          ]
        },
        {
          "id":"employment-1",
          "fields":[
            {
              "id":"base_salary",
              "title":"Base salary",
              "type":"select",
              "size":{
                "width":25,
                "height":1
              },
              "values":[
                {
                  "title":"Salary 1",
                  "id":0,
                  "value":100,
                  "targets":[
                    {
                      "id":"total",
                      "type":"field",
                      "action":"update"
                    }
                  ]
                },
                {
                  "title":"Salary 2",
                  "id":1,
                  "value":200,
                  "targets":[
                    {
                      "id":"total",
                      "type":"field",
                      "action":"update"
                    }
                  ]
                },
                {
                  "title":"Salary 3",
                  "id":2,
                  "value":10,
                  "targets":[
                    {
                      "id":"total",
                      "type":"field",
                      "action":"update"
                    }
                  ]
                }
              ]
            },
            {
              "id":"bonus_enabled",
              "title":"Bonus enabled",
              "type":"select",
              "size":{
                "width":25,
                "height":1
              },
              "values":[
                {
                  "id":true,
                  "title":"Ja"
                },
                {
                  "id":false,
                  "title":"Nei"
                }
              ]
            },
            {
              "id":"bonus",
              "title":"Bonus",
              "type":"float",
              "size":{
                "width":25,
                "height":1
              },
              "targets":[
                {
                  "id":"total",
                  "type":"field",
                  "action":"update"
                }
              ],
              "validations":{
                "max_value":100,
                "min_value":10
              }
            },
            {
              "id":"total",
              "title":"Total",
              "type":"float",
              "size":{
                "width":25,
                "height":1
              },
              "disabled":true,
              "formula":"$base_salary + $bonus"
            }
          ]
        },
        {
          "id":"companies",
          "type":"dynamic",
          "action_title":"ADD COMPANY ✛",
          "fields":null
        },
        {
          "id":"contacts",
          "type":"dynamic",
          "action_title":"ADD CONTACT ✛",
          "fields":null
        }
      ]
    },
    {
      "id":"employment3",
      "title":"Employment 3",
      "sections":[
        {
          "id":"employment-0",
          "fields":[
            {
              "id":"start_date",
              "title":"Start date",
              "info":"The day of employment",
              "type":"date",
              "size":{
                "width":25,
                "height":1
              }
            },
            {
              "id":"start_time",
              "title":"Start time",
              "type":"time",
              "size":{
                "width":25,
                "height":1
              }
            },
            {
              "id":"end_date",
              "title":"End date",
              "type":"date",
              "validations":{
                "compare_to":"start_date",
                "compare_rule":">"
              },
              "size":{
                "width":25,
                "height":1
              }
            },
            {
              "id":"end_time",
              "title":"End time",
              "type":"time",
              "size":{
                "width":25,
                "height":1
              },
              "validations":{
                "required":true,
                "min_length":2
              }
            },
            {
              "id":"contract_type",
              "title":"Contract type",
              "info":"Type of contract\n Permanent or temporary",
              "type":"select",
              "size":{
                "width":50,
                "height":1
              },
              "values":[
                {
                  "id":0,
                  "title":"Permanent",
                  "info":"Regular employee",
                  "default":true,
                  "targets":[
                    {
                      "id":"end_date",
                      "type":"field",
                      "action":"show"
                    },
                    {
                      "id":"end_time",
                      "type":"field",
                      "action":"show"
                    },
                    {
                      "id":"employment-1",
                      "type":"section",
                      "action":"show"
                    }
                  ]
                },
                {
                  "id":1,
                  "title":"Temporary",
                  "targets":[
                    {
                      "id":"end_date",
                      "type":"field",
                      "action":"hide"
                    },
                    {
                      "id":"end_time",
                      "type":"field",
                      "action":"hide"
                    },
                    {
                      "id":"employment-1",
                      "type":"section",
                      "action":"hide"
                    }
                  ]
                }
              ]
            }
          ]
        },
        {
          "id":"employment-1",
          "fields":[
            {
              "id":"base_salary",
              "title":"Base salary",
              "type":"select",
              "size":{
                "width":25,
                "height":1
              },
              "values":[
                {
                  "title":"Salary 1",
                  "id":0,
                  "value":100,
                  "targets":[
                    {
                      "id":"total",
                      "type":"field",
                      "action":"update"
                    }
                  ]
                },
                {
                  "title":"Salary 2",
                  "id":1,
                  "value":200,
                  "targets":[
                    {
                      "id":"total",
                      "type":"field",
                      "action":"update"
                    }
                  ]
                },
                {
                  "title":"Salary 3",
                  "id":2,
                  "value":10,
                  "targets":[
                    {
                      "id":"total",
                      "type":"field",
                      "action":"update"
                    }
                  ]
                }
              ]
            },
            {
              "id":"bonus_enabled",
              "title":"Bonus enabled",
              "type":"select",
              "size":{
                "width":25,
                "height":1
              },
              "values":[
                {
                  "id":true,
                  "title":"Ja"
                },
                {
                  "id":false,
                  "title":"Nei"
                }
              ]
            },
            {
              "id":"bonus",
              "title":"Bonus",
              "type":"float",
              "size":{
                "width":25,
                "height":1
              },
              "targets":[
                {
                  "id":"total",
                  "type":"field",
                  "action":"update"
                }
              ],
              "validations":{
                "max_value":100,
                "min_value":10
              }
            },
            {
              "id":"total",
              "title":"Total",
              "type":"float",
              "size":{
                "width":25,
                "height":1
              },
              "disabled":true,
              "formula":"$base_salary + $bonus"
            }
          ]
        },
        {
          "id":"companies",
          "type":"dynamic",
          "action_title":"ADD COMPANY ✛",
          "fields":null
        },
        {
          "id":"contacts",
          "type":"dynamic",
          "action_title":"ADD CONTACT ✛",
          "fields":null
        }
      ]
    },
    {
      "id":"employment4",
      "title":"Employment 4",
      "sections":[
        {
          "id":"employment-0",
          "fields":[
            {
              "id":"start_date",
              "title":"Start date",
              "info":"The day of employment",
              "type":"date",
              "size":{
                "width":25,
                "height":1
              }
            },
            {
              "id":"start_time",
              "title":"Start time",
              "type":"time",
              "size":{
                "width":25,
                "height":1
              }
            },
            {
              "id":"end_date",
              "title":"End date",
              "type":"date",
              "validations":{
                "compare_to":"start_date",
                "compare_rule":">"
              },
              "size":{
                "width":25,
                "height":1
              }
            },
            {
              "id":"end_time",
              "title":"End time",
              "type":"time",
              "size":{
                "width":25,
                "height":1
              },
              "validations":{
                "required":true,
                "min_length":2
              }
            },
            {
              "id":"contract_type",
              "title":"Contract type",
              "info":"Type of contract\n Permanent or temporary",
              "type":"select",
              "size":{
                "width":50,
                "height":1
              },
              "values":[
                {
                  "id":0,
                  "title":"Permanent",
                  "info":"Regular employee",
                  "default":true,
                  "targets":[
                    {
                      "id":"end_date",
                      "type":"field",
                      "action":"show"
                    },
                    {
                      "id":"end_time",
                      "type":"field",
                      "action":"show"
                    },
                    {
                      "id":"employment-1",
                      "type":"section",
                      "action":"show"
                    }
                  ]
                },
                {
                  "id":1,
                  "title":"Temporary",
                  "targets":[
                    {
                      "id":"end_date",
                      "type":"field",
                      "action":"hide"
                    },
                    {
                      "id":"end_time",
                      "type":"field",
                      "action":"hide"
                    },
                    {
                      "id":"employment-1",
                      "type":"section",
                      "action":"hide"
                    }
                  ]
                }
              ]
            }
          ]
        },
        {
          "id":"employment-1",
          "fields":[
            {
              "id":"base_salary",
              "title":"Base salary",
              "type":"select",
              "size":{
                "width":25,
                "height":1
              },
              "values":[
                {
                  "title":"Salary 1",
                  "id":0,
                  "value":100,
                  "targets":[
                    {
                      "id":"total",
                      "type":"field",
                      "action":"update"
                    }
                  ]
                },
                {
                  "title":"Salary 2",
                  "id":1,
                  "value":200,
                  "targets":[
                    {
                      "id":"total",
                      "type":"field",
                      "action":"update"
                    }
                  ]
                },
                {
                  "title":"Salary 3",
                  "id":2,
                  "value":10,
                  "targets":[
                    {
                      "id":"total",
                      "type":"field",
                      "action":"update"
                    }
                  ]
                }
              ]
            },
            {
              "id":"bonus_enabled",
              "title":"Bonus enabled",
              "type":"select",
              "size":{
                "width":25,
                "height":1
              },
              "values":[
                {
                  "id":true,
                  "title":"Ja"
                },
                {
                  "id":false,
                  "title":"Nei"
                }
              ]
            },
            {
              "id":"bonus",
              "title":"Bonus",
              "type":"float",
              "size":{
                "width":25,
                "height":1
              },
              "targets":[
                {
                  "id":"total",
                  "type":"field",
                  "action":"update"
                }
              ],
              "validations":{
                "max_value":100,
                "min_value":10
              }
            },
            {
              "id":"total",
              "title":"Total",
              "type":"float",
              "size":{
                "width":25,
                "height":1
              },
              "disabled":true,
              "formula":"$base_salary + $bonus"
            }
          ]
        },
        {
          "id":"companies",
          "type":"dynamic",
          "action_title":"ADD COMPANY ✛",
          "fields":null
        },
        {
          "id":"contacts",
          "type":"dynamic",
          "action_title":"ADD CONTACT ✛",
          "fields":null
        }
      ]
    }
  ],
  "templates":{
    "fields":null,
    "sections":[
      {
        "id":"companies",
        "fields":[
          {
            "id":"companies[:index].name",
            "title":"Company Name",
            "type":"name",
            "validations":{
              "required":true,
              "min_length":2
            },
            "size":{
              "width":50,
              "height":1
            }
          },
          {
            "id":"companies[:index].phone_number",
            "title":"Phone number",
            "type":"number",
            "size":{
              "width":30,
              "height":1
            }
          },
          {
            "id":"companies[:index].remove",
            "title":"Remove",
            "type":"button",
            "size":{
              "width":20,
              "height":1
            }
          }
        ]
      },
      {
        "id":"contacts",
        "fields":[
          {
            "id":"contacts[:index].name",
            "title":"Contact name",
            "type":"name",
            "validations":{
              "required":true,
              "min_length":2
            },
            "size":{
              "width":50,
              "height":1
            }
          },
          {
            "id":"contacts[:index].phone_number",
            "title":"Phone number",
            "type":"number",
            "size":{
              "width":30,
              "height":1
            }
          },
          {
            "id":"contacts[:index].remove",
            "title":"Remove",
            "type":"button",
            "size":{
              "width":20,
              "height":1
            }
          }
        ]
      }
    ]
  }
}

jeffleeismyhero avatar Jun 22 '17 21:06 jeffleeismyhero

Hi @jeffleeismyhero So the issue is that our JSON itself, sets a few group headers to be not collapsed by default. Lets say I collapse said group, scroll down so the header disappears. Then I scroll back up so the header appears. This will trigger my configureGroupHeaderAtIndexPathBlock

Inside this block, we assign the collapsible and collapsed state via the FORMGroup object being provided. However, it appears the FORMGroup JSON collapsed value doesn't change despite us having collapsed the header. Does that make more sense in regards to what I'm asking?

jasper-ch-chan avatar Jun 22 '17 21:06 jasper-ch-chan

@jasper-ch-chan so you are using configureGroupHeaderAtIndexPathBlock to custom configure the group header? Can you post that method?

jeffleeismyhero avatar Jun 22 '17 21:06 jeffleeismyhero

@jeffleeismyhero

self.dataSource.configureGroupHeaderAtIndexPathBlock = ^UICollectionReusableView *(FORMGroup *group, UICollectionView *collectionView, NSIndexPath *indexPath) {
  NSString *identifier = [NSString stringWithFormat:@"%@-%@", FORMHeaderViewCellIdentifier, group.groupID];
  [collectionView registerClass:[FORMHeaderView class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:identifier];
  FORMHeaderView *headerView = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:identifier forIndexPath:indexPath];

  headerView.collapsible = group.collapsible;
  headerView.isCollapsed = group.collapsed;

  return headerView;
};

FORMHeaderView is a class I created, which is a subclass of the original FORMGroupHeaderView. Essentially it adds a UIImageView and isCollapsed boolean for our purpose.``

jasper-ch-chan avatar Jun 22 '17 21:06 jasper-ch-chan