FormioResource Provider

Travis Tidwell edited this page Feb 4, 2017 · 18 revisions

The FormioResource provider allows you to register your Form.io Resources so that all of your UI Router CRUD states will be registered for you. In almost every case, a FormioResource will be registered for any Resource you have within your Form.io project. For example, if you create a Customer Resource within your Form.io project, a new FormioResource will be registered to represent the CRUD operations for that Customer within your application.

For every resource registration, there are 5 main states that you need to be concerned with when working with the FormioResource provider.

  • Index: This is the view which shows all of the submissions for a Resource within Form.io. This view by default is provided by the ngFormioGrid library.
  • Create: This state is the "C" in CRUD which is used to create a new resource record (also called Submission in Form.io). This will render the form for that resource.
  • Abstract: This state is used as the resource instance container for the Read, Update, and Delete states. It provides the overarching controller which loads the resource instance and provides that resource instance to all of the sub states. This is a UI Router abstract state, which means you cannot actually navigate to this state, but rather just serves as the container for the Read, Update, and Delete states within it.
  • Read: This state provides the "view" of the resource submission.
  • Update: This state provides the means to update the resource submission.
  • Delete: This state provides the ability to delete the resource submission.

Resource Registration

After you have created a Resource within your Form.io project, the first task will be to bring in that Resource into your application. This can be done by "registering" that resource within your application using the FormioResource.register method as follows.

FormioResource.register(name, url, options)

Name Type Description
name String The name of the resource you created and wish to represent within your application. Example: For a Customer resource, this would probably be 'customer'
url String The URL to the Resource form within Form.io. Example: https://myproject.form.io/customer
options Object The options for this provider as follows. See FormioResource.register Options section below.
UI Router States

The following ui-router states are generated for each resource:

State URL Default Template
baseName+‘Index' url + name + queryParams /resource/index.html
baseName+‘Create' /create/ + name + queryParams /resource/create.html
baseName / + name + /: + queryId /resource/resource.html
baseName.’view' / /resource/view.html
baseName.’edit /edit /resource/edit.html
baseName.’delete' /delete /resource/delete.html

FormioResource.register Options

The following are the options provided to the FormioResource.register method.

Property Description
title The title to show for the resource within the Abstract view.
base The UI Router state that is the parent to this resource. This is handy for representing nested resources.
parent The name of the parent resource.
parents The names of all the "parent" resources for this resource. These are not UI router states, but rather just the names of the resources which are parents.
alter An object of alter handlers. See Altering states below
defaultValue The default value to provide to the Submission when creating a new resource in the Create state.
endpoint A custom endpoint to retrieve data for the Abstract state. Good for integration with external systems.
templates Overrides to the templates provided to each main state. See Overriding Templates below.
controllers Overrides to the controllers provided to each main state. See Overriding Controllers below.
query The query parameters to add to the UI Router states. See UI Router Query Params
params An object for the params to pass to each state for UI Router states. See Adding state params below.
data An object for the data to pass to each state for UI Router states. See Adding State Data below.
breadcrumb Adds a breadcrumb (thanks to Angular BreadCrumb to the Resource. See Adding Breadcrumbs below.

An example registration usually looks like the following.

angular.module('myApp', ['ui.router', 'ui.bootstrap', 'ngFormioHelper', 'formio'])
.constant('AppConfig', {
  appUrl: 'https://wuhdbdzaucyashb.form.io',
  apiUrl: 'https://api.form.io',
  customerForm: 'https://wuhdbdzaucyashb.form.io/customer'
})
.config([
  'AppConfig',
  'FormioProvider',
  'FormioAuthProvider',
  '$locationProvider',
  function(
    AppConfig,
    FormioProvider,
    FormioResourceProvider,
    $locationProvider
  ) {
    // Only use "#" for the states.
    $locationProvider.hashPrefix('');

    // Set the appUrl and the apiUrl
    FormioProvider.setAppUrl(AppConfig.appUrl);
    FormioProvider.setApiUrl(AppConfig.apiUrl);
    FormioResourceProvider.register('customer', AppConfig.customerForm, {
      templates: {
        view: 'views/customer/view.html'
      },
      controllers: {
        view: ['$scope', function($scope) {
          $scope.position = null;
          $scope.customer.loadSubmissionPromise.then(function (customer) {
            if (customer.data.address) {
              $scope.position = [
                customer.data.address.geometry.location.lat,
                customer.data.address.geometry.location.lng
              ];
            }
          });
        });
      }
    }); 

Overriding Templates

All of the templates provides by the FormioResource can be overridden and provided by the application itself. It is typically a good strategy to simply copy the templates found within the templates folder of this library, and then copy those into your application, and then provide the overrides as follows.

FormioResourceProvider.register('customer', AppConfig.customerForm, {
  ...
  ...
  templates: {
    index: 'views/customer/index.html',
    create: 'views/customer/create.html',
    abstract: 'views/customer/abstract.html',
    view: 'views/customer/view.html',
    edit: 'views/customer/edit.html',
    delete: 'views/customer/delete.html'
  }
  ...
  ...
}); 

Overriding Controllers

In addition to overriding templates, the controllers of Resources can also be overridden as well. In many cases, the FormioResource parent controller will also handle an event triggered by either the form submissions or data grids within the view. You can turn off the handling of those events by returning the following within your controller override.

return {handle: true};

Example:

FormioResourceProvider.register('customer', AppConfig.customerForm, {
  ...
  ...
  controllers: {
    index: ['$scope', '$state', function($scope, $state) {
      $scope.currentResource.gridOptions.namespace = 'customer';
      $scope.$on('customerView', function(event, customer) {
        $state.go('customer.view', {customerId: customer._id});
      });
    }),
    create: ['$scope', function($scope) {
      $scope.$on('formSubmission', function(event, submission) {
        console.log(submission);
      });
      // We will handle the form submission event.
      return {handle: true};
    });
  }
  ...
  ...
}); 

Altering States

Not only can you provide overrides to certain controllers and templates, but in extreme cases, you may need to override the entire UI Router state definition itself. You can do this using the alter property of the options where you can alter any state provided as follows.

FormioResourceProvider.register('customer', AppConfig.customerForm, {
  ...
  ...
  alter: {
    index: function(state) {
      // Change the URL of the UI Router state.
      state.url = '/customurl';
      return state;
    }
  }
  ...
  ...
}); 

Adding State Parameters

UI Router provides a great way to pass in parameters into its states. To read more about this, you can read about state parameters at the UI Router State Parameter documentation. You can add these to each state by referencing the state ID as follows.

FormioResourceProvider.register('customer', AppConfig.customerForm, {
  ...
  ...
  params: {
    index: {foo: 'bar'},
    create: {test: 'param'}
  }
  ...
  ...
}); 

Adding State Data

Just like you can add custom state params, you can also add custom state data into the UI Router states as well.

FormioResourceProvider.register('customer', AppConfig.customerForm, {
  ...
  ...
  data: {
    index: {foo: 'bar'},
    create: {test: 'param'}
  }
  ...
  ...
}); 

Adding State Breadcrumbs

With the help of Angular Breadcrumbs, you can also include Breadcrumb support within your application by registering for Resource routes. In order to do this, you will first need to install and include the angular-breadcrumbs library in your application using the following.

bower install --save angular-breadcrumb

And then include it in your application module.

angular.module('myApp', ['ui.router', 'ui.bootstrap', 'ngFormioHelper', 'formio', 'ncy-angular-breadcrumb']) 

Once you do this, you can provide the breadcrumb for your Resource using the following parameter. You may use Angular.js binding to bring in the resource data into the breadcrumb item.

FormioResourceProvider.register('customer', AppConfig.customerForm, {
  ...
  ...
  breadcrumb: {
    label: '{{ customer.data.firstName }} {{ customer.data.lastName }}'
  }
  ...
  ...
}); 

Hiding and Defaulting Components

When you are within the Create and Edit states, you are able to hide and default certain components within the form using the $scope.hideComponents array, as well as have access to the $scope.submission of that resource as well. These two can be used to provide a default as well as hide certain components within the form. As an example, lets say you have a Resource that has a Status field which you wish to hide within the create state and also provide a default. The way this works is as follows.

FormioResourceProvider.register('customer', AppConfig.customerForm, {
  controllers: {
    create: ['$scope', function($scope) {
      // Default the status to pending.
      $scope.submission = {
        status: 'pending'
      };

      // Hide the field so they cannot change it.
      $scope.hideComponents = ['status'];
    }]
  }
});