Creating reusable FHIR components.

So this week I started on created web components. The first resource that I wanted to target was Appointment resource. As it contained the most components that will be reused in other components. To get some more insight on the resource. I also went through the examples at the FHIR test server. I looked at the appointment resource. ie: http://hapi.fhir.org/baseDstu3/Appointment/1966105/_history/1

{
  "resourceType": "Appointment",
  "id": "1966105",
  "meta": {
    "versionId": "1",
    "lastUpdated": "2019-06-22T23:20:15.284+00:00"
  },
  "text": {
    "status": "generated",
    "div": "<div xmlns=\"http://www.w3.org/1999/xhtml\"><div>Routine checkup</div><div>Dr Dave</div></div>"
  },
  "status": "pending",
  "description": "Routine checkup",
  "start": "2019-06-29T16:20:15-07:00",
  "end": "2019-06-29T16:35:15-07:00",
  "minutesDuration": 15,
  "participant": [
    {
      "actor": {
        "display": "Dr Dave"
      },
      "status": "accepted"
    },
    {
      "actor": {
        "reference": "Patient/1966031"
      },
      "status": "accepted"
    }
  ]
}

So looking at the example and the FHIR documentation for the appointment resource. I see that I will need the following components that I need to build for the.

  1. fhir-instant: Instant is similar to datetime which we have already used. But it is different in a way that it also contains the time and AM/PM. So it used when we need exact time. Which in our case. We need for the start and end of the appointment.
  2. fhir-positiveInt: In the resource we have minutes duration. Which tells the number of minutes the appointment will take. And this number has to be positive.
  3. fhir-appointment-status: This is a code component. Which will contain the select options for the status. Which can be either: Proposed, pending, booked, arrived, fulfilled, cancelled, noshow, entered in error, checked-in, waitlist.
  4. fhir-reference: This again is a type component. Which will be used in a lot of resource. It contains the display name and the reference url of the resource which we are targeting.
  5. fhir-appointment-participant: This component contains the participants of the appointment. It also contains the reference resource that we created earlier as “actor”
  6. fhir-create-appointment: This component will combine all components and post the result.

So as I was going to create the appointment resource. I created a git branch for this. After creating each component I committed the changes.

fhir-instant: commit

For the instant. We can use the datetime-local type for our inputs. And then return its value.

<div id="instantDiv">
        ${instant !== 'false'
          ? html`
              <mwc-formfield class="instant" alignEnd>
                <input
                  id="date"
                  type="datetime-local"
                  value="${this.value}"
                  on-input="${e => (this.value = e.target.value)}"
                />
              </mwc-formfield>
            `
          : ''}
      </div>

fhir-positiveint: commit

For the positive int. I am using the type number with min value as 0. So that we can only add positive values.

<div id="positiveIntDiv">
        ${positiveInt !== 'false'
          ? html`
              <mwc-formfield class="positiveInt" alignEnd">
                <input
                  id="positiveInt"
                  type="number"
                  min="0"
                  value="${this.value}"
                  on-input="${e => (this.value = e.target.value)}"
                />
              </mwc-formfield>
            `
          : ''}
      </div>

fhir-appointment-status: commit

For the appointment status. We are using the select component. As in MWC the mwc-select is not available and is under development.

<div id="appointmentStatus">
        ${typeField !== 'false'
          ? html`
              <label>Status:</label>
              <select
                class="typeField"
                value="${this.value}"
                on-change="${e => (this.value = e.target.value)}"
              >
                <option value="proposed">Proposed</option>
                <option value="pending">Pending</option>
                <option value="booked">Booked</option>
                <option value="arrived">Arrived</option>
                <option value="fullfilled">Fulfilled</option>
                <option value="cancelled">Cancelled</option>
                <option value="noshow">No Show</option>
                <option value="entered-in-error">Arrived</option>
                <option value="checked-in">Checked in</option>
                <option value="waitlist">Waitlist</option>
              </select>
            `
          : ''}
      </div>

fhir-reference: commit

For the reference we are using 2 input fields. Display and the Reference. Which points to the resource document.

<div id="referenceDiv">
        ${reference !== 'false'
          ? html`
              <label>Reference</label>
              <mwc-textfield
                outlined
                class="reference"
                value="${this.value.reference}"
                on-input="${e =>
                  (this.value.reference = e.target._input.value)}"
              ></mwc-textfield>
            `
          : ''}
        ${display !== 'false'
          ? html`
              <label>Display</label>
              <mwc-textfield
                outlined
                class="display"
                value="${this.value.display}"
                on-input="${e => (this.value.display = e.target._input.value)}"
              ></mwc-textfield
              ><br />
            `
          : ''}
      </div>

fhir-appointment-participant: commit

The participant in appointment contains the reference as an actor. As well as its status. So we are importing the reference components here and add the status as a select option.

<div id="participantDiv">
        ${status !== 'false'
          ? html`
              <label>Status:</label>
              <select
                class="status"
                value="${this.value.status}"
                on-change="${e => (this.value.status = e.target.value)}"
              >
                <option value="accepted">Accepted</option>
                <option value="declined">Declined</option>
                <option value="tentative">Tentative</option>
                <option value="needs-action">Needs Action</option>
              </select>
            `
          : ''}
        ${reference !== 'false'
          ? html`
              <fhir-reference
                class="reference"
                value="${this.value.actor}"
                on-input="${e => (this.value.actor = e.target.value)}"
              ></fhir-reference>
            `
          : ''}
      </div>

fhir-create-appointment: commit

And the create appointment basically just imports all the required components and posts them.

_render({ url }) {
    return html`
      <fhir-appointment-status id="appointmentStatus"></fhir-appointment-status>
      <p>Start:</p>
      <fhir-instant id="start"></fhir-instant>
      <p>End:</p>
      <fhir-instant id="end"></fhir-instant>
      <p>Minutes Duration:</p>
      <fhir-positiveint id="minutes"></fhir-positiveint>
      <p>Participant:</p>
      <fhir-appointment-participant
        id="participant"
      ></fhir-appointment-participant>

      <br />
      <mwc-button id="button" raised on-click=${() => this.doPost()}
        >Submit</mwc-button
      >
      <iron-ajax
        bubbles
        method="POST"
        id="ajax"
        url="${url}"
        on-response="handleResponse"
      ></iron-ajax>
    `;
  }
  doPost() {
    var status = this.shadowRoot.getElementById('appointmentStatus').value;

    var start = this.shadowRoot.getElementById('start').value;
    var end = this.shadowRoot.getElementById('end').value;
    var minutes = this.shadowRoot.getElementById('minutes').value;
    var participant = this.shadowRoot.getElementById('participant').value;

    this.shadowRoot.getElementById('ajax').contentType = 'application/json';
    this.shadowRoot.getElementById('ajax').body = {
      resourceType: 'appointment',
      status: status,
      start: start,
      end: end,
      minutesDuration: minutes,
      participant: participant
    };
    this.shadowRoot.getElementById('ajax').generateRequest();
  }

Some of the components are not in material design. Like the select component. As we are using mwc and they are still under progress. Several issues have been created on gitlab regarding this. #24 #29 #32 #40 . Hopefully we will soon have more mwc components so we can use them.

Next up: In the next month. I am hoping to create all components for the required resources and add their demos in the index.html. So that in the last month. I am only left with testing and add the demos in the proof of concept application.

Leave a Reply

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