formio / ngFormBuilder

The Form.IO Form Builder Application
http://formio.github.io/ngFormBuilder/
MIT License
130 stars 130 forks source link

Add Custom Component #264

Closed hamidsharifi closed 7 years ago

hamidsharifi commented 7 years ago

Hi How can I Add custom component. thanks

prashant93 commented 7 years ago

Hi i have added custom component, have look. Let me know if have any issues. (function () {

'use strict';
angular.module('formApp', ["ui.bootstrap", "ui.select", "formio", "ngFormBuilder", "daterangepicker"])
.run(run)
.config(config);

run.$inject = ['formioComponents', '$templateCache', 'FormioUtils'];
config.$inject = ['formioComponentsProvider'];

function config(formioComponentsProvider) {
    //form RENDER
    formioComponentsProvider.register('tool', {
        title: 'Tool',
        template: 'formio/components/tool.html',
        group: 'layout',
        settings: {
            input: false,
            key: 'columns',
            columns: [{ components: [] }, { components: [] }, { components: [] }, { components: [] }, { components: [] }, { components: [] }, { components: [] }, { components: [] }, { components: [] }, { components: [] }, { components: [] }, { components: [] }]
        },
        viewTemplate: 'formio/componentsView/tool.html'
    });

    formioComponentsProvider.register('dateRange', {
        title: 'Date-Range',
        template: 'formio/components/dateRange.html',
        tableView: function (data, component, $interpolate) {
            return $interpolate('<span>{{ "' + data + '" | date: "' + component.format + '" }}</span>')();
        },
        group: 'advanced',
        controller: ['$scope', '$timeout', function ($scope, $timeout) {
            if ($scope.builder) return;
            $scope.options = {
                applyClass: 'bg-olive',  opens: "center" , showDropdowns: true,locale: {
                    separator: " To ",
                    applyLabel: "Apply",
                    fromLabel: "From",
                    format: 'MM/DD/YYYY',
                    toLabel: 'To',
                    cancelLabel: 'Cancel',
                    //customRangeLabel: 'Custom range'
                },
                //ranges: {
                //    'Last 7 Days': [moment().subtract(6, 'days'), moment()], 'Last 30 Days': [moment().subtract(29, 'days'), moment()]
                //}
            }
        }],
        settings: {
            input: true,
            tableView: true,
            label: '',
            key: 'dateRange',
            placeholder: '',
            format: 'yyyy-MM-dd HH:mm a',
            enableDate: true,
            enableTime: true,
            defaultDate: '',
            minDate: null,
            maxDate: null,
            datepickerMode: 'day',
            datePicker: {
                showWeeks: true,
                startingDay: 0,
                initDate: '',
                minMode: 'day',
                maxMode: 'year',
                yearRange: '20'
            },
            timePicker: {
                hourStep: 1,
                minuteStep: 1,
                showMeridian: true,
                readonlyInput: false,
                mousewheel: true,
                arrowkeys: true
            },
            protected: false,
            persistent: true,
            clearOnHide: true,
            validate: {
                required: false,
                custom: ''
            }
        }
    });

    //form BUILDER
    formioComponentsProvider.register('tool', {
        fbtemplate: 'formio/formbuilder/tool.html',
        icon: 'fa fa-gavel',
        noDndOverlay: true,
        confirmRemove: true,
        views: [
          {
              name: 'Display',
              template: 'formio/components/tool/display.html'
          },
          {
              name: 'API',
              template: 'formio/components/common/api.html'
          },
          {
              name: 'Conditional',
              template: 'formio/components/common/conditional.html'
          }
        ]
    });

    formioComponentsProvider.register('dateRange', {
        onEdit: ['$scope', 'FORM_OPTIONS', function ($scope, FORM_OPTIONS) {
            // FOR-34 - Update 12hr time display in the field, not only time picker.
            $scope.$watch('component.timePicker.showMeridian', function (value) {
                var _old = value ? 'HH' : 'hh';
                var _new = !value ? 'HH' : 'hh';

                if ($scope.component.enableTime) {
                    $scope.component.format = $scope.component.format.toString().replace(_old, _new);
                }
            });

            $scope.fieldSizes = FORM_OPTIONS.fieldSizes;
            $scope.labelAlignments = FORM_OPTIONS.labelAlignments;
            $scope.setFormat = function () {
                if ($scope.component.enableDate && $scope.component.enableTime) {
                    $scope.component.format = 'yyyy-MM-dd HH:mm';
                }
                else if ($scope.component.enableDate && !$scope.component.enableTime) {
                    $scope.component.format = 'yyyy-MM-dd';
                }
                else if (!$scope.component.enableDate && $scope.component.enableTime) {
                    $scope.component.format = 'HH:mm';
                }
            };
            $scope.startingDays = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
            $scope.modes = [
              {
                  name: 'day',
                  label: 'Day'
              },
              {
                  name: 'month',
                  label: 'Month'
              },
              {
                  name: 'year',
                  label: 'Year'
              }
            ];
        }],
        icon: 'fa fa-calendar',
        views: [
      {
          name: 'Display',
          template: 'formio/components/dateRange/display.html'
      },
      {
          name: 'Date',
          template: 'formio/components/dateRange/date.html'
      },
      {
          name: 'Time',
          template: 'formio/components/dateRange/time.html'
      },
      {
          name: 'Validation',
          template: 'formio/components/dateRange/validate.html'
      },
      {
          name: 'API',
          template: 'formio/components/common/api.html'
      },
      {
          name: 'Layout',
          template: 'formio/components/common/layout.html'
      },
      {
          name: 'Conditional',
          template: 'formio/components/common/conditional.html'
      }
        ],
    });
}

function run(formioComponents, $templateCache, FormioUtils) {

    //form RENDER
    $templateCache.put('formio/components/tool.html',
                           FormioUtils.fieldWrap("<div class=\"row\">\n  <div class=\"col-sm-1\" style=\"width:9.333333%\" ng-repeat=\"column in component.columns track by $index\">\n    <formio-component\n      ng-repeat=\"_component in column.components track by $index\"\n      component=\"_component\"\n      data=\"data\"\n      formio=\"formio\"\n      submission=\"submission\"\n      hide-components=\"hideComponents\"\n      ng-if=\"builder ? '::true' : isVisible(_component, data)\"\n      formio-form=\"formioForm\"\n      read-only=\"isDisabled(_component, data)\"\n      grid-row=\"gridRow\"\n      grid-col=\"gridCol\"\n      builder=\"builder\"\n    ></formio-component>\n  </div>\n</div>\n"
                         ));

    $templateCache.put('formio/componentsView/tool.html',
      FormioUtils.fieldWrap("<div class=\"row\">\n  <div class=\"col-sm-1\" style=\"width:9.333333%\" ng-repeat=\"column in component.columns track by $index\">\n    <formio-component-view\n      ng-repeat=\"_component in column.components track by $index\"\n      component=\"_component\"\n      data=\"data\"\n      form=\"form\"\n      submission=\"submission\"\n      ignore=\"ignore\"\n      ng-if=\"builder ? '::true' : isVisible(_component, data)\"\n      builder=\"builder\"\n    ></formio-component-view>\n  </div>\n</div>\n"
    ));

    $templateCache.put('formio/components/dateRange.html',
                       FormioUtils.fieldWrap("<div  class=\"input-group \">\n <input date-range-picker clearable=\"true\" options=\"options\"  class=\"form-control date-picker\" type=\"text\"  format=\"{{ component.format }}\"  ng-model=\"data[component.key]\" /> <span class=\"glyphicon glyphicon-calendar btn-sm form-control-feedback\"></span></div>\n"
                        //'<span class="input-group-btn">' +
                        //          '<button type="button" class="btn btn-sm" ><i class="glyphicon glyphicon-calendar"></i></button>' +
                        // '</span>'
                     ));
    //form Builder

    $templateCache.put('formio/components/dateRange/display.html',
   '<ng-form>' +
     '<form-builder-option property="label"></form-builder-option>' +
     '<form-builder-option property="defaultDate"></form-builder-option>' +
     '<form-builder-option property="placeholder"></form-builder-option>' +
     '<form-builder-option property="description"></form-builder-option>' +
     '<div class="form-group">' +
                        '<label for="fieldSize" form-builder-tooltip="Set size of input field.">Field Size</label>' +
                        '<select class="form-control input-sm" id="fieldSize" name="fieldSize"   ng-init="component.fieldSize = component.fieldSize || fieldSizes[0].name" ng-options="size.name as size.title for size in fieldSizes" ng-model="component.fieldSize"></select>' +
                      '</div>' +
                      '<div class="form-group">' +
                        '<label for="labelAlignment" form-builder-tooltip="Set Alignment of label.">Label Alignment</label>' +
                        '<select class="form-control input-sm" id="labelAlignment" name="labelAlignment" ng-model="component.labelAlignment" ng-init="component.labelAlignment = component.labelAlignment || labelAlignments[0].name" ng-options="labelAlignment.name as labelAlignment.title for labelAlignment in labelAlignments"></select>' +
                      '</div>' +
     '<form-builder-option property="format" label="Date Format" placeholder="Enter the Date format" title="The format for displaying this field\'s date. The format must be specified like the <a href=\'https://docs.angularjs.org/api/ng/filter/date\' target=\'_blank\'>AngularJS date filter</a>."></form-builder-option>' +
     '<form-builder-option property="customClass"></form-builder-option>' +
     '<form-builder-option property="tabindex"></form-builder-option>' +
     '<form-builder-option property="clearOnHide"></form-builder-option>' +
     '<form-builder-option property="protected"></form-builder-option>' +
     '<form-builder-option property="persistent"></form-builder-option>' +
     '<form-builder-option property="disabled"></form-builder-option>' +
     '<form-builder-option property="tableView"></form-builder-option>' +
   '</ng-form>'
 );

    $templateCache.put('formio/components/dateRange/date.html',
      '<ng-form>' +
        '<div class="checkbox">' +
          '<label form-builder-tooltip="Enables date input for this field.">' +
            '<input type="checkbox" id="enableDate" name="enableDate" ng-model="component.enableDate" ng-checked="component.enableDate" ng-change="setFormat()"> Enable Date Input' +
          '</label>' +
        '</div>' +
        '<div class="form-group">' +
          '<label for="datepickerMode" form-builder-tooltip="The initial view to display when clicking on this field.">Initial Mode</label>' +
          '<select class="form-control" id="datepickerMode" name="datepickerMode" ng-model="component.datepickerMode" ng-options="mode.name as mode.label for mode in modes"></select>' +
        '</div>' +
        '<div class="form-group">' +
          '<label for="placeholder" form-builder-tooltip="The minimum date that can be picked.">Minimum Date</label>' +
          '<div class="input-group">' +
            '<input type="text" class="form-control" ' +
              'ng-focus="minDateOpen = true" ' +
              'ng-init="minDateOpen = false" ' +
              'is-open="minDateOpen" ' +
              'datetime-picker="yyyy-MM-dd" ' +
              'enable-time="false" ' +
              'ng-model="component.minDate" />' +
            '<span class="input-group-btn">' +
              '<button type="button" class="btn btn-default" ng-click="minDateOpen = true"><i class="fa fa-calendar"></i></button>' +
            '</span>' +
          '</div>' +
        '</div>' +
        '<div class="form-group">' +
          '<label for="placeholder"  form-builder-tooltip="The maximum date that can be picked.">Maximum Date</label>' +
          '<div class="input-group">' +
            '<input type="text" class="form-control" ' +
              'ng-focus="maxDateOpen = true" ' +
              'ng-init="maxDateOpen = false" ' +
              'is-open="maxDateOpen" ' +
              'datetime-picker="yyyy-MM-dd" ' +
              'enable-time="false" ' +
              'ng-model="component.maxDate" />' +
            '<span class="input-group-btn">' +
              '<button type="button" class="btn btn-default" ng-click="maxDateOpen = true"><i class="fa fa-calendar"></i></button>' +
            '</span>' +
          '</div>' +
        '</div>' +
        '<div class="form-group">' +
          '<label for="startingDay" form-builder-tooltip="The first day of the week.">Starting Day</label>' +
          '<select class="form-control" id="startingDay" name="startingDay" ng-model="component.datePicker.startingDay" ng-options="idx as day for (idx, day) in startingDays"></select>' +
        '</div>' +
        '<div class="form-group">' +
          '<label for="minMode" form-builder-tooltip="The smallest unit of time view to display in the date picker.">Minimum Mode</label>' +
          '<select class="form-control" id="minMode" name="minMode" ng-model="component.datePicker.minMode" ng-options="mode.name as mode.label for mode in modes"></select>' +
        '</div>' +
        '<div class="form-group">' +
          '<label for="maxMode" form-builder-tooltip="The largest unit of time view to display in the date picker.">Maximum Mode</label>' +
          '<select class="form-control" id="maxMode" name="maxMode" ng-model="component.datePicker.maxMode" ng-options="mode.name as mode.label for mode in modes"></select>' +
        '</div>' +
        '<form-builder-option property="datePicker.yearRange" label="Number of Years Displayed" placeholder="Year Range" title="The number of years to display in the years view."></form-builder-option>' +

        '<form-builder-option property="datePicker.showWeeks" type="checkbox" label="Show Week Numbers" title="Displays the week numbers on the date picker."></form-builder-option>' +
      '</ng-form>'
    );

    $templateCache.put('formio/components/dateRange/time.html',
                   '<ng-form>' +
                     '<div class="checkbox">' +
                       '<label form-builder-tooltip="Enables time input for this field.">' +
                         '<input type="checkbox" id="enableTime" name="enableTime" ng-model="component.enableTime" ng-checked="component.enableTime" ng-change="setFormat()"> Enable Time Input' +
                       '</label>' +
                     '</div>' +
                     '<form-builder-option property="timePicker.hourStep" type="number" label="Hour Step Size" title="The number of hours to increment/decrement in the time picker."></form-builder-option>' +
                     '<form-builder-option property="timePicker.minuteStep" type="number" label="Minute Step Size" title="The number of minutes to increment/decrement in the time picker."></form-builder-option>' +
                     '<form-builder-option property="timePicker.showMeridian" type="checkbox" label="12 Hour Time (AM/PM)" title="Display time in 12 hour time with AM/PM."></form-builder-option>' +
                     '<form-builder-option property="timePicker.readonlyInput" type="checkbox" label="Read-Only Input" title="Makes the time picker input boxes read-only. The time can only be changed by the increment/decrement buttons."></form-builder-option>' +
                   '</ng-form>'
                 );

    $templateCache.put('formio/components/dateRange/validate.html',
      '<ng-form>' +
        '<form-builder-option property="validate.required"></form-builder-option>' +
        '<form-builder-option-custom-validation></form-builder-option-custom-validation>' +
      '</ng-form>'
    );

    $templateCache.put('formio/formbuilder/tool.html', FormioUtils.fieldWrap(
        '<div class="row">' +
            '<div class="col-xs-2 component-form-group" ng-repeat="component in component.columns">' +
                '<form-builder-list class="formio-column" component="component" form="form" formio="::formio"></form-builder-list>' +
            '</div>' +
        '</div>'
     ));
    // Create the settings markup.
    $templateCache.put('formio/components/tool/display.html',
     '<ng-form>' +
      '<form-builder-option property="customClass"></form-builder-option>' +
    '</ng-form>'
    );
}})();
dim2k2006 commented 7 years ago

@prashant93 I don't understand how to define template for my custom component, since i can't find folder "formio/components/" inside ngFormBuilder project. Did i misunderstood something? Can you help me?

prashant93 commented 7 years ago

formio/components/ is the way formio parse your template as component. You can look this line "template: 'formio/components/ "for all components in ngFormBuilder-full.js

rjaffari commented 7 years ago

Hi @prashant93:

I have created a custom component and marked it as required however it doesn't get validated. I put a breakpoint in the "checkErrors" function and I do not see my custom component in the "$scope.formioForm" object. I do see all the other components in there. Do I need to register my custom components some where OR do I need to have a specific attribute in my component definition?

Thanks for your help.

darrell-aevum commented 7 years ago

I am having the same issue as rjaffari.