Angular 8 Pagination with Data from Database -- - datatable

I am having a little trouble with this one.
Using the approach discussed in this -- https://jasonwatmore.com/post/2019/06/18/angular-8-simple-pagination-example
Use-case difference is, my data all comes from database. So I have had to use a model class and all. But, due to some problem, I am getting the same data [1st row from db] in all the rows. Let me post the code I used --
ANGULAR
method inside my component to get data from service class
newsTopics: NewsTopic[];
pageOfItems: Array<NewsTopic>;
getAllNewsTopics() {
this.userService.getAllTopics()
.subscribe((data: NewsTopic[]) => {
this.newsTopics = (data as NewsTopic[]).map((x, i) => ({ Id: (i + 1), TopicId: data[0].TopicId, TopicName: data[0].TopicName, TopicInfo: data[0].TopicInfo, IssueStartDate: data[0].IssueStartDate, IssueCloseDate: data[0].IssueCloseDate, NewsCategory_Id: 0 }));
})
}
my model class
export class NewsTopic
{
Id: number;
TopicId: string;
TopicName: string;
TopicInfo: string;
IssueStartDate: Date;
IssueCloseDate: Date;
NewsCategory_Id: number;
}
the method in service class itself
getAllTopics(){
var reqHeader = new HttpHeaders({ 'No-Auth': 'True' });
return this.http.get<NewsTopic[]>(this.rootUrl + '/api/NewsTopic/GetAllNewsTopics', { headers: reqHeader });
}
my html for showing the data and the pagination control
<div class="card-body">
<table class="table table-striped" id="newstopics_tbl">
<thead>
<tr style="background:linear-gradient(50deg, #d9fcfc, #dafbde)">
<th>Topic ID</th>
<th>Topic Name</th>
<th>Topic Info</th>
<th>Start Date</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let nt of pageOfItems">
<td><b>{{nt.TopicId}}</b></td>
<td>{{nt.TopicName}}</td>
<td>{{nt.TopicInfo}}</td>
<td>{{nt.IssueStartDate}}</td>
</tr>
</tbody>
</table>
</div>
<div class="card-footer pb-0 pt-3" style="background:linear-gradient(50deg, #d9fcfc, #dafbde); margin-top:15px">
<jw-pagination [items]="newsTopics" (changePage)="onChangePage($event)"></jw-pagination>
</div>
My guess is, the problem lies in the getAllNewsTopics() method, where I am trying to fill and map the array of objects and assign to the variable. Something wrong there. If you see the original example from the link, they used a .fill(0) also. In my case I tried doing .fill(data[0]) however result is the same, ie. only first record, repeated multiple times.
What is the trick I am missing? Can someone just point me out.
Much needed, Thanks,
EDITS --
These are the changes->
getAllNewsTopics() {
var reqHeader = new HttpHeaders({ 'No-Auth': 'True' });
return this.http.get<NewsTopic[]>(this.rootUrl + '/api/NewsTopic/GetAllNewsTopics', { headers: reqHeader })
.subscribe((data: NewsTopic[]) => {
this.newsTopics = data;
});
}
and
<div class="card-body">
<table class="table table-striped" id="newstopics_tbl">
<thead>
<tr style="background:linear-gradient(50deg, #d9fcfc, #dafbde)">
<th>Topic ID</th>
<th>Topic Name</th>
<th>Topic Info</th>
<th>Start Date</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let nt of pageOfItems" style="cursor:pointer" (click)="NewsArticleAdd(nt)">
<td (click)=""><b>{{nt.TopicId}}</b></td>
<td style="color:mediumvioletred;" (click)="">{{nt.TopicName}}</td>
<td (click)="">{{nt.TopicInfo}}</td>
<td (click)="">{{nt.IssueStartDate}}</td>
</tr>
</tbody>
</table>
</div>
<div class="card-footer pb-0 pt-3" style="background:linear-gradient(50deg, #d9fcfc, #dafbde); margin-top:15px">
<jw-pagination [items]="newsTopics" (changePage)="onChangePage($event)"></jw-pagination>
</div>
That does the trick. Works as expected,

Related

calculate shopping cart sale total in laravel and vuejs

i'm developing a shopping cart with laravel and vuejs i'm new to programming. I want to get the total amount of the products in the shopping cart but I don't understand how to do it.
any help is appreciated
I am using vuejs components, in my data element I have a cart that is the one who has the cart with the products.
<script >
import Axios from 'axios'
export default {
data(){
return{
csrf: document.head.querySelector('meta[name="csrf-token"]').content,
carrito: [],
}
},
mounted(){
Axios.get('carrito')
.then(Response => {this.carrito = Response.data})
},
}
</script>
Inside my template I have a table where it traverses the products with the v-for directive, I would like to have the total in a but I don't understand how I can do this operation
<table class="table">
<thead>
<tr>
<th scope="col">Producto</th>
<th scope="col">Cantidad</th>
<th scope="col">precio</th>
<th scope="col">total</th>
<th scope="col">accion</th>
</tr>
</thead>
<tbody >
<tr v-for="(ProductCart, index) in carrito" :key="index.id">
<td>{{ProductCart.name}}</td>
<td>{{ProductCart.cantidad}}</td>
<td>{{ProductCart.precio}}</td>
<td>{{ProductCart.cantidad * ProductCart.precio}}</td>
<td>
<form action="" method="post">
<input :value="csrf" type="hidden" name="_token" >
<input type="hidden" name="id" id="id" value="<?php echo $producto['id'] ?>" >
<button name="btnAccion" value="Eliminar" class="btn btn-danger" type="submit"> Remove</button>
</form>
</td>
</tr>
</tbody>
<tfoot>
<tr>
<th colspan="2"></th>
<td>
<h2>Total</h2>
</td>
<td align="right">
<h3> </h3>
</td>
</tr>
</tfoot>
</table>
so I receive the data
{1: {id: "1", name: "Motor 1", cantidad: "1", precio: "20.00"}}
1: {id: "1", name: "Motor 1", cantidad: "1", precio: "20.00"}
cantidad: "1"
id: "1"
name: "Motor 1"
precio: "20.00"
It seems like computed properties would work best in your case. I'm not sure how the data in carrito is structured, but assuming it looks something like this:
carrito: {
1: {
"id":"1",
"name":"Motor 1",
"cantidad":"1",
"precio":"20.00"
}
...
}
...you would have to loop through carrito, take the precio times the cantidad of each object, and add it to a running total. Here's an example:
total: function () {
let total = 0;
Object.values(this.carrito).forEach(
(item) => (total += item.precio * item.cantidad)
);
return total;
}
Object.values returns an array of just the values of carrito, which is then iterated through by .forEach, and its precios/cantidads are multiplied together, and then then added to the running total, and returned.
total would go in computed: {}, within your Vue instance. Computed properties are re-evaluated when dependant data changes, so total will be reevaluated whenever carrito changes. You can then place it wherever you want in the page, like a normal data property:
...
<tfoot>
<tr>
<th colspan="2"></th>
<td>
<h2>Total</h2>
</td>
<td align="right">
<h3>{{ total }}</h3>
</td>
</tr>
</tfoot>
...
Check out the demo here, (network fetching is simulated, so it takes two seconds to load carrito) and its code here.
More info on computed properties:
Computed Properties and Watchers: Vue Docs
Computed Properties: Vue Mastery
You could create a computed property or a method for your component. There you could loop all the items and add each price to a total variable. Then you return the total.
Have a look here: Vue computed properties

ColdFusion dataTable returning f is undefined

I'm adding dataTable to my coldFusion project, but it is returning: Uncaught TypeError: f is undefined
Code:
<table id="webPosttable" cellpadding="5" cellspacing="0">
<thead>
<tr>
<th>DATE</th>
<th>CK</th>
<th>NAME</th>
<th>IN</th>
<th>RATE</th>
<th>COST</th>
</tr>
</thead>
<tbody>
<cfoutput query="myQuery">
<cfset totalreportin = totalreportin + val(counter)>
<cfset totalreportcost = rate*counter + totalreportcost>
<tr>
<TD>#inserteddate#</TD>
<TD>#ck#</TD>
<TD>#fullname#</td>
<TD>#counter#</TD>
<td>#decimalformat(rate)#</td>
<td>#dollarformat(rate*counter)#</td>
</tr>
</cfoutput>
</tbody>
<tfoot>
<cfoutput>
<tr>
<TD colspan="3">TOTAL:</TD><td>#totalreportin#</td><TD></td><td>#dollarformat(totalreportcost)#</td>
<TD colspan="3">AVERAGE:</TD><td><Cfif incomingreport.recordcount GT 0>#decimalformat(val(totalreportin/incomingreport.recordcount))#<Cfelse>0</CFIF></td>
</tr>
<tr>
<td></td><td><Cfif totalreportin GT 0>#dollarformat(totalreportcost/totalreportin)#<cfelse>0</cfif></td>
</tr>
</cfoutput>
</tfoot>
</table>
<script>
$('#webPosttable').DataTable({
"lengthChange": false,
"paging": false,
"bInfo" : false,
"dom": '<"pull-left"f><"pull-right"l>tip'
});
</script>
Does anyone know what if something is missing in my table structure or javascript datable settings?
Thanks
The problem won't be in your Coldfusion code, it will be the structure of your <tfoot> content. The number of columns in the tfoot doesn't match the number of columns in the rest of your table. Even the two trs within your tfoot don't match each other.
Comment out the tfoot temporarily to test whether it works without, then balance up the columns and put it back in.
eg:
<tfoot>
<cfoutput>
<tr>
<TD>TOTAL:</TD>
<td>#totalreportin#</td>
<td></td>
<td>#dollarformat(totalreportcost)#</td>
<TD>AVERAGE:</TD>
<td><Cfif incomingreport.recordcount GT 0>#decimalformat(val(totalreportin/incomingreport.recordcount))#<Cfelse>0</CFIF></td>
</tr>
<tr>
<td colspan="5"></td>
<td><Cfif totalreportin GT 0>#dollarformat(totalreportcost/totalreportin)#<cfelse>0</cfif></td>
</tr>
</cfoutput>
</tfoot>
If you still have errors after that then I'd advise updating the question to include the code showing which version of jQuery+datatables you're including and where and how you're including it. You may also need to wrap your script in a $(document).ready( function () { ...

Spring Boot And Thymeleaf remain on the same page on post request is made

I've created an web app that searches for online car ads and populates the page with a few tables after a post request.It looks like this:
After Search:
Every table element has a save button which should save those values to the database but my problem is that the page gets refreshed after submitting a post request. How can I do this without refreshing the page?
Table:
<form th:action="#{/saveAd}" method="POST">
<table class="table table-sm table-hover">
<thead class="thead-dark">
<tr>
<th>Imagine</th>
<th>Titlu Anunt</th>
<!-- <th style="width: 16.66%">Link</th> -->
<th>Pret</th>
<th>Oras</th>
</tr>
</thead>
<tbody id="myTable">
<th:block th:each="element : ${lista}">
<trth:onclick="'javascript:rowClicked(\'' + ${element.url} + '\');'">
<td><img th:src="#{${element.img}}" class="size" /></td>
<td th:text="${element.title}"></td>
<td th:text="${element.pret}"></td>
<td th:text="${element.oras}"></td>
<td><input class="btn btn-danger" type="submit"value="Save"></td>
</tr>
</th:block>
</tbody>
Controller:
#RequestMapping(path = "/saveAd", method = RequestMethod.POST)
public String saveAd(#ModelAttribute("adValue") AdValue adValue) {
System.out.println(adValue.getImg());
System.out.println(adValue.getLink());
System.out.println(adValue.getOras());
System.out.println(adValue.getPret());
System.out.println(adValue.getTitle());
return "home";
}
And also, how could I bind the list to a model object after pressing the save button?
I guess you may like this project. It is similar with what you need :
https://github.com/adinafometescu/tutorials/tree/master/spring-elasticsearch
You can use .bootstrapTable(). It a very method to update dynamically your table.
<table id="car-table" class="table table-striped">
<thead>
<tr>
<th data-field="id">Id</th>
<th data-field="title">Title</th>
<th data-field="price">Price</th>
<th data-field="city">City</th>
<th data-width="10" data-formatter="saveButtonFormatter"/>
</tr>
</thead>
</table>
The beauty is that it will map the data-field to a java object.
js stuff:
function saveButtonFormatter(value, row, index){
var adId = row.id;
return "<button class=\"btn btn-danger \" data-title=\"Save\"
data-toggle=\"modal\" onclick=\"saveAd(\'"+adId+"\')\"
</button>"
}
The function saveAd(adId) will call the rest endpoint and will update the bootstrap table on success.
I see that in your thymeleaf you don't have inputs. I suggest to not post your entire object if you don't need user input, just the id.
// anotate the controller class with #RestController
#Autowired
AdService adService;
#PostMapping(path = "/ad/{id}")
public ResponseEntity<?> saveAd(#PathVariable("id") String id) {
adService.saveAd(id);
return new ResponseEntity<>(HttpStatus.ACCEPTED);
}
P.S : don't write code in Romanian :D

datatables by ajax in codeigniter issue

I'm working on a project using codeigniter. I'm trying to use datatables to view data fetched by ajax. the network tab shows that the ajax returned values correctly but the function is marked as 404 and I get this error
"DataTables warning: table id=data - Ajax error. For more information about this error, please see http://datatables.net/tn/7"
Here's the ajax in the network tab
I checked the response and it's correct. I've opened the ajax function like this: domain.com/module/controller/merchantsTable and I got correct data
{ "merchantsdata":[{"id":"6","email":"user#mail.com"},{"id":"7","email":"user2#mail.com"}]}
datatables code [updated: added 'processing' and 'serverSide']
<table id="data">
<thead>
<tr>
<th>id</th>
<th>email</th>
</tr>
</thead>
<tfoot>
<tr>
<th>id</th>
<th>email</th>
</tr>
</tfoot>
<tbody>
</tbody>
</table>
//base_url refers to https://www.domain.com/
$(function () {
$('#data').DataTable( {
"processing": true,
"serverSide": true,
"ajax": "<?=base_url()?>merchants/admin_merchants/merchantsTable",
"columns": [
{ "merchantsdata": "id" },
{ "merchantsdata": "email"}
],
"order":[0 , 'desc'],
"lengthMenu": [[20, 50, -1], [20, 50, "All"]]
} );
});
So how to fix this issue and make it work?
change to
<table id="data">
<thead>
<tr>
<th>id</th>
<th>email</th>
</tr>
</thead>
<tbody>
</tbody>
<tfoot>
<tr>
<th>id</th>
<th>email</th>
</tr>
</tfoot>
</table>
Worked without modifying the code. My mistake, there was another folder in the root named 'merchants' so ajax didn't fetch data from the codeigniter route path (merchants module) but from the folder in the root which is wrong so I renamed the folder in the root and it worked.

Dynamically load a table using javascript

I want to load the table dynamically as soon as the page loads.i have tried the following code , but it is not showing 2nd column values found out in javascript.plz help me out.
<html>
<head>
<script type="text\javascript">
var brw=navigator.appCodeName;
var bw=navigator.appName;
var vrs=navigator.appVersion;
var plt=navigator.platform;
document.getElementById('r1').innerHTML = ' '+brw;
document.getElementById('r2').innerHTML = ' '+bw;
document.getElementById('r3').innerHTML = ' '+vrs;
document.getElementById('r4').innerHTML = ' '+plt;
</script>
</head>
<body>
<table border='1'>
<tr><td>Browser code </td><td><div id='r1'></div></td></tr>
<tr><td>Browser </td><td><div id='r2'></div></td></tr>
<tr><td>Browser Version </td><td><div id='r3'></div></td></tr>
<tr><td>Platform </td><td><div id='r4'></div></td></tr>
</table>
</body>
</html>
Your table should be like :
<table>
<thead>
<tr>
<th>Browser code</th>
<th>Browser</th>
<th>Browser version</th>
<th>Platform</th>
</tr>
</thead>
<tbody>
<tr>
<td><div id='r1'></div></td>
<td><div id='r2'></div></td>
<td><div id='r3'></div></td>
<td><div id='r4'></div></td>
</tr>
</tbody>
</table>
This way your table heads are set at top in <thead> balise, then you can add rows in <tbody> balise.
Just put your Javascript code at the end of your page.

Resources