Text only showing up in td element and not HTML - vue.js

I have a table td element that only shows this and I don't need it to appear like that but only as a blank space.
new Vue({
el: '#app2',
beforeCreate: function() {
},
created: function() {
},
mounted: function() {},
data: {
itemPriceList: [],
orderItems: [{
globalGroupName: "-- ABC"
},
{
globalGroupName: "-- CDE"
},
{
globalGroupName: "--- FGH"
},
{
globalGroupName: "- IJK"
},
{
globalGroupName: "-- LMN"
}
],
priceList: null
},
methods: {
GetOrderItems: function() {
},
ReplaceDashesInGlobalGroups: function(globalGroupName) {
if (globalGroupName[0] === "-") {
// Remove leading dashes and replace with a blank space
console.log("ReplaceDashesInGlobalGroups");
return globalGroupName.replace(/-(?![a-zA-Z])|-(?=\s|-)/g, ' ');
}
return globalGroupName;
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet" />
<div id="app2">
<table class="table table-striped table-bordered table-hover" style="width:350px;">
<thead class="thead-dark">
<tr>
<th width="235px"><label>Global Name</label></th>
</tr>
</thead>
<tbody>
<template v-for="global in orderItems">
<tr>
<td>{{ ReplaceDashesInGlobalGroups(global.globalGroupName) }}</td>
</tr>
</template>
</tbody>
</table>
</div>

Try this:
<td v-html="ReplaceDashesInGlobalGroups(global.globalGroupName)"></td>
This should be rendered as HTML now instead of just plain text. Note this can open you up to XSS attacks.
Source: Documentation
Updates the element’s innerHTML. Note that the contents are inserted
as plain HTML - they will not be compiled as Vue templates. If you
find yourself trying to compose templates using v-html, try to rethink
the solution by using components instead.
Dynamically rendering arbitrary HTML on your website can be very
dangerous because it can easily lead to XSS attacks. Only use v-html
on trusted content and never on user-provided content.
In single-file components, scoped styles will not apply to content
inside v-html, because that HTML is not processed by Vue’s template
compiler. If you want to target v-html content with scoped CSS, you
can instead use CSS modules or an additional, global <style> element
with a manual scoping strategy such as BEM.

Related

Ajax Reload on Vue.js DataTables

ajax.reload() and/or ajax.url().load() is just not working for Vue3 DataTable integration. It works if you include the CDN and follow the jQuery approach to it.
If you follow the instructions on the DataTables website on how to integrate DataTables into Vue3, that feature just doesn't seem to work.
https://datatables.net/blog/2022-06-22-vue
For example:
<template>
<div class="p-6">
<button #click="changeIt">
Change
</button>
<DataTable
class="display"
id="datatable"
:columns="columns"
:ajax="{
url: 'api/users',
}"
ref="table"
:options="{
select: true,
serverSide: true,
}"
>
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Email</th>
<th>Action</th>
</tr>
</thead>
<tbody>
</tbody>
</DataTable>
</div>
</template>
<script>
import DataTable from 'datatables.net-vue3'
import DataTablesLib from 'datatables.net';
DataTable.use(DataTablesLib);
export default {
name: 'DataTableComponent',
components: {DataTable},
data(){
return {
columns: [
{"data": "id"},
{"data": "name"},
{"data": "email"},
{"data": "action", "sortable": false},
],
}
},
methods: {
changeIt() {
$('#datatable').DataTable().ajax.url('users/user').load();
}
},
}
</script>
<style>
#import 'datatables.net-dt';
</style>
For a simple example, if you click the button, there would be a new Ajax request to somewhere else. This does not currently work.
The error that I get is:
runtime-core.esm-bundler.js:218 Uncaught TypeError: $(...).DataTable is not a function
at Proxy.changeIt (DataTableComponent.vue:55:29)
at _createElementVNode.onClick._cache.<computed>._cache.<computed> (DataTableComponent.vue:3:25)
at callWithErrorHandling (runtime-core.esm-bundler.js:155:22)
at callWithAsyncErrorHandling (runtime-core.esm-bundler.js:164:21)
at HTMLButtonElement.invoker (runtime-dom.esm-bundler.js:369:13)
I've tried every combination, and it doesn't seem to work. For example:
$('#datatable').DataTable().ajax.url('users/user').load();
$('#datatable').DataTable.ajax.url('users/user').load();
$('#datatable').ajax.url('users/user').load();
DataTable().ajax.url('users/user').load();
DataTable.ajax.url('users/user').load();
Any ideas?
EDIT
I did find that DataTables provides a dt() function, but it's still not working. It recommends the following:
DataTables API
Update and delete are very similar in that we just manipulate the array of data, but we will need to access the DataTables API to know which rows have been selected by the end user. The DataTable component provides a dt() method that we can use to get this via a Vue reference:
let dt;
const table = ref(); // This variable is used in the `ref` attribute for the component
onMounted(function () {
dt = table.value.dt();
});
So the modified code looks like this, but still doesn't work.
<template>
<div>
<h1>Simple table</h1>
<button #click="changeIt">Change It</button>
<DataTable
class="display"
id="datatable"
:columns="columns"
ajax="api/users"
ref="table"
:options="{
select: true,
serverSide: true,
}"
>
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Email</th>
<th>Action</th>
</tr>
</thead>
<tbody>
</tbody>
</DataTable>
</div>
</template>
<script>
import DataTable from 'datatables.net-vue3';
import DataTablesLib from 'datatables.net';
import 'datatables.net-select';
import {onMounted, ref} from "vue";
DataTable.use(DataTablesLib);
export default {
name: "DataTableComponent",
components: {DataTable},
data(){
return {
columns: [
{"data": "id"},
{"data": "name"},
{"data": "email"},
{"data": "action", "sortable": false},
]
}
},
setup() {
let dt;
const table = ref();
onMounted(() => {
dt = table.value.dt();
});
return {
dt,
}
}
}
</script>
<style>
#import 'datatables.net-dt';
</style>
Code Sandbox: https://codesandbox.io/s/serverless-pond-4mu4zw?file=/src/App.vue
EDIT #2:
And I got it to work like this, if I use the <script setup> tag. Still can't get it to work in the export default.
https://codesandbox.io/s/festive-forest-1ojspm?file=/src/App.vue:514-719
EDIT #3 (SOLUTION):
Solved with the help of #Aleksandr Savkin. I had to use this.$refs in mounted() and not ref() as the docs suggested.
<template>
<div>
<h1>Simple table</h1>
<button #click="changeIt">Change It</button>
<DataTable
class="display"
id="datatable"
:columns="columns"
ajax="api/users"
ref="table"
:options="{
select: true,
serverSide: true,
}"
>
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Email</th>
<th>Action</th>
</tr>
</thead>
<tbody>
</tbody>
</DataTable>
</div>
</template>
<script>
import DataTable from 'datatables.net-vue3';
import DataTablesLib from 'datatables.net';
import 'datatables.net-select';
DataTable.use(DataTablesLib);
export default {
name: "DataTableComponent",
components: {DataTable},
data(){
return {
columns: [
{"data": "id"},
{"data": "name"},
{"data": "email"},
{"data": "action", "sortable": false},
],
dt: null,
}
},
mounted() {
this.dt = this.$refs.table.dt();
},
methods: {
changeIt() {
this.dt.ajax.url('api/users/user').load();
}
}
}
</script>
<style>
#import 'datatables.net-dt';
</style>
Maybe it'll help you!
You tried to get a table element using Jquery, but it's not Vue's way to get a component.
I noticed you use the Vue's ref attribute for the DataTable component, so use that to get the component, like this-
methods: {
changeIt() {
const componentTable = this.$refs.table;
componentTable.ajax.url('users/user').load();
}
},
Also, see this- Template refs documentation
DataTables requires jQuery. Don't select either version if you already have it.
So, verify if you are-
Failing to contain the DataTables library.
Loading the DataTables library before the jQuery library.
Loading the jQuery library double.
Selecting the wrong route to the jQuery files.
For instance, in your HTML file at the head section, verify those-
<!-- Load CSS file for DataTables -->
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/datatables/1.10.21/css/jquery.dataTables.min.css"
integrity="sha512-1k7mWiTNoyx2XtmI96o+hdjP8nn0f3Z2N4oF/9ZZRgijyV4omsKOXEnqL1gKQNPy2MTSP9rIEWGcH/CInulptA=="
crossorigin="anonymous"
referrerpolicy="no-referrer"
/>
<!-- load jQuery -->
<script
src="https://code.jquery.com/jquery-3.6.0.min.js"
integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4="
crossorigin="anonymous"
></script>
<!-- load DataTables -->
<script
src="https://cdnjs.cloudflare.com/ajax/libs/datatables/1.10.21/js/jquery.dataTables.min.js"
integrity="sha512-BkpSL20WETFylMrcirBahHfSnY++H2O1W+UnEEO4yNIl+jI2+zowyoGJpbtk6bx97fBXf++WJHSSK2MV4ghPcg=="
crossorigin="anonymous"
referrerpolicy="no-referrer"
></script>
For more information, refer this documentation- https://bobbyhadz.com/blog/jquery-datatable-is-not-a-function

Uncaught (in promise) File 'Roboto-Regular.ttf' not found in virtual file system DataTable - vuejs

I am working with vuejs - DataTable and when I want to generate my report of the tables in pdf I get an error.
while if I generate an excel report it works correctly
my form
<table id="example1" class="table table-bordered table-striped responsive">
<thead>
<tr>
<th>Id_categoria</th>
<th>Categoria</th>
<th>Fecha(s)</th>
<!--<th>Botones(s)</th>-->
</tr>
</thead>
<tbody>
</tbody>
<tfoot>
<tr>
<th>Id_categoria</th>
<th>Categoria</th>
<th>Fecha(s)</th>
</tr>
</tfoot>
</table>
my script
<script>
import axios from "axios";
import $ from 'jquery';
import * as pdfMake from 'pdfmake/build/pdfmake';
import * as pdfFonts from 'pdfmake/build/vfs_fonts';
export default {
mounted() {
this.getUsers();
},
methods: {
getUsers() {
axios
.get("https://sistema-control-inventario.herokuapp.com/categoria/")
.then((response) => {
var table = $("#example1").DataTable({
"responsive": true, "lengthChange": true, "autoWidth": false,
"buttons": ["copy", "csv", "excel", "pdf", "print", "colvis"],
"language": "",
data: response.data,
columns: [
{ data: "id_categoria" },
{ data: "categoria" },
{ data: "fecha" },
// { defaultContent : '<button type="button" class="editar btn btn-primary"><i class = "fa fa-pencil-alt"></i></button> <button type="button" class="eliminar btn btn-danger" data-toggle="modal" data-target="#modalEliminar"><i class="fas fa-dumpster-fire"></i></button>'}
],
}).buttons().container().appendTo('#example1_wrapper .col-md-6:eq(0)')
//obtener_data_editar('',table);
}).catch((error) => console.log(error.response));
},
},
};
var obtener_data_editar = function(tbody,table){
$(tbody).on("click", "button.editar", function(){
var data = table.row($(this).parent('tr')).data();
console.log(data)
})
}
</script>
the page looks something like this
I would be grateful if you could help me to generate the pdf with this button and with the data that are in this one.
Thank you very much.
pd: i am using vue 3 cli
Maybe you can try changing the pdfmake imports to be like this:
import pdfMake from "pdfmake/build/pdfmake";
import pdfFonts from "pdfmake/build/vfs_fonts";
pdfMake.vfs = pdfFonts.pdfMake.vfs;
Note the third line which is (probably) the most important one.
This is straight from the library's documentation.
Aside from that, I strongly encourage you to reconsider using jQuery here. You'll do much better with Vue.js and vanilla JS alone, especially since Vue uses a virtual DOM so manipulating the actual DOM directly doesn't make any sense.

Vue 2 + TinyMCE Single Page Confusion

I write quite a few single page vue 2 files but have never tried using a "component" before. Can someone help spot the problem with my code? The error I'm getting is "Editor is not defined". Every example out there has you importing the vue module but I'm not using a builder so I thought just including the script(s) would work. I have removed a lot of extraneous code to make it simpler to read (I hope).
<script src="https://cdn.jsdelivr.net/npm/vue#2.X/dist/vue.js"></script>
...
<script src="https://cdn.tiny.cloud/1/no-api-key/tinymce/5/tinymce.min.js" referrerpolicy="origin"></script>
<script src="https://cdn.jsdelivr.net/npm/tinymce-vue/dist/tinymce-vue.min.js"></script>
<div id="vue_app">
...
<div v-show="showtable">
...
<table class="tbdesign">
<tr>
<th>ID</th>
<th>Name</th>
...
<th>Func</th>
</tr>
<tr v-for='row in filteredRows' :key="row.property_id">
<td :id="row.property_id">{{row.property_id}}</td>
<td>{{ row.name }}</td>
...
<td><div v-on:click="editRow(row.property_id)" href="#">Edit</div>
</td>
</tr>
</table>
</div>
</section>
<section v-if="showeditor">
<div >
...
<form>
<div>
<div>
<label for="name">Name:</label> <input class="detail_update id="name" type="text" v-model="editrow.name" />
</div>
...
<div class="form-group col">
Description:<br>
<editor
apiKey="no-api-key"
v-model="editrow.description"
:init="{
height: 500,
menubar: true,
plugins: [
'advlist autolink lists link image charmap',
'searchreplace visualblocks code fullscreen',
'print preview anchor insertdatetime media',
'paste code help wordcount table'
],
toolbar:
'undo redo | formatselect | bold italic | \
alignleft aligncenter alignright | \
bullist numlist outdent indent | help'
}"
>
</editor>
</div>
<div class="form-group col">
<button v-on:click="submitData" type="button">Save</button>
</div>
</div>
</form>
</div>
...
</div>
<script type="module">
var app = new Vue({
el: '#vue_app',
data() {
return {
rows: [],
row: [],
...
editrow: [],
...
errors: []
}
},
components: {
'editor': Editor
},
mounted() {
this.init();
},
computed: {
...
},
methods: {
init() {
this.loading = true;
axios.get('/dap/api/?/functions/get_properties/')
.then(response => {
this.rows = response.data;
console.log(response.data);
this.showtable = true;
})
.catch(function(error) {
this.errored = true;
alert(error);
})
.finally(() => this.loading = false)
},
...
checkData() {
...
},
submitData() {
...
},
editRow(rowID) {
for (var i = 0; i < this.rows.length; i++) {
if (this.rows[i]['property_id'] == rowID) {
this.editrow = this.rows[i];
this.showeditor = true;
this.showtable = false;
break;
}
}
}
}
});
</script>
Editor is not actually defined anywhere in your code, and <script type="module"> uses strict mode, requiring all referenced variables to be declared upfront. Since the Editor variable doesn't exist, the script immediately fails with the error you observed. However, it doesn't look like you actually need <script type="module"> here, so you could just use a regular <script>.
Every example out there has you importing the vue module but I'm not using a builder so I thought just including the script(s) would work.
The examples that import .vue files use a build system to automatically compile the imports with vue-loader. In this case you're using a pre-compiled script from CDN, so no loader is needed, but you do need to reference the correct symbol that the tinymce-vue script defines.
The tinymce-vue script sets its exports on window.TinymceVue. The pre-built Editor.vue component happens to be exported as the same name as the root export: window.TinymceVue.TinymceVue.
So you should locally register tinymce-vue's Editor component as:
<script>
new Vue({
components: {
editor: window.TinymceVue.TinymceVue,
}
})
</script>
demo

Load More Data On Scroll With Vue And Vuex

I would like to ask how can I display more data by using Vue and vuex. all data stored in vuex-store management already. From State management now I want to load more data on scrolling.
I found online solution by ajax. but I need to loading form state management (Vuex).
This is my Vue template:
<template>
<div>
<div class="panel panel-default">
<div class="panel-body">
<table class="table table-bordered table-striped">
<thead>
<tr>
<tr>
<th>Name - Number of Products: <span style="color: red"> {{products}} </span></th>
<th width="100"> </th>
</tr>
</tr>
</thead>
<tbody v-if="isLoaded">
<tr v-for="company, index in companies">
<td>{{ company.name }}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</template>
<script>
export default {
data: function () {
return { }
},
computed: {
companies(){
return this.$store.getters['exa1Company/getProducts'];
},
products(){
return this.$store.getters['exa1Company/countProducts'];
}
},
mounted() {
this.$store.dispatch('exa1Company/indexResource');
}
}
</script>
My vuex store file is partial for simplicity
export const getters = {
countProducts(state) {
return state.list.data.length;
},
getProducts(state) {
return state.list.data;
},
getTodoById: (state) => (id) => {
return state.list.data.find(tod => tod.id === id)
}
};
export default {
namespaced: true,
state: customerState,
getters,
actions,
mutations,
};
something like this should work. use companiesLoaded in the template, and increase page when scrolled to bottom. I hope this helps.
data: function () {
return {
page: 1,
perPage: 20
}
},
computed: {
companies(){
return this.$store.getters['exa1Company/getProducts'];
},
companiesLoaded(){
return this.companies.slice(0, this.page * this.perPage)
},
...

Vuejs and datatables: table empty when using v-for to fill data

I'm trying to fill a datatable using vuejs v-for directive and ajax to get the data but the table is always showing "No data available in table" even though there are some data shown and also in the bottom says "Showing 0 to 0 of 0 entries". I guess this is because vuejs is reactive and the table can't recognize the changes maybe?
I've been searching and trying for a while but with no solution found..
thanks a lot! :)
here's the template:
<table id="suppliersTable" class="table table-hover table-nomargin table-bordered dataTable">
<thead>
<tr>
<th>...</th>
...
</tr>
</thead>
<tbody>
<tr v-for="supplier in suppliers">
<td>{{ supplier.Supplier_ID }}</td>
<td>...</td>
...
</tr>
</tbody>
</table>
and the vue and ajax:
<script>
export default {
data() {
return {
suppliers: [],
}
},
methods: {
fetchSuppliers() {
this.$http.get('http://localhost/curemodules/public/suppliers/list')
.then(response => {
this.suppliers = JSON.parse(response.bodyText).data;
});
}
},
created() {
this.fetchSuppliers();
},
}
Once initialized, DataTables does not automatically reparse the DOM. Here's a relevant FAQ:
Q. I append a row to the table using DOM/jQuery, but it is removed on redraw.
A. The issue here is that DataTables doesn't know about your manipulation of the DOM structure - i.e. it doesn't know that you've added a new row, and when it does a redraw it will remove the unknown row. To add, edit or delete information from a DataTable you must use the DataTables API (specifically the row.add(), row().data() and row().remove() methods to add, edit and delete rows.
However, you can call table.destroy() to destroy the current instance before reinitializing it. The key is to delay the reinitialization until $nextTick() so that Vue can flush the DOM of the old DataTables. This is best done from a watcher on suppliers so that the DataTables reinitialization is done automatically when the variable is updated in fetchSuppliers().
mounted() {
this.dt = $(this.$refs.suppliersTable).DataTable();
this.fetchSuppliers();
},
watch: {
suppliers(val) {
this.dt.destroy();
this.$nextTick(() => {
this.dt = $(this.$refs.suppliersTable).DataTable()
});
}
},
demo
I know this is a bit late answer but I just encountered this problem just today and my only solution for this issue is using setTimeout function.After fetching data using axios I set a bit of delay then init the data-table. With this work around v-for works fine.
See below for my code.
GetDepartmentList(){
axios.get('department')
.then((response) => {
this.departmentList = response.data;
// this.dataTable.rows.add(response.data).draw();
setTimeout(() => $('#department-data-table').DataTable(), 1000);
})
.catch((error) => {
if (error.response.status == 401) {
alert('User session has expired. Please login again.');
location.replace("/login");
}
});
},
Also you can use .rows.add() function if you want to draw row data in the table without using v-for of vue. Refer to this doc.
You can using Axios in Vuejs, you try see the following above:
<template>
<div class="danhsach">
<h2>{{title}}</h2>
<table class="table">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Password</th>
<th>Age</th>
</tr>
</thead>
<tbody>
<tr v-for='data in datas'>
<td>{{data.id}}</td>
<td>{{data.name}}</td>
<td>{{data.password}}</td>
<td>{{data.age}}</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
export default{
data(){
return {
title:"Tile Lists",
datas:[]
}
},
created:function(){
this.danhsach_user();
},
methods:{
danhsach_user(){
this.axios.get('https://599f807effe73c0011b9fcc5.mockapi.io/api/user').then((response)=>{
this.datas=response.data;
});
}
}
}
</script>