How to display "No data available" in datatable after deleting rows - datatables

I have datatable with action onclick delete function that deleting the row.
How can i display "no data available" in case i delete all the row?
Here's my code.
{
"data": "Action",
render: (data, type, row) => {
return `<div class="actionIcon"><a id="viewExamination" onclick="individualDetails('${row["NAME"]}', '${row["BIRTHDAY"]}', '${row["Phone Number"]}')" data-toggle="modal" data-target="#asdffdsddd" data-backdrop="false" data-keyboard="false"><i class="fa-solid fa-outdent"></i></a><a id="delThisData" onclick="deleteDetailsNewHired()"><i class="fas fa-trash-alt"></i> </a> </div>`;
}
}
function deleteDetailsNewHired() {
$("#delThisData").closest('tr').remove();
}

There is a difference between the data stored inside the DataTables object and the data you can see displayed in the web page. If you only delete a <tr> from the HTML, you have not deleted that row from the underlying DataTable.
See the DataTables API function row().remove().
Note the use of the draw() function as well, to re-draw the table data so you actually see the resuts of the remove() operation reflected in the HTML.
After that, you can take a look at the language.emptyTable option (which you set once as part of the table definition) if you want to use a custom message. By default, the message you see is:
No data available in table
But it can be anything you want.
This is a similar overall issue as noted here. It is important to understand the difference between the data stored in your DataTable and the data which happens to be rendered on the currently visible web page.

Related

VueJS: Computed Property inside a loop

My scenario is that of the picture:
I have some transaction headers and transaction details. The screenshot is a pop-up dialog for editing a transaction...
One transaction could be a member ship fee. If a member pays a fee (see 1) then I want to be able to enter the month related to the fee.
Each "Buchungsvorgang" (transaction detail) is being looped through with v-for:
<v-row
v-for="(item, index) in editedItem.transactionDetail"
:key="index"
dense
align="center"
class="mb-2"
>
I also want to show the months for which a member has already paid previously.
I have set it by:
When the name (see figure 1) is changed call a method:
async showMonths (idPerson) {
try {
const response = await this.$axios.$get(`/api/api.php/records/transactions?filter=idPerson,eq,${idPerson}&size=5`)
this.lastMonths = response.records
.map((item) => {
return `${this.$moment(item.month, 'YYYY-MM').format('MMM YY')} - (${new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).format(item.Amount)})`
})
.join(' // ')
} catch (e) {
this.lastMonths = e.message
}
}
This works perfectly. It's an async function as it always picks up the latest info directly from the database.
So each time, if a change the member (see number 1), the output changes.
My problem: It only changes when someone triggers the change event of the form. If I open the dialog, number two would be empty because no one triggered the event in the first place.
This is the way it looks when I open the dialog.
Question:
Can I use a async computed property here and as a parameter, pass the editedItem.transactionId to the prop in order to retrieve the data?
Or can I put the method inside the data () - function? I want the output to be visible all the time, not just if someone clicks on a field.
I have created to small codepen to illustrate the problem:
https://codepen.io/rasenkantenstein/pen/qBdZepM
The first form (person.name) is meaningless. However, the city is the variable equal to figure 1. The result should be printed as the :message property of figure 2 (city).
How - when loading the codepen - can I populate both details?
I've updated your codepen that does what I think you want, see example.
Essentially, you just set your messages on either created or mounted hooks:
created: function () {
this.people.forEach((item, i) => {
Vue.set(this.message, i, item.country)
})
}
The key thing to note above is the use of Vue.set, since Vue cannot detect changes to an array when you directly set an item with the index, see the documentation around this. So I recommend you use Vue.set inside your changeCity function as well.

getting filtered rows array from vue-tables-2

I need some help with a popular vue libraries https://www.npmjs.com/package/vue-tables-2.
I have a filter fixed for the rows but now I need the filtered rows(the objects of rows) stored in an array does anyone know how to achieve this?
I hope this is integrated in the libraries itself because I don't like to fix a hacky solution.
I tried to look it up in the documentation but I couldn't find anything.
Short answer:
You can use the allFilteredData property of the component.
Longer answer using working examples:
You can use a ref on an instance of the table component and then access the allFilteredData property.
Here are two examples:
The code below in available in a full fiddle. Typing "zi" into the filter for example and clcking the "Process Filtered Result" button under the table. Clicking the button results in a method accessing the allFilteredData property.
https://jsfiddle.net/tzdw17qo/
Given this partial code from that fiddle example:
<v-client-table ref="countries" :columns="columns" v-model="data" :options="options">...</v-client-table>
<button #click="handleFilteredResult">Process Filtered Result</button>
<textarea ref="json_dump"></textarea>
A method such as this will have the reference to the filtered data to do something more useful with. This is just a basic working example:
methods: {
/**
* Log out allFilteredData for now for demo only
* #TODO Something specific with the data
*/
handleFilteredResult () {
// log the value of the allFilteredData attribute
console.log({allFilteredData: this.$refs.countries.allFilteredData});
// for example write the json version out to a textarea:
this.$refs.json_dump.value = JSON.stringify(this.$refs.countries.allFilteredData);
}
},
Then another example where listening to the "filter" event:
https://jsfiddle.net/ev645umy/
Html from the fiddle:
<!-- bind to the `filter` event of the component -->
<v-client-table ref="countries" #filter="onFilter" :columns="columns" v-model="gridData" :options="options">
JavaScript from the fiddle:
methods: {
/**
* Log out allFilteredData for now for demo only
* #TODO Something specific with the data
*/
onFilter () {
// as of this writing, the `filter` event fires before the data is filtered so we wait to access the filtered data
setTimeout(() => {
console.log({allFilteredData: this.$refs.countries.allFilteredData});
this.$refs.json_dump.value = JSON.stringify(this.$refs.countries.allFilteredData);
}, 250);
}
},
More info:
https://matanya.gitbook.io/vue-tables-2/properties
https://matanya.gitbook.io/vue-tables-2/events

Looping through and sending to modal

I'm trying to understand why when I click on the button below I get three different objects before it says that invoice is undefined.
<tr :key="invoice" v-for="(invoice, index) in invoices">
<td><button #click.prevent="openEdit(index)" Edit Invoice</button></td>
</tr>
openEdit(index) {
var invoice = this.invoices.splice(index, 1)[0];
this._beforeEditingCache = Object.assign({}, invoice);
console.log(invoice);
Bus.$emit('editting', { invoice: invoice, phase: this.phase, editModalName: this.editModalName });
},
After a long time i think i understood that question
You want to open a modal with the values of table row that gets clicked.
*I made a jsfiddle for this.Take a look here :https://jsfiddle.net/Roland1993/eywraw8t/5415/
That fiddle is very simple.I suggest you to use the modal as child component.
But if you using vue it would be vuetiful to use vuetify.Take a look to this table which includes edit,delete and add new item. click here to see

Angular2 table is not refreshing data

I have an Angular2 application which is getting Json data and displaying it as a table. When I try to refresh / Update it with new data, table is showing old data only.
getting data through service like below:
#Input()
participants:Participant[];
testClasses: TestClass[] = [];
ngOnChanges() {
let codes="";
for (let item of this.participants)
{
codes = codes.concat(item.Id).concat(",");
}
this.buildTable(codes);
}
buildTable(codes){
let url = this.serverUrl + "api/test?codes=" + codes;
// passing input participants as parameter in url
this.testService.getData(url)
.subscribe(data => this.onDataUpdate(data));
}
onDataUpdate(data: any) {
this.testClasses = data;
// here I am getting new/refreshed data.
}
displying in table like below:
<table id="testGrid">
<tr *ngFor="let testClass of testClasses">
<td>{{testClass.name}}</td>
<td *ngFor="let t of (testClass.Score)">
{{ t }}
</td>
</tr>
</table>
When page loads data first time, table is showing data, but when I try to refresh data, I can see new refreshed data in onDataUpdate funcion, but html table is not refreshing view with new data.
Any idea or help would be much appreciated.
I tried below link:
https://github.com/swimlane/ngx-datatable/issues/255
Angular 2 - View not updating after model changes
I made my own example and I was able to reproduce the behaviour.
So what going on here it's that you use an array as input. (participants:Participant).
And after what you said about your checkboxes its seems that you mutate your array. It has for effect that the reference of the array is still the same therefor angular don't detect a change. (by the way I don't know if it's an expected behaviour).
A solution to your problem could be to create a new array of participants at each change on checkboxes.
Something like that:
this.participants = this.participants.slice(0)
You could also look at this answer: Angular2 change detection: ngOnChanges not firing for nested object

.dataTable() pagination breaks class .click responsiveness

When I construct a normal table and give each column a distinct class, the classes are responsive for all rows. However, when I call .dataTable() on my table, only page 1 of the paginated results is responsive. Page 2 and beyond are not responsive.
Example code:
var dataTableID = 'questionsTable';
var columns = {
questionID: "ID",
CategoryString: "Cat",
difficultyLevel: "Diff",
timesAsked: "Qty",
questionText: "Question Text"
};
// my own little function that builds the HTML table. <TD> classes are column names
//-- eg .questionID, .CategoryString, etc
var tableHTML = makeTable(questions, columns);
$('#' + dataTableID).html(tableHTML);
// dataTable works nicely except only page 1 .click is responsive!
$('#' + dataTableID).dataTable();
// works fine if I remove .dataTable() above. ONLY works for first page of results
// if I keep .dataTable()
$('.questionID').on("click", function() {
alert('Click called');
});
When using pagination, dataTables change the visible rows by moving <tr>'s back and forth the DOM. $('.questionID').on is processed for columns on the first page only, since those columns is the only visible (accessible) columns after initialization.
So you must assign the click handler (or whatever you want to attach) on page change rather than on initialization. Here by the use of the fnDrawCallback event :
function clickHandler() {
alert('Click called');
}
var dataTable = $('#example').dataTable({
fnDrawCallback : function() {
$('.questionID')
.off("click", clickHandler)
.on("click", clickHandler)
}
});
see demo -> http://jsfiddle.net/U9Jmg/
Notice the use of .off. dataTables actually moves the <tr>'s back and forth the DOM and a table in memory, including any attached events. If previous attached events is not released, we will end up in multiple alerts for each column.
Also note I have only used only one class .questionID for all the columns in the demo. The example is 1.10.x but this works in 1.9.x as well.
As you can see of the comments below, you could also use a delegated event instead of direct event binding. It changes the setup and perhaps it is not suitable for your needs, but anyway :
$('#example tbody').on('click', '.questionID', clickHandler);
see demo -> http://jsfiddle.net/L29Dq/
When using DataTables pagination feature (as you do), only the first page of your data is present in the dom when you attach the click event handler. That's why the handler is attached to the elements on the first page and only to those elements.
When going to another page, DataTables will redraw the table which in effect removes the attached event handler. You have to reattach the event handler after every table draw. The drawCallback option should be the right place for that:
$('#' + dataTableID).dataTable({
"drawCallback": function(settings){
$('.questionID').on("click", function(){
alert('Click called');
});
}
});
As #davidkonrad pointed out in his answer, the click handler should be removed (using off) to avoid handling the event multiple times.
The DataTables page has a section on this as well: Advanced Initialisation - DOM/jQuery events. The example there uses delegated events.