4

I need to create a dynamic form using JSON. I have parsed the JSON but i don't have any idea how to create a form dynamically. i'm getting json data with some control like check box ,text fields ,and questions now i want to create From based on there Question . Similar to how we can create a from using Google Forms. Please Check below link https://docs.google.com/forms/d/1lPn1aSvJsiDbJchsJjwsC93tWizXhj1qWkFPygt3oU4/viewform Please suggest some code or tutorial.

naga rocks
  • 93
  • 1
  • 7

2 Answers2

3

My idea would be, in steps

1) create model class example

     class UIControl
     {
          NSString *strControlName;
          NSString *strControlType;
          NSString *strControlValue;
          Bool  isSelected;
     }

2) Parse json and create object of model class

3) add model class object into arrOfControls

4) either go for table view, or just use loop to traverse entire arrOfControls

5) in case, table view check at cellForRowAtIndexPath type of control.

6) create custom cell for every possible field which could be come with your JSON data.

7) Return custom cell in deleage function(cellForRowAtIndexPath) depending on type of control. ex:-

         if([[arrOfControls objectAtIndexPath:indexPath.row] strType] isEqualToString:@"TextField"]])
          {
                 //create object of customcell for textfield and return cell
           }
          else if([[arrOfControls objectAtIndexPath:indexPath.row] strType] isEqualToString:@"CheckBox"]])
          {
                 //create object of customcell for checkbox and return cell
          }
          else
          {
                //control type if not match any of the above
          }

this is rough idea not acutal code. few code from my project, for cellForRowAtIndexPath

       if(indexPath.section==0)
    {
        FormField *currControl=[fieldArray objectAtIndex:indexPath.row];
        if(([currControl.strFieldType caseInsensitiveCompare:@"TextLabel"]==NSOrderedSame )|| [currControl.strFieldType caseInsensitiveCompare:@"Text"]==NSOrderedSame)
        {
            TextFieldWithLabelTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"CellTextFieldWithLabel"];
            cell.txtTextField.delegate=self;
            [cell.txtTextField setTag:indexPath.row];
            if([currControl strFieldValue]==nil)
            {
                cell.txtTextField.text = @"";
                [cell.txtTextField setPlaceholder:[currControl strPlaceHolder]];
            }
            else
            {
                //if save value exists
                cell.txtTextField.text=@"";
                cell.txtTextField.text=[currControl strFieldValue];
            }
            cell.lblTextFieldIdenti.text=[[fieldArray objectAtIndex:indexPath.row] strFieldName];
            if([currControl.strFieldType caseInsensitiveCompare:@"Text"]==NSOrderedSame)
            {
                cell.lblTextFieldIdenti.text=@"";
            }
            [cell setSelectionStyle:UITableViewCellSelectionStyleNone];
            return cell;
        }
        else if(([currControl.strFieldType caseInsensitiveCompare:@"TextView"]==NSOrderedSame)||([currControl.strFieldType caseInsensitiveCompare:@"TextViewWithCam"]==NSOrderedSame))
        {
            TableViewTextAreaCell *cell = [tableView dequeueReusableCellWithIdentifier:@"TableViewTextAreaCell"];
            cell.txtView.delegate=self;
            cell.txtView.text=@"";
            if([currControl strFieldValue]!=nil)
            {
                //if save value exists
                cell.txtView.text=@"";
                cell.txtView.text=[currControl strFieldValue];
            }
            cell.fieldLabel.text=[[fieldArray objectAtIndex:indexPath.row] strFieldName];
            NSMutableArray *barItems = [[NSMutableArray alloc] init];
            UIToolbar* keyboardDoneButtonView = [[UIToolbar alloc] init];
            keyboardDoneButtonView.barStyle = UIBarStyleDefault;
            keyboardDoneButtonView.translucent = NO;
            keyboardDoneButtonView.barTintColor=[UIColor colorWithHue:0.6 saturation:0.33 brightness:0.69 alpha:0];
            [keyboardDoneButtonView sizeToFit];
            UIBarButtonItem *leftFlexSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:self action:nil];
            [barItems addObject:leftFlexSpace];
            UIBarButtonItem *btnDone = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"BTN_DONE", nil) style:UIBarButtonItemStyleBordered target:self action:@selector(pickerDoneClicked:)];

            [barItems addObject:btnDone];
            [keyboardDoneButtonView setItems:barItems animated:YES];
            [cell.txtView setInputAccessoryView:keyboardDoneButtonView];

            [cell configureCell:currControl.strFieldName];
            cell.fieldLabel.textColor=[UIColor darkTextColor];
            cell.txtView.backgroundColor =[UIColor colorWithHexString:@"#f3f1f2"];
            cell.fieldLabel.font=[UIFont systemFontOfSize:12];
            cell.selectionStyle=UITableViewCellSelectionStyleNone;
            [cell setSelectionStyle:UITableViewCellSelectionStyleNone];
            [cell.imgViewCam setHidden:TRUE];
            if([currControl.strFieldType caseInsensitiveCompare:@"TextViewWithCam"]==NSOrderedSame)
            {
                UITapGestureRecognizer *singleTap =  [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(CameraClicked:)];
                [singleTap setNumberOfTapsRequired:1];
                [cell.imgViewCam addGestureRecognizer:singleTap];
                [cell.imgViewCam setHidden:FALSE];

            }
            return cell;
        }
        else if([currControl.strFieldType caseInsensitiveCompare:@"DropDown"]==NSOrderedSame)
        {
            //if dropdwon box
            DropDownTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"CellDropDown"];
            cell.lblDropDownidentifier.text=[currControl strFieldName];
            [cell.btnDropDown setTag:indexPath.row];
            [cell.btnDropDown addTarget:self action:@selector(ShowOptions:) forControlEvents:UIControlEventTouchUpInside];
            [cell.btnDropDown setTitle:@"" forState:UIControlStateNormal];


            if([currControl strFieldValue]!=nil)
            {
                [cell.btnDropDown setTitle:[currControl strFieldValue] forState:UIControlStateNormal];
            }
            [cell setSelectionStyle:UITableViewCellSelectionStyleNone];
            if([[currControl strFieldName] caseInsensitiveCompare:@"Time Of Delivery:"]==NSOrderedSame)
            {
                cell.imgDropDown.image=[UIImage imageNamed:@"stopwatch.png"];
            }
            else if([[currControl strFieldName] caseInsensitiveCompare:@"Date Of Delivery:"]==NSOrderedSame)
            {
                cell.imgDropDown.image=[UIImage imageNamed:@"calendar.png"];
            }
            else
            {
                cell.imgDropDown.image=[UIImage imageNamed:@"dropdown.jpeg"];
            }

            return cell;

        }
Khawar
  • 9,151
  • 9
  • 46
  • 67
Sheshnath
  • 3,293
  • 1
  • 32
  • 60
1

This is something that I found quite interesting and did a quick search. Depending on what your JSON has in it I can see 2 ways of achieving this.

1.) If your JSON is along these lines:

{ "Type":"TextField", "Properties" : { "Property1":"Value1", "Property2":"Value2"} }

etc.

You would have to have conditional code depending on the Type e.g;

UIControl *newControl

if([[parsedJson valueForKey:@"Type"] isEqualTo:"TextField"])
{
   newControl = [UITextField alloc]init];
   for(NSDictionary *dict in [parsedJson valueForKey:"Properties")
   {
     [newControl setValue:[dict value] forKey:[dict Key]];
   }
}

On the other hand if your JSON uses UIKit names for Types e.g.:

{"Type":"UITextField","Properties":{"Property1":"Value1","Property2":2}}

etc.

There is a bit of Reflection you can do:

id *control = [[NSClassFromString([parsedJson valueForKey:"Type"]) alloc] init];

       for(NSDictionary *dict in [parsedJson valueForKey:"Properties")
       {
         [newControl setValue:[dict value] forKey:[dict Key]];
       }

But you need to have a lot of error handling/try{} catch{} in case the system fails to create a class or you set a value for a property that doesn't exist.

Also properties stated in the JSON need to reference the properties of the class.

Some references used for this answer:

how to instantiate an object of class from string in Objective-C? - StackOverflow Convert a string (“MyExampleClass”) into a class name (MyExampleClass) - StackOverflow

Community
  • 1
  • 1
Naughty_Ottsel
  • 1,103
  • 10
  • 12
  • here in iOS we don't have check box control right how to handle that – naga rocks Nov 26 '14 at 09:38
  • I don't have a sample. This was all done from memory/references. A UITableView with the selection set to be a Checkmark is the best way to display multiple selection options. This follows the System UI as well – Naughty_Ottsel Nov 26 '14 at 09:40