Friday, October 1, 2021

Creating Your First SMART on FHIR Application

Overview

SameerDoshi_0-1633098858171.png

 

SMART on FHIR is a set of open specifications to integrate partner applications with FHIR servers and electronic medical records systems that have FHIR interfaces. One of the main purposes of the specifications is to describe how an application should discover authentication endpoints for an FHIR server and start an authentication sequence.

You can use SMART on FHIR to create cloud hosted apps that can then interact, securely, with any FHIR compatible EMR.

What the series covers

  1. Creating the app (YOU ARE HERE)
  2. Integrate the app with your EMR (previous article)
  3. Host the app (coming soon- use this document for now)

What the series does not cover:

(Don’t worry about these if you don’t have them, we can use the SMART app launcher instead)

  1. Setting up a scenario specific application (but you can find instructions on the FHIR Blaze repo)
  2. Setting up an EMR (but you can find instructions on Open EMR’s page)
Note: Quick start: You can use the SMART on FHIR starter kit to get started.  It’s a fully coded version of this tutorial.

 

Prerequisites

You’ll need a development environment so if you don’t have the following please install them:

Visual Studio Code

Node.js

 

(Optional) You’ll need a FHIR capable EMR, or a scenario-specific application.

EMR: Open EMR
Scenario-specific-application: FHIR-Blaze

Don't worry if you don't have an EMR or SSApp.  We can use the SMART Launcher without installing anything.


Create the app

 

Setup our project

Follow the instructions on the Create React App to create our basic app.

Now we’ll need to add some packages!

yarn add  fhirclient fhir-visualizers react-bootstrap react-hook-form

 

Why are we installing each package:

fhirclient – will interpret input data, make a secure connection to the FHIR backend and fetch patient data

fhir-visualizers – will format and present patient data

react-bootstrap – will be used to format our input form

react-hook-form – will be used to process data from our form

From here- let’s get the app started

yarn start

This will pop open a browser to http://localhost:3000 that displays the CRA boiler plate.

 

Fetch patient  data from FHIR backend

Let’s pop open index.js and add code to fetch the patient.

Add a reference to the fhirclient object:

import FHIR from 'fhirclient';

 

Initializing the FHIR client is simple.  The code below calls the oauth2 initialization method with two variables.   Client ID is a unique identifier for your app.  This identifier is registered in the FHIR Backend’s Identity prover as an authored client application.  The scope is the list of permissions that the app will request as the user. After the FHIR client authorizes the standard react code will run and start the App component.   Note that we’re passing the initialized fhirclient to the App component as a property.

const smartLaunch = () => {

  FHIR.oauth2

    .init({

      clientId: '20560ea5-f224-4658-b667-4e6bab935c85',

      scope: 'launch/patient openid profile'

    })

    .then(client => {

      ReactDOM.render(<App client={client} />, rootElement);

    });

};

 

Note: From here on you cannot just open a browser to run the app.  You MUST run it with a SMART launcher- either an EMR, a scenario specific app, or the SMART Launcher referenced above. 

 

For simplicity let’s use the SMART launcher. 

  1. Open the SMART Launcher in a new browser

SameerDoshi_1-1633098858179.png

 

  1. Leave everything as default, at the bottom of the form change the launch url to http://localhost:3000

SameerDoshi_2-1633098858185.png

 

  1. Click “Launch”  A pop up simulating an EMR will open.  Click Login

SameerDoshi_3-1633098858191.png

 

  1. Select any patient on the next list

SameerDoshi_4-1633098858200.png

 

  1. Finally the app will open.  But our app doesn’t do anything yet it just displays the create react app.  We’ll change this next!

SameerDoshi_5-1633098858210.png

 

 

Displaying the Patient Data

Visualizing the Patient is super easy with the visualizer component.

Let’s pop open our App component and add a reference to the visualizer.

import {PatientVisualizer} from 'fhir-visualizers';

 

We need to grab the fhirclient from the component’s properties.  We’ll want to store the patient data object in state, so we need to initialize it (as null) and create our setter.  Next, the MAFIC of fhir.js.  We need only call client.patient.read() to get the patient data!   Finally we set that to state.

const client=props.client;

  const [patient, setPatient] = useState(null);

  useEffect(() => {

    client.patient.read().then((patient) => setPatient(patient));

  });

 

Next in our return let’s replace all the CRA boiler-plate with the patient visualizer.  We’ll want to display a loading indicator while the fhirclient fetchs the data so we’ll use an ternary operator to either display the visualizer or a Loading message.

return (

 <div id="app">

{patient?

  <PatientVisualizer patient={patient} />

  : <h1>Loading</h1>;}

</div>);

 

Let’s load our app again!

SameerDoshi_6-1633098858221.png

 

 

Ok so with less than 50 lines of code we’ve managed to securely fetch a patient data set and render it!  Let’s go one step further and modify the patient record.

Rendering a form

With react-hook-forms and react-bootstrap it’s very easy to render a nice looking form.

Let’s import both.

import { useForm } from "react-hook-form";
import {Spinner, Container, Button, Form} from "react-bootstrap";
import 'bootstrap/dist/css/bootstrap.min.css';

We’ll need to initialize react-hook-forms.

const { register, handleSubmit, formState: { errors } } = useForm();

 

handleSubmit is a function that will be called on form submission.  In it we’ll take the first name and last name fields and reset them on the patient object.  Then we’ll have the fhir client update the patient object.

const onSubmit = data => {
    let np=patient;
    np.name[0].given[0]=data.fname;
    np.name[0].family=data.lname;
    setPatient(np);
    client.update(np);
  };

 

 

To render the we register input fields. 

 

<Container>
 <h4>Update Patient Name</h4>
  <Form onSubmit={handleSubmit(onSubmit)}>
        <Form.Group className="mb-3" controlId="formFirst">
        <Form.Label>First</Form.Label>
        <Form.Control type="text" {...register("fname")} defaultValue={ patient.name[0].given.join(' ')} />
        </Form.Group>
        <Form.Group className="mb-3" controlId="formLast">
        <Form.Label>Last</Form.Label>
        <Form.Control type="text" {...register("lname")} defaultValue={ patient.name[0].family } />

        </Form.Group>
        <Button type="submit" >Update</Button>
      </Form>
</Container>

 

Now when we rerun the app we get the form, and it works!

SameerDoshi_7-1633098858224.png

 

 

 

Review

That’s it!  We’ve now fetched and modified a FHIR resource and it took us less than 100 lines of code!

What’s Next?

If you've ever had a piece of functionality you've wanted to add to an EMR you can code it in a SMART on FHIR app- using all the web dev tech you already know. Then just add that app to your EMR.

 

An example use of this is the Chestist demo app that packages ML assisted image analysis.

Posted at https://sl.advdat.com/3D6lOkG