kelp404 / angular-form-builder

Drag and drop to build bootstrap forms in AngularJS.
http://kelp404.github.io/angular-form-builder/
MIT License
600 stars 340 forks source link

Multiple Form Builders #49

Open neoborn opened 10 years ago

neoborn commented 10 years ago

Hi,

In my use case, I need to create several fb-builder's which are arranged in tabs like this http://cl.ly/Xm3j so that an admin user can build the form and get it rendered with "Prev Section" and "Next Section" functionality.

This is the change that I made to allow <div fb-builder="{{dynamicNameFromMainCtrl}}"></div> so that I can use ng-repeat to dynamically create the fb-builder's :

scope: {
    fbBuilder: '@'
}

This results in $builder.forms variable to be in this structure:

{ default: [], form1: [formObject1, formObject2], form2: [formObject3], and so on }

When I move certain formObject around in one of the form (e.g. form1) the $builder.updateFormObjectIndex(scope.formName, oldIndex, newIndex) is executed (line 259) and then execute the reindexFormObject (line 1205) method too.

However, the issue that I encounter here is that the reindexFormObject method also update and affect form2 (e.g. if I move a formObject from index 2 to index 3 in form1, the form object at index 3 in form2 is deleted), which should not be the case. Because I only want to update form1.

Any idea on this matter? Does anyone encounter this issue also when trying to implement multiple form builder?

Appreciate any help here. thanks.

momoohidayat commented 9 years ago

+1 for multiple builder

in my case, i have: { default: [], form1: [formObject1, formObject2], form2: [formObject3, formObject4], and so on }

and i want to move formObject1 at form1 to form2 between formObject3 and formObject4

i want to make it looks like this: { default: [], form1: [formObject2], form2: [formObject3, formObject1, formObject4], and so on }

any idea?

karlhorky commented 9 years ago

Yeah a multi-form builder would be great.

As for why this is happening, I took a quick look at this today, and it appears reindexFormObject is being called multiple times because of the up hook passed to the $drag provider fires for all form builder instances (it loops through here). The reason your form objects are being deleted is that the up function is calling removeFormObject from the other forms here.

Quite a lot is going on in the $drag provider so I'm not sure what the best option is here. @kelp404 any tips for trying to make this module work properly with multiple forms?

dan12mol commented 9 years ago

I solved this.

As stated you should first change

scope: {
    fbBuilder: '@'
}

Afterwards take the following lines of code and remove them. That should enable you to have multiple forms each with their own data.

You can see my forked implementation of this together with the directive:

<div fb-multiple="arrayName">

The implementation of this directive can be found here and the way I implemented this in the view can be found here

One more thing I'm trying to implement is skip logic such that people may build surveys and have parts of them skipped depending on some user answers. Any hints for this? Interested?

miguelcastro67 commented 9 years ago

I found a better way so not to simply remove that $builder.removeFormObject line. I can determine if the code being executed is for the form on which you performed your drag by putting a condition around the removeFormObject, like this:

                          if (formObject.editable) {
                              if (scope.formObjects.indexOf(draggable.object.formObject) > -1)  // MAC-MOD
                                   $builder.removeFormObject(attrs.fbBuilder, formObject.index);
                            }

Also, there seemed to be an issue on the calculation of NewIndex a little below that. It seems that the $(element) being accessed to obtain newIndex was accounting for all contained form objects for any forms defined previous to the current form. This cause the drag-and-move UP to be ignored because the drop index was way beyond the total objects of that form. The move DOWN worked sometimes. I recalculated newIndex to account for all earlier objects so if you defined four forms and are performing a move in the third, I account for the first and second now as well. So far so good. I replaced this code:

                              if (oldIndex < newIndex) {
                                  newIndex--;
                              }

with this:

                              var formNames = Object.keys($builder.forms);
                              var totalObjects = 0;
                              for (var i = 0; i < formNames.length; i++) {
                                  if (formNames[i] != scope.formName) {
                                      totalObjects += $builder.forms[formNames[i]].length;
                                  }
                                  else
                                      break;
                              }
                              newIndex -= totalObjects;

And the following one is left alone. It should look like this:

                              $builder.updateFormObjectIndex(scope.formName, oldIndex, newIndex);

Now if I could just figure out a way move objects between forms. Anybody got an idea there?