Getting ready for coding period.

Before the coding period starts. Requirements analysis and design is really important. So I have been working on the design of the components that I am going to build. I am advised to look for FHIR components that are of Maturity level 3 or 4. In the latest FHIR version 4.0. A lot of new components were added in the resource list. But almost all of them are of Maturity level 0 (draft). I cant really use them right now.

Before going for the new components. Let’s look at the current state of the project. As I am continuing the project from last year. We don’t want to repeat any components / resources.

Current State

Last year. A lot of work was done. 2 students worked on the project. Around 38 components were created. Which covered the following resources:

Resources:

  • Patient
  • Organisation
  • AllergyIntolerance
  • Location
  • Practitioner

All the components are made in Polymer 3. And testing was performed using web-component-tester.

Currently all the components are placed in the packages directory. I think it might be a good idea to refactor the structure of the directory making sub directories for each resource and a separate directory for the general purpose components. I think that would be make things easier manage as the list of components grows.

Let’s look at the structure of current component. For example lets take the

human-name component:

Imports:

At the top we have our imports. First is the compulsory LitElement, html import which we will use to create the component. Then there is material text-field. Material design was chosen for the elements. So that all the elements have consistent styling. After that as the human name resource has a period. So we are importing the period component which is built separately. At the last we have iron-ajax. It is used for sending and parsing ajax calls. It is used for testing the components here. We will get back to iron-ajax in a bit.

import {LitElement, html} from '@polymer/lit-element/lit-element.js';
import '@material/mwc-textfield/mwc-textfield.js';
import '@lh-toolkit/fhir-period/fhir-period.js';
import '@polymer/iron-ajax/iron-ajax.js';

State:

Now here we define the state of our components. Similar to how we have props in react and inputs in angular. We also have our state / properties in polymer. The useField is actually used to display or hide the component.

static get properties() {
        return {
            /**useField is a selectable option for use of name. Use this property to show/hide. Default: true */
            useField: String,
            /**suffixField is show suffix. Use this property to show/hide. Default: true */
            suffixField: String,
            /**prefixField is used to show prefix. Use this property to show/hide. Default: true */
            prefixField: String,
            /**fName is to show first name of a person. Use this property to show/hide. Default: true */
            fName: String,
            /**lName is to show last name of a person. Use this property to show/hide. Default: true */
            lName: String,
            /**mName is to show mName name of a person. Use this property to show/hide. Default: false */
            mName: String,
            /**periodField is to have start and end dates. Use this property to show/hide. Default: false */
            periodField: String,
            /**url is used to make AJAX call to FHIR resource. Default: null */
            url: String,
            /**value is used to take the input value of each field*/
            value: Array
        }
    }

Constructor:

As we know constructor is called as soon as the component is instantiated. So here we are just setting the default values of our state.

constructor() {
        super();
        this.useField = 'true';
        this.suffixField = 'true';
        this.prefixField = 'true';
        this.fName = 'true';
        this.mName = 'false';
        this.lName = 'true';
        this.periodField = 'false';
        this.value = [{given:[]}];
    }

_didRender:

Similar to the ngAfterInit in angular. And I believe its componentDidMount in react. The didRender is lifeCycle hook in polymer. It executes when the components has completed rendered. In here we are using it for the iron-ajax response. Adding an event listener to it. So that when the ajax request is made. We set the value of our form / state to that of the response. This way we can test the component that it has the correct value.

_didRender() {
        this.shadowRoot.getElementById('ajax').addEventListener('iron-ajax-response', function (e) {
            var humanName = this.parentNode.host;
            if(e.detail.response.name !== undefined) {
                humanName.value = e.detail.response.name;
            }
            else {
                this.parentNode.removeChild(this.parentNode.querySelector('#humanNameDiv'));
            }
        });
    }

_Render:

This is the fun part. Here we render our html. In react we render JSX. But in polymer. Similar to angular. We have html templates in which we can use string interpolation. Also it supports 2 way data binding. So our state and the template is connected. Here we are just creating the form. And binding the value of the form fields to that of our state.

_render({useField, suffixField, fName, mName, lName, periodField, url, prefixField, value}) {
        if (typeof(value) == "string") {
            this.value = JSON.parse(value);
        }
        return html`${this.value.map((i, index) => html`
   <div id="humanNameDiv">
   <label>Name:</label>
   ${useField !== 'false' ? html`
     <label>Use:</label>
     <select class="useField" value="${i.use}" on-change="${e => this.value[index].use = e.target.value}">
         <option value="usual">Usual</option>
         <option value="official">Official</option>
         <option value="temp">Temporary</option>
         <option value="nickname">Nickname</option>
         <option value="anonymous">Anonymous</option>
         <option value="old">Old</option>
         <option value="maiden">Maiden</option>
     </select>` : ''}
     ${prefixField !== 'false' ? html`<mwc-textfield outlined class="prefixField" value="${i.prefix}" on-input="${e => this.value[index].prefix = e.target._input.value}" id="prefix" label="Prefix"></mwc-textfield>` : ''}
     ${fName !== 'false' ? html`<mwc-textfield outlined class="fName" value="${mName !== 'false' ? i.given[0]:i.given}" on-input="${(e) => mName !== 'false' ? this.value[index].given[0] = e.target._input.value:this.value[index].given = e.target._input.value}" label="First Name:"></mwc-textfield>` : ''}
     ${mName !== 'false' ? html`<mwc-textfield outlined class="mName" value="${i.given[1]}" on-input="${e => this.value[index].given[1]= e.target._input.value}" label="Middle Name:"></mwc-textfield>` : ''}
     ${lName !== 'false' ? html`<mwc-textfield outlined class="lName" value="${i.family}" on-input="${e => this.value[index].family = e.target._input.value}" label="Last Name:"></mwc-textfield>` : ''}
     ${periodField !== 'false' ? html`<fhir-period class="periodField"></fhir-period>` : ''}
     ${suffixField !== 'false' ? html`<mwc-textfield outlined class="suffixField" value="${i.suffix}" on-input="${e => this.value[index].suffix = e.target._input.value}" label="Suffix"></mwc-textfield>` : ''}
     </div>
     <iron-ajax id="ajax" bubbles auto handle-as="json" url="${url}"></iron-ajax>
    `)}`;
    }

And that’s pretty much it. We have our component. We combine all the components like these to make a full resource.

Going forward

Now its my turn. There are quite a few level 3 and 4 resources that I can work on. Following is the list of components with wire frames that I will be working on.

  • Appointment
  • Condition
  • Diagnostic Report

Resource Wireframes:

Components:

The above resource will be composed of several components. Following is the list of components that I will be building.

I have a few questions regarding some codeable concepts. As some of them have a lot of codes. Like 1000+ codes for components. How will we manage that on the front-end. I will be discussing that soon on the forum.

All in all. I am really excited for the coding period. I will try my best to complete all these in time. Wish me luck 😛

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.