3lvis / Form

The most flexible and powerful way to build a form on iOS
http://hyper.no
Other
1.64k stars 145 forks source link

Formula to sum fields added from templates #379

Open jeffleeismyhero opened 9 years ago

jeffleeismyhero commented 9 years ago

I have a calculated field total as a value of price * quantity. Additional sections can be added via templates with the same fields so that moretickets[:index].total = moretickets[:index].price * moretickets[:index].quantity.

I would like to have a field at the bottom of my form that dynamically updates with sum or "Grand Total" of the total and moretickets[:index].total fields.

Is this currently possible using the formula/target process?

3lvis commented 9 years ago

At the moment we don't have support for this out of the box, I will take some time tomorrow to see how we can achieve this with the current setup and also if it would be possible to add this as a feature.

I get the feeling that this could be a useful feature ;)

jeffleeismyhero commented 9 years ago

This is mostly working. However, the application crashes when I run this method and subsequently attempt to remove a section added via a template.

- (void)updateButtonAction {
    NSNumber *grandTotal = 0;
    NSDictionary *values = [self.dataSource values];

    for (NSString *key in values) {
        HYPParsedRelationship *parsedRelationship = [key hyp_parseRelationship];
        if (key && [parsedRelationship.attribute isEqualToString:@"total"]) {
          NSString *totalValue = values[key];
          if (totalValue != (id)[NSNull null]) {
            grandTotal = @([grandTotal floatValue] + [totalValue floatValue]);
          }
        }
    }

    [self.dataSource reloadWithDictionary:@{@"grand-total" : grandTotal}];
    [self.collectionView reloadData];
}

JSON

{
  "groups":[
    {
      "id":"tickets",
      "title":"Tickets",
      "sections":[
        {
          "id":"tickets-0",
          "fields":[
            {
              "id":"tickettype",
              "title":"Ticket Type",
              "info":"Type of ticket",
              "type":"select",
              "size":{
                "width":100,
                "height":1
              },
              "values":[
                {
                  "id":0,
                  "title":"3-Day Adult Ticket ($39)",
                  "default":true,
                  "value":39,
                  "targets":[
                    {
                      "id":"price",
                      "type":"field",
                      "action":"update"
                    },
                    {
                      "id":"quantity",
                      "type":"field",
                      "action":"update"
                    }
                  ]
                },
                {
                  "id":1,
                  "title":"3-Day Child Ticket ($10)",
                  "value":10,
                  "targets":[
                    {
                      "id":"price",
                      "type":"field",
                      "action":"update"
                    },
                    {
                      "id":"quantity",
                      "type":"field",
                      "action":"update"
                    }
                  ]
                }
              ]
            },
            {
              "id":"start_date",
              "title":"Start date",
              "type":"date",
              "size":{
                "width":25,
                "height":1
              },
              "info":"Tickets are valid starting on this date",
              "validations":{
                "required":true
              }
            },
            {
              "id":"quantity",
              "title":"Quantity",
              "type":"number",
              "size":{
                "width":25,
                "height":1
              },
              "targets":[
                {
                  "id":"total",
                  "type":"field",
                  "action":"update"
                }
              ],
              "validations":{
                "max_value":100,
                "min_value":1,
                "required":true
              },
              "value":1
            },
            {
              "id":"price",
              "title":"Price",
              "type":"float",
              "size":{
                "width":25,
                "height":1
              },
              "targets":[
                {
                  "id":"total",
                  "type":"field",
                  "action":"update"
                }
              ],
              "formula":"$tickettype",
              "validations":{
                "max_value":100,
                "min_value":1,
                "required":true
              }
            },
            {
              "id":"total",
              "title":"Total",
              "type":"float",
              "size":{
                "width":25,
                "height":1
              },
              "disabled":true,
              "formula":"$quantity * $price"
            }
          ]
        }
      ]
    },
    {
      "id":"add-tickets",
      "title":"Add Additional Tickets",
      "sections":[
        {
          "id":"moretickets",
          "type":"dynamic",
          "action_title":"✛ ADD ANOTHER TICKET ✛",
          "fields":null
        }
      ]
    },
    {
      "id":"grand-total",
      "title":"Total",
      "sections":[
        {
          "id":"grand-total-section",
          "fields":[
            {
              "id":"grand-total",
              "title":"Grand Total",
              "type":"float",
              "size":{
                "width":25,
                "height":1
              },
              "disabled":true
            }
          ]
        }
      ]
    }
  ],
  "templates":{
    "fields":null,
    "sections":[
      {
        "id":"moretickets",
        "fields":[
          {
            "id":"moretickets[:index].tickettype",
            "title":"Ticket Type",
            "info":"Type of ticket",
            "type":"select",
            "size":{
              "width":100,
              "height":1
            },
            "values":[
              {
                "id":0,
                "title":"3-Day Adult Ticket ($39)",
                "default":true,
                "value":39,
                "targets":[
                  {
                    "id":"moretickets[:index].price",
                    "type":"field",
                    "action":"update"
                  },
                  {
                    "id":"moretickets[:index].quantity",
                    "type":"field",
                    "action":"update"
                  }
                ]
              },
              {
                "id":1,
                "title":"3-Day Child Ticket ($10)",
                "value":10,
                "targets":[
                   {
                     "id":"moretickets[:index].price",
                     "type":"field",
                     "action":"update"
                   },
                   {
                    "id":"moretickets[:index].quantity",
                    "type":"field",
                    "action":"update"
                  }
                 ]
              }
            ]
          },
          {
            "id":"moretickets[:index].start_date",
            "title":"Start date",
            "type":"date",
            "size":{
              "width":25,
              "height":1
            },
            "info":"Tickets are valid starting on this date",
            "validations":{
              "required":true
            }
          },
          {
            "id":"moretickets[:index].quantity",
            "title":"Quantity",
            "type":"number",
            "value":1,
            "size":{
              "width":20,
              "height":1
            },
            "targets":[
              {
                "id":"moretickets[:index].total",
                "type":"field",
                "action":"update"
              }
            ],
            "validations":{
              "max_value":100,
              "min_value":1,
              "required":true
            },
            "formula":"1"
          },
          {
            "id":"moretickets[:index].price",
            "title":"Price",
            "type":"float",
            "size":{
              "width":30,
              "height":1
            },
            "targets":[
              {
                "id":"moretickets[:index].total",
                "type":"field",
                "action":"update"
              }
            ],
            "formula":"$moretickets[:index].tickettype",
            "validations":{
              "max_value":100,
              "min_value":1
            }
          },
          {
            "id":"moretickets[:index].total",
            "title":"Total",
            "type":"float",
            "size":{
              "width":25,
              "height":1
            },
            "disabled":true,
            "formula":"$moretickets[:index].quantity * $moretickets[:index].price"
          },
          {
            "id":"moretickets[:index].remove",
            "title":"Remove",
            "type":"button",
            "size":{
              "width":20,
              "height":1
            }
          }
        ]
      }
    ]
  }
}
jeffleeismyhero commented 9 years ago

The crash issue was resolved by renaming the "grand-total" field to "grand_total". It seems that the dash did not place nicely with setValuesForKeysWithDictionary