Still very new to svelte (but learning more each day!) and need a bit of help.
I am working on a veterinary drug dose calculator that calculates the individual dose of each drug based on the concentration of each drug, the mg/kg dosage of that drug and the weight in kilograms of the patient. I have a weight converter for lbs <-> kgs and my calculations will work if I have just one concentration. The issue is that many drugs have multiple concentrations so I need a select input to allow the user to change the concentration for each drug.
Here is a REPL
Here is my Code:
<div class="row no-gap">
<div class="col-50 tablet-25">
<div class="item-content item-input item-input-outline item-input-with-value">
<div class="item-inner">
<div class="item-title item-label">Pounds</div>
<div class="item-input-wrap">
<input value={l} on:input="{e => setBothFromL(e.target.value)}" min="0" type=number placeholder=" lbs">
</div>
</div>
</div>
</div>
<div class="col-50 tablet-25">
<div class="item-content item-input item-input-outline item-input-with-value">
<div class="item-inner">
<div class="item-title item-label">Kilogram</div>
<div class="item-input-wrap">
<input value={k} on:input="{e => setBothFromK(e.target.value)}" min="0" type=number placeholder="kgs">
</div>
</div>
</div>
</div>
</div>
<h1>Antibiotics</h1>
{#each antibiotics as antibiotic, i}
<div class="Rtable-row eachdrug eachdrugE" data-id="{i + 1}">
<div class="Rtable-cell drug-cell">
<span class="drugTitle searchme">{antibiotic.name}
{#if antibiotic.concSelect.length === 1}
{antibiotic.concentration} {antibiotic.perml}
{:else if antibiotic.concSelect.length > 1}
<select bind:value={selected} on:change="{() => concs = selected}">
{#each antibiotic.concSelect as concSelect}
<option value={concSelect.conc}>
{concSelect.name}
</option>
{/each}
</select>
{/if}
</span>
</div>
</div>
<div>
<div>
Dose: <input bind:value={antibiotic.dosevalue} step={antibiotic.dosestep} min="{antibiotic.dosemin}" max="{antibiotic.dosemax}" type=number>
{#if antibiotic.dosevalue > antibiotic.dosemax * 1.1 }
<span class="error-message1 hidden-print" transition:fly="{{ y: 10, duration: 500 }}"><i class="fas fa-exclamation-triangle fa-sm fa-fw hidden-print" data-fa-transform="up-2"></i> Above Range</span>
{/if}
</div>
<div> <span class="vol">{(k * antibiotic.dosevalue).toFixed(antibiotic.decimal)} {antibiotic.appendose}</span>
<span class="vol">{#if antibiotic.concSelect.length === 1}
{((k * antibiotic.dosevalue) / antibiotic.concentration).toFixed(antibiotic.decimal)} {antibiotic.appendvol}
{:else if antibiotic.concSelect.length > 1}
{((k * antibiotic.dosevalue) / concs).toFixed(antibiotic.decimal)} {antibiotic.appendvol}
{/if} </span></div>
</div>
{/each}
<style>
input{min-width:120px}
.vol {
background: rgba(0, 0, 0, .12); padding:5px;}
.error-message1 {
font-size: 10px !important;
line-height: 11px !important;
font-weight: normal;
color: red;
opacity: 0.5;
font-weight: 700;
}
.eachdrug {border-top: 1px solid #ccc; margin-top:15px}
</style>
<script>
import { fade, fly } from 'svelte/transition';
let k = '';
let l = '' ;
let selected;
let concs ="";
function setBothFromK(value) {
k = +value;
l = +( k * 2.2046226218).toFixed(1);
}
function setBothFromL(value) {
l = +value;
k = +( l / 2.2046226218).toFixed(1);
}
let antibiotics = [
{
"group":"",
"route":"IV,IM,SQ BID",
"perml":"mg/ml",
"concentration":"50",
"concSelect": [
{ "conc": 50, "name": "50 mg/ml","perml": "ml" }
],
"perkg":"mg/kg",
"doseper":"10",
"dosemin":"10",
"dosemax":"30",
"dosestep":"1",
"dosevalue":"10",
"hide":"",
"name":"Amikacin",
"calc":"Amikacin",
"calcID":"Amikacin2",
"decimal": "2",
"appendose": " mg",
"appendvol": " ml",
"multiply": "",
"class": "drug",
"color": "green"
},
{
"group":"",
"route":"BID",
"perml":"mg/ml",
"concentration":"50",
"concSelect": [
{"id": 1 , "conc": 50, "name": "50 mg/ml","perml": "ml" },
{"id": 2 , "conc": 100, "name": "100 mg/ml","perml": "" },
{"id": 3 , "conc": 150, "name": "150 mg/ml","perml": "" },
{"id": 4 , "conc": 200, "name": "200 mg/ml","perml": "" },
{"id": 5 , "conc": 400, "name": "400 mg/ml","perml": "" }
],
"perkg":"mg/kg",
"doseper":"11",
"dosemin":"11",
"dosemax":"22",
"dosestep":"1",
"dosevalue":"11",
"hide":"",
"name":"Amoxicillin",
"decimal": "2",
"appendose": " mg",
"appendvol": " ml",
"class": "drug"
},
{
"group":"",
"route":"BID",
"perml":"mg/ml",
"concentration":"62.5",
"concSelect": [
{"id": 1 , "conc": 62.5, "name": "62.5","perml": "ml" },
{"id": 2, "conc": 125, "name": "125","perml": "" },
{"id":3 , "conc": 250, "name": "250","perml": "" },
{"id": 4, "conc": 375, "name": "375","perml": "" }
],
"perkg":"mg/kg",
"doseper":"13.75",
"dosemin":"13.75",
"dosemax":"25",
"dosestep":"1",
"dosevalue":"13.75",
"hide":"",
"name":"Amoxicillin-Clavulanate",
"calc":"Amoxicillin-Clavulanate",
"calcID":"Amoxicillin-Clavulanate2",
"decimal": "2",
"appendose": " mg",
"appendvol": " ml",
"class": "drug",
},
{
"group":"",
"route":"BID",
"perml":"mg/ml",
"concentration":"100",
"concSelect": [
{"id": 1 , "conc": 100, "name": "100","perml": "ml" },
{"id": 2 , "conc": 125, "name": "125","perml": "" },
{"id": 3 , "conc": 250, "name": "250","perml": "" },
{ "id": 4 ,"conc": 500, "name": "500","perml": "" }
],
"perkg":"mg/kg",
"doseper":"6.6",
"dosemin":"6.6",
"dosemax":"22",
"dosestep":"1",
"dosevalue":"6.6",
"hide":"",
"name":"Ampicillin",
"calc":"Ampicillin",
"calcID":"Ampicillin2",
"decimal": "2",
"appendose": " mg",
"appendvol": " ml",
"class": "drug"
}
];1
</script>
The problems are :
On page load, the select option value is not initially utilized in the drug dose equation ( I get NaN or Infinity). After selecting, it is.
Changing the select option changes all of the drug concentrations, not just the individual drug concentration.
Any help would be appreciated.
You have one of the following for each antibiotic:
<select bind:value={selected} on:change="{() => concs = selected}">
...
</select>
Your on:change
handler is not necessary here, since it's a simple assignment. So you could just bind:value={concs}
which would be exactly the same. You're using two variables where you could use a single one. This is also the reason why you're seeing NaN
values, because your concs
variable is not set until you change the selected option. By binding directly to the tracking variable, you're solving that first issue.
However, you're also using a single variable (or variable pair, as seen above) to track changes in several distinct select fields, and that's where your real problem lies. For each of these select fields, you want a different variable to track its selected value.
You can easily do this by adding a concs
key to each antibiotic
and setting it to what you want your default value to be, then updating your select fields to use that new variable, using the simplified binding, and finally updating the line where you rely on that value for your concentration computation:
<select bind:value={antibiotic.concs}>
...
</select>
...
{#if antibiotic.concSelect.length === 1}
...
{:else if antibiotic.concSelect.length > 1}
{((k * antibiotic.dosevalue) / antibiotic.concs).toFixed(antibiotic.decimal)}{antibiotic.appendvol}
{/if}
...
<script>
...
let antibiotics = [
{
...
"concs": 50,
},
{
...
"concs": 100,
},
{
...
"concs": 62.5,
},
{
...
"concs": 100,
},
]
...
</script>