I'm trying to create a table and for each row add a button, which will then call a custom function. However, whatever I have tried has not worked and the only function I am able to call is alert()
. I am doing this in Vuejs and using java script functions. Here is my code:
<template>
<div >
<component :is="checkJWT()"/>
<h3>{{organization_name}}</h3>
<div>
<table id="workflowTable" style="width:100%"> <!-- the id can also be named organizationCaseTable -->
<tr>
<th>ID</th>
<th>Title</th>
</tr>
</table>
</div>
</div>
</template>
<script>
import jwt_decode from "jwt-decode";
export default{
data () {
return {
organization_name: ""
}
},
methods: {
checkJWT: function(){
var access_token = document.cookie.split("=")[1];
var decoded = jwt_decode(access_token)
this.organization_name = decoded.azp
this.getCaseInformation(this.organization_name)
},
getCaseInformation: async function(){
fetch('http://localhost:3000/workflow-page/' this.organization_name, {
method: "GET",
headers: {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "DELETE, POST, GET, OPTIONS",
"Access-Control-Allow-Headers": "Content-Type, Authorization, X-Requested-With",
"Content-Type": "text/plain",
"Authorization": "Bearer " document.cookie["access_token"]
}
})
.then(response => response.json())
.then(result => result.forEach(rec => {
var rowCol = "<tr><td style='border: 1px solid;text-align:center'>" rec.id
"</td><td style='border: 1px solid;text-align:center'>" rec.title "</td>"
"<td><button id='viewWorkflow" String(rec.id) "' v-on:click='myFunction()'>View</button></td></tr>"
document.getElementById('workflowTable').innerHTML = rowCol
}))
},
myFunction(){
console.log("HERE")
}
}
}
</script>
The attribute is being set when I inspect the button element, but when I click it, nothing happens. I also realized that .innerHTML
adds it as plain text so I tried the following:
After the line document.getElementById('workflowTable').innerHTML = rowCol
I called a function called this.makeClickable(rec.id)
and that function looks like this:
makeClickable(id){
document.getElementById('viewWorkflow' String(id)).setAttribute('onclick', 'myFunction');
},
Even with this I am not able to call a custom function and I don't know why or how to fix/get around it.
CodePudding user response:
Avoid mutating the DOM directly. It's something that is rarely, if ever a good idea. This goes for all frontend frameworks; they all work on the same principle of the DOM being a function of data. I assume you are looking to do some thing like this...
<script>
export default{
data () {
return {
organization_name: "",
apiResponseData: null
}
},
methods: {
getCaseInformation(){
fetch(myUrl)
.then(d => d.json())
.then(data => this.apiResponseData = data)
},
myFunction(record){
console.log("selected", record)
}
}
}
</script>
<template>
<div >
<h3>{{organization_name}}</h3>
<div>
<span v-if="!apiResponseData">LOADING</span>
<table v-if="apiResponseData" id="workflowTable" style="width: 100%">
<thead>
<tr>
<th>ID</th>
<th>Title</th>
</tr>
</thead>
<tbody>
<tr v-for="rec in apiResponseData" :key="rec.id">
<td style="border: 1px solid; text-align: center">{{rec.id}}</td>
<td style="border: 1px solid; text-align: center">{{rec.title}}</td>
<td>
<button @click="myFunction(rec)">View</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</template>
I removed a bunch of stuff there to keep it simple, but here are some things to note.
apiResponseData
will be null until the data loads, so you need to usev-if="apiResponseData"
to only render the table or the table rows when that value is set. You can use this also to show a loading indicatorv-for
directive is used to loop over the data, it should also use a key. (not mandatory, but important in many cases) docs- the
:key
is defined with a colon before it, this marks the content for parsing, otherwise it is treated as a string value - you can pass the record to your function in the button
myFunction(rec)
.
Also, you don't need to define the function as async
since you are treating it as a promise (using then
)