8

HL7 FHIR Objects in Blazor

 2 years ago
source link: https://techcommunity.microsoft.com/t5/healthcare-and-life-sciences/hl7-fhir-objects-in-blazor/ba-p/2955865?WT_mc_id=DOP-MVP-4025064
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
HL7 FHIR Objects in Blazor

HL7 FHIR Objects in Blazor

Published Nov 11 2021 10:23 AM 515 Views




When we initially developed our open-source FhirBlaze application we ran into several problems when attempting to create a Patient.  The Patient class is complex (FHIR Patient spec) and contains complex properties that do not lend themselves to easy integration with Blazor’s excellent EditForm component.

But let’s back up and see how a simplified Patient might be created.

Using a Simple Model

Let’s say we want our Patient to have:

Our SimplePatient model would look like this:





public class SimplePatient
{
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string PatientID { get; set; } 
        public DateTime Birthdate { get; set; } 
}






Then it’s pretty easy to create an EditForm to model against this class:





<EditForm Model="Patient" OnValidSubmit="SavePatient" class="form-horizontal">
	    <DataAnnotationsValidator/>
	    <ValidationSummary />
	    <div class="form-group">
	        <label>ID</label>
	        <InputText required @bind-Value="Patient.PatientID" />
	   </div>
	   <div class="form-group">
	        <label>Birthday</label>
	        <InputDate required @bind-Value="Patient.Birthdate" />
	    </div>
	    <div class="form-group">
	        <label>First</label>
	        <InputText required @bind-Value="Patient.FirstName" />
	   </div>
	

	   <div class="form-group">
	        <label>Last</label>
	        <InputText required @bind-Value="Patient.LastName" />
	    </div>
	    @if (Processing)
	    {
	        <button type="button" class="btn btn-primary-outline" disabled  >Processing</button>
	    }
	    else{
	        <button type="submit" class="btn btn-primary">Save</button>
	    }
	</EditForm>






This then gives us a simple form and we can now create SimplePatients- but there’s a catch!  We’re not creating FHIR objects!  So we can’t store them in a FHIR capable system- and we can’t load Patients from a FHIR capable system into our app!

Complexity of FHIR Makes This Model Unscalable

At this point we have several options- we can create toFHIR() and fromFHIR() methods to our SimplePatient.  But this is complex and as we import more properties from FHIR into our SimplePatient  model- complexity will scale! Instead let’s use native HL7 FHIR objects

The Complexities of HL7 FHIR Objects

We’ll focus on Patient, but you’ll see examples of these problems on Practionier, Questionnaire, QuestionnaireResponse, and more!   You should be able to apply the principles below.

List Containing Complex Objects (Patient.Identifier)

Look at Patient.Id. It’s a list of Identifier Objects.  Each Identifier contains a string that represents the system for the Identifier (ex: “http://somelink.spac”) and a string representing the Value (ex: “123-123-123-123”). 

Representing this in a form would look like this:





<EditForm model=@Patient>
@foreach (var id in FhirPatient.Identifier)
    {
        <div class="form-group">
            <label>Patient ID </label>
            <InputText required @[email protected]/>
        </div>
    }
</EditForm>






List Containing Lists (Patient.Name.Family)

Look at Patient.Name.  It’s a list of HumanName objects.  Each HumanName contains a single Family name (ex: “Brown”).  Unlike the previous Identifier objects, each HumanName also contains a List of Given names (ex: “Dave”,”John”. 

We can use the same syntax as above for creating Family names:





@foreach(var PatientName in FhirPatient.Name)
    {
        <div class="form-group">
            <label>Family Name</label>
            <InputText required @[email protected] />
        </div>
    }




List Containing Arrays (Patient.Name.Given)

But for the Given name we can’t use a foreach because Given is an iEnumerable<string> and we can’t bind the contents of an iEnumerable.  Luckily we CAN manipulate the more complex GivenElement.  Each complex class will contain Elements that are exclusive to C#.





@foreach(var PatientName in FhirPatient.Name)
    {
         <div class="form-group">
          @foreach  (var gName in PatientName.GivenElement){
             <label>Given Name</label>
             <InputText required @bind-Value=@(((FhirString)gName).Value) />     
          }       
            
        </div>
         <div class="form-group">
            <label>Family Name</label>
            <InputText required @[email protected] />
        </div>
    }




Complete Example

You can see a complete example of the above in our FhirBlaze project.  Happy FHIR coding!





You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.

%3CLINGO-SUB%20id%3D%22lingo-sub-2955865%22%20slang%3D%22en-US%22%3EHL7%20FHIR%20Objects%20in%20Blazor%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-2955865%22%20slang%3D%22en-US%22%3E%3CP%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-inline%22%20image-alt%3D%22SameerDoshi_0-1636653589334.png%22%20style%3D%22width%3A%20400px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F326372iBB46D526FD1B3423%2Fimage-size%2Fmedium%3Fv%3Dv2%26amp%3Bpx%3D400%22%20role%3D%22button%22%20title%3D%22SameerDoshi_0-1636653589334.png%22%20alt%3D%22SameerDoshi_0-1636653589334.png%22%20%2F%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EWhen%20we%20initially%20developed%20our%20%3CA%20href%3D%22https%3A%2F%2Fgithub.com%2Fmicrosoft%2FFhirBlaze%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noreferrer%22%3Eopen-source%20FhirBlaze%3C%2FA%3E%20application%20we%20ran%20into%20several%20problems%20when%20attempting%20to%20create%20a%20Patient.%26nbsp%3B%20The%20Patient%20class%20is%20complex%20(%3CA%20href%3D%22https%3A%2F%2Fwww.hl7.org%2Ffhir%2Fpatient.html%22%20target%3D%22_blank%22%20rel%3D%22noopener%20nofollow%20noreferrer%22%3EFHIR%20Patient%20spec%3C%2FA%3E)%20and%20contains%20complex%20properties%20that%20do%20not%20lend%20themselves%20to%20easy%20integration%20with%20Blazor%E2%80%99s%20excellent%20EditForm%20component.%3C%2FP%3E%0A%3CP%3EBut%20let%E2%80%99s%20back%20up%20and%20see%20how%20a%20simplified%20Patient%20might%20be%20created.%3C%2FP%3E%0A%3CH2%20id%3D%22toc-hId--295155056%22%20id%3D%22toc-hId--295155026%22%3EUsing%20a%20Simple%20Model%3C%2FH2%3E%0A%3CP%3ELet%E2%80%99s%20say%20we%20want%20our%20Patient%20to%20have%3A%3C%2FP%3E%0A%3CUL%3E%0A%3CLI%3Ea%20first%20name%3C%2FLI%3E%0A%3CLI%3Ea%20last%20name%3C%2FLI%3E%0A%3CLI%3Ean%20ID%3C%2FLI%3E%0A%3CLI%3Ea%20date%20of%20birth%3C%2FLI%3E%0A%3C%2FUL%3E%0A%3CP%3EOur%20SimplePatient%20model%20would%20look%20like%20this%3A%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CPRE%20class%3D%22lia-code-sample%20language-csharp%22%3E%3CCODE%3Epublic%20class%20SimplePatient%0A%7B%0A%20%20%20%20%20%20%20%20public%20string%20FirstName%20%7B%20get%3B%20set%3B%20%7D%0A%20%20%20%20%20%20%20%20public%20string%20LastName%20%7B%20get%3B%20set%3B%20%7D%0A%20%20%20%20%20%20%20%20public%20string%20PatientID%20%7B%20get%3B%20set%3B%20%7D%20%0A%20%20%20%20%20%20%20%20public%20DateTime%20Birthdate%20%7B%20get%3B%20set%3B%20%7D%20%0A%7D%0A%3C%2FCODE%3E%3C%2FPRE%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EThen%20it%E2%80%99s%20pretty%20easy%20to%20create%20an%20EditForm%20to%20model%20against%20this%20class%3A%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CPRE%20class%3D%22lia-code-sample%20language-markup%22%3E%3CCODE%3E%3CEDITFORM%20model%3D%22Patient%22%20onvalidsubmit%3D%22SavePatient%22%20class%3D%22form-horizontal%22%3E%0A%20%20%20%20%20%3CDATAANNOTATIONSVALIDATOR%3E%3C%2FDATAANNOTATIONSVALIDATOR%3E%0A%20%20%20%20%20%3CVALIDATIONSUMMARY%3E%3C%2FVALIDATIONSUMMARY%3E%0A%20%20%20%20%20%3CDIV%20class%3D%22form-group%22%3E%0A%20%20%20%20%20%20%20%20%20%3CLABEL%3EID%3C%2FLABEL%3E%0A%20%20%20%20%20%20%20%20%20%3CINPUTTEXT%20required%3D%22%22%3E%3C%2FINPUTTEXT%3E%0A%20%20%20%20%3C%2FDIV%3E%0A%20%20%20%20%3CDIV%20class%3D%22form-group%22%3E%0A%20%20%20%20%20%20%20%20%20%3CLABEL%3EBirthday%3C%2FLABEL%3E%0A%20%20%20%20%20%20%20%20%20%3CINPUTDATE%20required%3D%22%22%3E%3C%2FINPUTDATE%3E%0A%20%20%20%20%20%3C%2FDIV%3E%0A%20%20%20%20%20%3CDIV%20class%3D%22form-group%22%3E%0A%20%20%20%20%20%20%20%20%20%3CLABEL%3EFirst%3C%2FLABEL%3E%0A%20%20%20%20%20%20%20%20%20%3CINPUTTEXT%20required%3D%22%22%3E%3C%2FINPUTTEXT%3E%0A%20%20%20%20%3C%2FDIV%3E%0A%20%0A%0A%20%20%20%20%3CDIV%20class%3D%22form-group%22%3E%0A%20%20%20%20%20%20%20%20%20%3CLABEL%3ELast%3C%2FLABEL%3E%0A%20%20%20%20%20%20%20%20%20%3CINPUTTEXT%20required%3D%22%22%3E%3C%2FINPUTTEXT%3E%0A%20%20%20%20%20%3C%2FDIV%3E%0A%20%20%20%20%20%40if%20(Processing)%0A%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%3CBUTTON%20type%3D%22button%22%20class%3D%22btn%20btn-primary-outline%22%20disabled%3D%22%22%3EProcessing%3C%2FBUTTON%3E%0A%20%20%20%20%20%7D%0A%20%20%20%20%20else%7B%0A%20%20%20%20%20%20%20%20%20%3CBUTTON%20type%3D%22submit%22%20class%3D%22btn%20btn-primary%22%3ESave%3C%2FBUTTON%3E%0A%20%20%20%20%20%7D%0A%20%3C%2FEDITFORM%3E%0A%3C%2FCODE%3E%3C%2FPRE%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EThis%20then%20gives%20us%20a%20simple%20form%20and%20we%20can%20now%20create%20SimplePatients-%20but%20there%E2%80%99s%20a%20catch!%26nbsp%3B%20We%E2%80%99re%20not%20creating%20FHIR%20objects!%26nbsp%3B%20So%20we%20can%E2%80%99t%20store%20them%20in%20a%20FHIR%20capable%20system-%20and%20we%20can%E2%80%99t%20load%20Patients%20from%20a%20FHIR%20capable%20system%20into%20our%20app!%3C%2FP%3E%0A%3CH2%20id%3D%22toc-hId--2102609519%22%20id%3D%22toc-hId--2102609489%22%3EComplexity%20of%20FHIR%20Makes%20This%20Model%20Unscalable%3C%2FH2%3E%0A%3CP%3EAt%20this%20point%20we%20have%20several%20options-%20we%20can%20create%20toFHIR()%20and%20fromFHIR()%20methods%20to%20our%20SimplePatient.%26nbsp%3B%20But%20this%20is%20complex%20and%20as%20we%20import%20more%20properties%20from%20FHIR%20into%20our%20SimplePatient%20%26nbsp%3Bmodel-%20complexity%20will%20scale!%20Instead%20let%E2%80%99s%20use%20native%20HL7%20FHIR%20objects%3C%2FP%3E%0A%3CP%3EThe%20Complexities%20of%20HL7%20FHIR%20Objects%3C%2FP%3E%0A%3CP%3EWe%E2%80%99ll%20focus%20on%20Patient%2C%20but%20you%E2%80%99ll%20see%20examples%20of%20these%20problems%20on%20Practionier%2C%20Questionnaire%2C%20QuestionnaireResponse%2C%20and%20more!%20%26nbsp%3B%26nbsp%3BYou%20should%20be%20able%20to%20apply%20the%20principles%20below.%3C%2FP%3E%0A%3CH2%20id%3D%22toc-hId-384903314%22%20id%3D%22toc-hId-384903344%22%3EList%20Containing%20Complex%20Objects%20(Patient.Identifier)%3C%2FH2%3E%0A%3CP%3ELook%20at%20%3CA%20href%3D%22https%3A%2F%2Fwww.hl7.org%2Ffhir%2Fpatient-definitions.html%23Patient.identifier%22%20target%3D%22_blank%22%20rel%3D%22noopener%20nofollow%20noreferrer%22%3EPatient.Id%3C%2FA%3E.%20It%E2%80%99s%20a%20list%20of%20%3CA%20href%3D%22https%3A%2F%2Fwww.hl7.org%2Ffhir%2Fdatatypes.html%23Identifier%22%20target%3D%22_blank%22%20rel%3D%22noopener%20nofollow%20noreferrer%22%3EIdentifier%3C%2FA%3E%20Objects.%26nbsp%3B%20Each%20Identifier%20contains%20a%20string%20that%20represents%20the%20system%20for%20the%20Identifier%20(ex%3A%20%E2%80%9C%3CA%20href%3D%22http%3A%2F%2Fsomelink.spac%E2%80%9D%22%20target%3D%22_blank%22%20rel%3D%22noopener%20nofollow%20noreferrer%22%3Ehttp%3A%2F%2Fsomelink.spac%E2%80%9D%3C%2FA%3E)%20and%20a%20string%20representing%20the%20Value%20(ex%3A%20%E2%80%9C123-123-123-123%E2%80%9D).%26nbsp%3B%3C%2FP%3E%0A%3CP%3ERepresenting%20this%20in%20a%20form%20would%20look%20like%20this%3A%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CPRE%20class%3D%22lia-code-sample%20language-markup%22%3E%3CCODE%3E%3CEDITFORM%20model%3D%22%40Patient%22%3E%0A%40foreach%20(var%20id%20in%20FhirPatient.Identifier)%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%3CDIV%20class%3D%22form-group%22%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3CLABEL%3EPatient%20ID%20%3C%2FLABEL%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3CINPUTTEXT%20required%3D%22%22%3E%3C%2FINPUTTEXT%3E%0A%20%20%20%20%20%20%20%20%3C%2FDIV%3E%0A%20%20%20%20%7D%0A%3C%2FEDITFORM%3E%0A%3C%2FCODE%3E%3C%2FPRE%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CH2%20id%3D%22toc-hId--1422551149%22%20id%3D%22toc-hId--1422551119%22%3EList%20Containing%20Lists%20(Patient.Name.Family)%3C%2FH2%3E%0A%3CP%3ELook%20at%20%3CA%20href%3D%22https%3A%2F%2Fwww.hl7.org%2Ffhir%2Fpatient-definitions.html%23Patient.name%22%20target%3D%22_blank%22%20rel%3D%22noopener%20nofollow%20noreferrer%22%3EPatient.Name%3C%2FA%3E.%26nbsp%3B%20It%E2%80%99s%20a%20list%20of%20%3CA%20href%3D%22https%3A%2F%2Fwww.hl7.org%2Ffhir%2Fdatatypes.html%23HumanName%22%20target%3D%22_blank%22%20rel%3D%22noopener%20nofollow%20noreferrer%22%3EHumanName%3C%2FA%3E%20objects.%26nbsp%3B%20Each%20HumanName%20contains%20a%20single%20Family%20name%20(ex%3A%20%E2%80%9CBrown%E2%80%9D).%26nbsp%3B%20Unlike%20the%20previous%20Identifier%20objects%2C%20each%20HumanName%20also%20contains%20a%20List%20of%20Given%20names%20(ex%3A%20%E2%80%9CDave%E2%80%9D%2C%E2%80%9DJohn%E2%80%9D.%26nbsp%3B%3C%2FP%3E%0A%3CP%3EWe%20can%20use%20the%20same%20syntax%20as%20above%20for%20creating%20Family%20names%3A%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CPRE%20class%3D%22lia-code-sample%20language-markup%22%3E%3CCODE%3E%40foreach(var%20PatientName%20in%20FhirPatient.Name)%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%3CDIV%20class%3D%22form-group%22%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3CLABEL%3EFamily%20Name%3C%2FLABEL%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3CINPUTTEXT%20required%3D%22%22%3E%3C%2FINPUTTEXT%3E%0A%20%20%20%20%20%20%20%20%3C%2FDIV%3E%0A%20%20%20%20%7D%0A%3C%2FCODE%3E%3C%2FPRE%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CH2%20id%3D%22toc-hId-1064961684%22%20id%3D%22toc-hId-1064961714%22%3EList%20Containing%20Arrays%20(Patient.Name.Given)%3C%2FH2%3E%0A%3CP%3EBut%20for%20the%20Given%20name%20we%20can%E2%80%99t%20use%20a%20foreach%20because%20Given%20is%20an%20iEnumerable%3CSTRING%3E%20and%20we%20can%E2%80%99t%20bind%20the%20contents%20of%20an%20iEnumerable.%26nbsp%3B%20Luckily%20we%20CAN%20manipulate%20the%20more%20complex%20GivenElement.%26nbsp%3B%20Each%20complex%20class%20will%20contain%20Elements%20that%20are%20exclusive%20to%20C%23.%3C%2FSTRING%3E%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CPRE%20class%3D%22lia-code-sample%20language-markup%22%3E%3CCODE%3E%40foreach(var%20PatientName%20in%20FhirPatient.Name)%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%3CDIV%20class%3D%22form-group%22%3E%0A%20%20%20%20%20%20%20%20%20%20%40foreach%20%20(var%20gName%20in%20PatientName.GivenElement)%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%3CLABEL%3EGiven%20Name%3C%2FLABEL%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%3CINPUTTEXT%20required%3D%22%22%3E%3C%2FINPUTTEXT%3E%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%7D%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%3C%2FDIV%3E%0A%20%20%20%20%20%20%20%20%20%3CDIV%20class%3D%22form-group%22%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3CLABEL%3EFamily%20Name%3C%2FLABEL%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3CINPUTTEXT%20required%3D%22%22%3E%3C%2FINPUTTEXT%3E%0A%20%20%20%20%20%20%20%20%3C%2FDIV%3E%0A%20%20%20%20%7D%0A%3C%2FCODE%3E%3C%2FPRE%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CH2%20id%3D%22toc-hId--742492779%22%20id%3D%22toc-hId--742492749%22%3EComplete%20Example%3C%2FH2%3E%0A%3CP%3EYou%20can%20see%20a%20complete%20example%20of%20the%20above%20in%20our%20%3CA%20href%3D%22https%3A%2F%2Fgithub.com%2Fmicrosoft%2FFhirBlaze%2Fblob%2Fmain%2FFhirBlaze.PatientModule%2FPatientForm.razor.cs%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noreferrer%22%3EFhirBlaze%20project.%3C%2FA%3E%26nbsp%3B%20Happy%20FHIR%20coding!%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%3C%2FLINGO-BODY%3E%3CLINGO-TEASER%20id%3D%22lingo-teaser-2955865%22%20slang%3D%22en-US%22%3E%3CP%3EHL7%20FHIR%20Objects%20are%20complex%20and%20you%20might%20be%20tempted%20to%20use%20helper%20classes%20to%20create%20or%20edit%20them.%26nbsp%3B%20In%20this%20article%20we%20will%20walk%20you%20through%20directly%20binding%20these%20classes-%20saving%20you%20tons%20of%20time%20and%20code!%3C%2FP%3E%3C%2FLINGO-TEASER%3E%3CLINGO-LABS%20id%3D%22lingo-labs-2955865%22%20slang%3D%22en-US%22%3E%3CLINGO-LABEL%3EHLS_Hack%3C%2FLINGO-LABEL%3E%3C%2FLINGO-LABS%3E

Version history
Last update:

‎Nov 11 2021 10:23 AM

Updated by:
Labels

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK