Skip to content

Resource Management

Travis Tidwell edited this page Aug 23, 2017 · 12 revisions

One major component of Form.io is the ability to manage Resources within your Serverless application. This library provides a mechanism to allow you to easily introduce those Resources within your application so that you can provide all of the CRUD capabilities of these resources to your users of the application.

Building your resources

To get started, you will first need to create a separate module for each Resource you wish to bring into your application. As a quick example, lets suppose that we wish to add new Users to our application. Assuming that this resource has an API url of https://myproject.form.io/user, we can register this within our application using the following code.

user.module.ts

import { NgModule, Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule } from '@angular/router';
import { FormioAppConfig } from 'angular-formio';
import {
  FormioResourceModule,
  FormioResourceRoutes,
  FormioResourceConfig,
  FormioResourceService
} from 'angular-formio/resource';

@NgModule({
  imports: [
    CommonModule,
    FormioResourceModule,
    RouterModule.forChild(FormioResourceRoutes())
  ],
  providers: [
    FormioResourceService,
    {provide: FormioAppConfig, useValue: {
      appUrl: 'https://myproject.form.io',
      apiUrl: 'https://api.form.io'
    }},
    {provide: FormioResourceConfig, useValue: {
      name: 'user',
      form: 'user'
    }}
  ]
})
export class UserResource {}

This will register all of the CRUDI routes within the UserResource class so that they can be provided within the application.

Custom Components

Now let's suppose that you wish to provide your own custom component for the User view page where you provide your own template, as well as introduce your own business logic. You can do this by simply extending the FormioResourceViewComponent class and then adding it to the route registration like so.

import { NgModule, Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule } from '@angular/router';
import { FormioAppConfig } from 'angular-formio';
import {
  FormioResourceModule,
  FormioResourceRoutes,
  FormioResourceConfig,
  FormioResourceViewComponent,
  FormioResourceService
} from 'angular-formio/resource';

@Component({
  template:
    '<div class="panel panel-default" *ngIf="service.resourceLoaded | async">' +
      '<div class="panel-heading">' +
        '<h3 class="panel-title">{{ service.resource.data.firstName }} {{ service.resource.data.lastName }}</h3>' +
      '</div>' +
      '<div class="panel-body">' +
        '<div class="well">' +
          '<p>This is a custom template for the user view.</p>' +
        '</div>' +
        '<table class="table table-striped table-bordered">' +
          '<thead>' +
            '<tr>' +
              '<th>Property</th>' +
              '<th>Value</th>' +
            '</tr>' +
          '</thead>' +
          '<tbody>' +
            '<tr><td>First Name</td><td>{{ service.resource.data.firstName }}</td></tr>' +
            '<tr><td>Last Name</td><td>{{ service.resource.data.lastName }}</td></tr>' +
            '<tr><td>Email</td><td>{{ service.resource.data.email }}</td></tr>' +
          '</tbody>' +
        '</table>' +
      '</div>' +
    '</div>'
})
export class UserViewComponent extends FormioResourceViewComponent {
  constructor(service: FormioResourceService) {
    super(service);
  }
}

@NgModule({
  imports: [
    CommonModule,
    FormioResourceModule,
    RouterModule.forChild(FormioResourceRoutes({
      view: UserViewComponent
    }))
  ],
  providers: [
    FormioResourceService,
    {provide: FormioAppConfig, useValue: {
      appUrl: 'https://myproject.form.io',
      apiUrl: 'https://api.form.io'
    }},
    {provide: FormioResourceConfig, useValue: {
      name: 'user',
      form: 'user'
    }}
  ],
  declarations: [
    UserViewComponent
  ]
})
export class UserResource {}

Once you have done this, your View component will now be executed when the user visits the view page of the User component.

Mounting the User Resource

The last thing that needs to be done is that the User resource needs to be "mounted" within the main application. This can be done using the loadChildren construct within the router. We can do this as follows.

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RouterModule, Routes } from '@angular/router';
import { FormioModule } from 'angular-formio';
import { MainComponent } from './main';

@NgModule({
  imports: [
    BrowserModule,
    FormioModule,
    RouterModule.forRoot([
      {
        path: 'user',
        loadChildren: './user.module#UserResource'
      }
    ])
  ],
  declarations: [
    MainComponent
  ],
  bootstrap: [
    MainComponent
  ]
})
export class AppModule {}

Nested (hierarchical) Resources

Within this library, you can also created Nested, or Hierarchical Resources. This is useful if you wish to have some resources be the child of other resources. An example of this would be if you were creating an Event management system, you may wish to have Activities available for that Event. You would, therefore, create an Event Resource within Form.io, and then Create an Activity resource that has the Event Resource Field that points to its parent. If you wish to create a project with this configuration, then you can go to https://portal.form.io, and use this project.json as your template when creating your project.

https://github.com/formio/angular-app-starterkit/blob/master/src/project.json

Once you have that project created, you can now establish the nesting of resources by first creating the Event resource as well as the Activity resource.

activity.resource.ts

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule } from '@angular/router';
import { FormioAppConfig } from 'angular-formio';
import {
  FormioResourceModule,
  FormioResourceRoutes,
  FormioResourceConfig,
  FormioResourceService
} from 'angular-formio/resource';

@NgModule({
  imports: [
    CommonModule,
    FormioResourceModule,
    RouterModule.forChild(FormioResourceRoutes())
  ],
  providers: [
    FormioResourceService,
    {provide: FormioAppConfig, useValue: {
      appUrl: 'https://myproject.form.io',
      apiUrl: 'https://api.form.io'
    }},
    {provide: FormioResourceConfig, useValue: {
      name: 'activity',
      form: 'activity',
      parents: ['event']
    }}
  ]
})
export class ActivityResource {}

event.resource.ts

import { NgModule, Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule, Routes, ActivatedRoute } from '@angular/router';
import { FormioAppConfig } from 'angular-formio';
import {
  FormioResourceModule,
  FormioResourceRoutes,
  FormioResourceConfig,
  FormioResourceService,
  FormioResourceComponent
} from 'angular-formio/resource';

let eventResourceRoutes: Routes = FormioResourceRoutes();
eventResourceRoutes[2].children.push({
  path: 'activity',
  loadChildren: 'es6-promise-loader?,[name]!../activity/activity.module#ActivityResource'
});

@NgModule({
  imports: [
    CommonModule,
    FormioResourceModule,
    RouterModule.forChild(eventResourceRoutes)
  ],
  declarations: [
    EventResourceComponent
  ],
  providers: [
    FormioResourceService,
    {provide: FormioAppConfig, useValue: {
      appUrl: 'https://myproject.form.io',
      apiUrl: 'https://api.form.io'
    }},
    {provide: FormioResourceConfig, useValue: {
      name: 'event',
      form: 'event'
    }}
  ]
})
export class EventResource {}

Notice in the Activity Resource declaration, that we provide the parents parameter to the FormioResourceConfig. This is what establishes the hierarchy and tells the Activity resource to ensure that the Event resource is loaded and populated when filling out the forms and viewing the indexes.

For a full working example of how this works, take a look at the Angular App Starterkit

Full Working Example

For a full working application example of how this works, please take a look at the Angular App Starterkit project.