VuePdbInput#
Download this notebook from GitHub (right-click to download).
Custom PDB Input Component using Vue.js#
Panel makes it easy to build data apps in Python using a wide range of built in components. Sometimes you want to go beyond those built in components and build custom components instead.
The lessons below will build on each other, culminating in a Panel+Vue.js custom component inspired by medicinal chemistry. It’ll look like this:
This guide is heavily inspired by Web Development with Python and Vue.js Components.
What is a Vue Component?#
Vue components are self-contained elements that can render HTML/CSS, store data within Javascript variables, and much more. Once defined, they are callable as HTML tags. For example, within existing HTML a Vue component can be rendered like below:
Here, the Vue component tags <v-component></v-component>
are responsible for rendering a part of the frontend that takes user input.
The components are usually defined in a .vue file and require Webpack to serve.
With Panel you can take a simpler approach, there is no need to configure, learn and maintain an advanced javascript build tool chain to utilize Vue.js. We will show you how this is done below using Panels ReactiveHTML.
Lets Get Started#
In order to ensure that all the resources we need (such as Vue.js) are loaded appropriately we need to declare baseclasses which declare these dependencies before we run the panel.extension
:
import panel as pn
import param
import requests
class BasicVueComponent(pn.reactive.ReactiveHTML):
_template = """
<div id="container" style="height:100%; width:100%; background:#0072B5; border-radius:4px; padding:6px; color:white">
<vue-component></vue-component>
</div>
"""
_scripts = {
"render": """
const template = "<div>Hello Panel + Vue.js World!</div>"
const vue_component = {template: template}
el=new Vue({
el: container,
components: {
'vue-component' : vue_component
}
})
"""
}
__javascript__=[
"https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"
]
class BootstrapVueComponent(BasicVueComponent):
__javascript__=[
"https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js",
"https://unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.min.js",
]
__css__=[
"https://unpkg.com/bootstrap/dist/css/bootstrap.min.css",
"https://unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.min.css",
]
Now that we have declared the components we run the extension:
pn.extension(sizing_mode="stretch_width")
Basic Vue Component#
Let’s start by rendering the BasicVueComponent
which simply renders a Hello World
template using Vue.js:
BasicVueComponent(height=40, width=190)
What are PDBs?#
This example will build a little example based on fetching and rendering so called PDBs. A PDB is a file format that stores 3-D structural information about a protein. This information is useful for example when designing drugs that inhibit disease-causing proteins. We will use the KLIFS open source database of PDBs.
You can find more information about PDBs here.
Getting PDBs#
We can get PDBs using KLIFS structured_pdb_list
rest endpoint.
URL = "https://klifs.net/api/structures_pdb_list"
def get_pdb_data_from_klifs(pdb_id):
if not pdb_id:
return "Please specify a PDB ID."
params = {'pdb-codes': pdb_id}
res = requests.get(url = URL, params = params)
data = res.json()
if res.status_code == 400:
return f"Error 400, Could not get PDB {pdb_id}", data[1]
return data[0]
Lets test the function:
get_pdb_data_from_klifs("4WSQ") # Examples: 2xyu, 4WSQ
PDBInput Component#
Now we will build a Vue.js component containing an input field and a button that will update the value
parameter of the PDBInput
component:
class PDBInput(BootstrapVueComponent):
value = param.String()
_template = """
<div id="container" style="height:100%; width:100%">
<vue-component></vue-component>
</div>
"""
_scripts = {
"render": """
const template = `
<div>
<b-form v-on:keydown.enter.prevent>
<b-form-input v-model="pdb_id" placeholder="Enter PDB ID" required></b-form-input>
<b-button variant="secondary" size="sm" v-on:click="setPDBId" style="margin-top:10px;width:100%">
Retrieve PDB metadata
</b-button>
</b-form>
</div>`
const vue_component = {
template: template,
delimiters: ['[[', ']]'],
data: function () {
return {
pdb_id: data.value,
}
},
methods: {
setPDBId() {
data.value = this.pdb_id
}
}
}
const el = new Vue({
el: container,
components: {
'vue-component': vue_component
}
})
"""
}
pdb_input = PDBInput(height=90, max_width=800)
pdb_input
Please note how we get and set the value
of the Parameterized python class using data.value
.
Display the PDB Response#
Next we will bind the get_pdb_data_from_klifs
function to the value
parameter of the pdb_input
component:
iget_klifs_data = pn.bind(get_pdb_data_from_klifs, pdb_id=pdb_input.param.value)
component = pn.Column(
pdb_input,
pn.panel(iget_klifs_data, theme="light")
)
component
Lets wrap it up in a nice app#
ACCENT = "#0072B5"
INFO = """# Featurize Protein Structure
Use the Vue component below to retrieve PDB metadata from [KLIFS](https://klifs.net/). For example for `2xyu` or `4WSQ`"""
pn.template.BootstrapTemplate(
site="Awesome Panel", title="Custom PDB Input Component using Vue.js", main=[INFO, component], header_background=ACCENT
).servable();
You can serve the app via panel serve VuePdbInput.ipynb
and find it at https://localhost:5006/VuePdbInput.
If you want to use Panel for Chemistry and Molecular Biology checkout panel-chemistry.
Download this notebook from GitHub (right-click to download).