Search code examples
ember.jsmetadatasugarcrm

How to build a meta-driven application in emberJS


Note: The English used in this article (along with the terms) may be a bit "out of order" since my native language is not English. Rest assured I have tried my best to make it as readable as possible, and if I have missed anything please do comment before downvoting so I may update the question accordingly (I'm still new to this)

So I've searched most of the internet for a solution to this, to find a tutorial that would guide me on the metadata driven approach for building an application on EmberJS. The documentation on Ember doesn't explain anything about the approach, just a function definition of extractMeta here, and a basic overview of how to handle metadata here.

What I want to achieve is to build a portal, with Sugar as the back-end for the application. The application will use REST API for making calls to extract the data as well as the metadata of the application. We want to make the application generic, so that no matter what module is called, the metadata is extracted to determine the fields required in the model, a filtered portion of the data needed from the call is populated into the model accordingly and the is displayed in a generic template, that will be global and used throughout the application.

The metadata includes various items such as buttons, panels, attributes(each with multiple layers of data within) etc, each may be used once or multiple times within the call or not at all. For example, for displaying the application would require the attributes for display within the table, as well as buttons for adding, deleting updating etc. Upon click the panel may be required for say, adding a particular record, which itself may contain various fields.

list As an example, is the default Sugar instance that shows the leads in the data, notice how it contains various components.

add data Here, another example, of the panel that appears when I click the create button in the leads list, notice the fields that appear within the panel

Please Note that I do understand how to make the REST API calls for the data as well as the metadata. But how to turn that into a generic meta driven application is what I am struggling with. Thanks in advance!


Solution

  • If I understand this correctly, you're looking for some kind of generic UI builder based off of returned data from a REST endpoint. Ember provides the component helper.

    The {{component}} helper can be used to defer the selection of a component to run time. The {{my-component}} syntax always renders the same component, while using the {{component}} helper allows choosing a component to render on the fly. This is useful in cases where you want to interact with different external libraries depending on the data. Using the {{component}} helper would allow you to keep different logic well separated.

    {{#each model as |post|}}
      {{!-- either foo-component or bar-component --}}
      {{component post.componentName post=post}}
    {{/each}}
    

    Read here for a more thorough explanation.

    What you essentially need to do is build a bunch of different components for each of the possible attributes from the metadata. Your models will contain what components they should render and you'll use the component helper to dynamically render the correct elements.

    If you're using a table based approach, have a look at ember light table. They leverage this approach heavily with how they build the columns for their tables and support custom components:

    columns: computed(function() {
        return [{
          label: 'Avatar',
          valuePath: 'avatar',
          width: '60px',
          sortable: false,
          cellComponent: 'user-avatar'
        }, {
          label: 'First Name',
          valuePath: 'firstName',
          width: '150px'
        }];
      })
    

    As you see here, the columns are rendered generically and they use the cellComponent property to determine which component type to render.