Refresh data table after edit row in to database - html

I have data table in the manage.component.html (portion of code):
<table
class="table table-striped table-hover table-responsive-lg"
[mfData]="links$ | async"
#mf="mfDataTable"
[mfRowsOnPage]="10">
<thead>
<tr>
<th style="width: 5%">
<mfDefaultSorter by="id" #sortId>
ID
<span *ngIf="sortId.isSortedByMeAsc" class="cil-arrow-top" aria-hidden="true"></span>
<span *ngIf="sortId.isSortedByMeDesc" class="cil-arrow-bottom" aria-hidden="true"></span>
</mfDefaultSorter>
</th>
<th style="width: 50%">
<mfDefaultSorter by="linkCategory" #sortCategory>
Category
<span *ngIf="sortCategory.isSortedByMeAsc" class="cil-arrow-top" aria-hidden="true"></span>
<span
*ngIf="sortCategory.isSortedByMeDesc"
class="cil-arrow-bottom"
aria-hidden="true"
></span>
</mfDefaultSorter>
</th>
<th style="width: 50%"></th>
</tr>
</thead>
<tbody>
<tr *ngFor="let link of mf.data">
<td>{{ link.id }}</td>
<td>{{ link.linkCategory }}</td>
<td>
<button type="button" class="btn btn-primary mr-2 btn-edit" (click)="editLink(link.id)">
Edit
</button>
<button type="button" class="btn btn-danger ml-2 btn-delete" (click)="deleteLink(link.id)">
Delete
</button>
</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="9">
<mfBootstrapPaginator [rowsOnPageSet]="[5, 10, 15]"></mfBootstrapPaginator>
</td>
</tr>
</tfoot>
</table>
I have service for manage.component with links$ Observable as well:
export class ManageService {
private _links$ = new BehaviorSubject<model.Link[]>([]);
private _query$: BehaviorSubject<string> = new BehaviorSubject('');
links$: Observable<model.Link[]>;
query$: Observable<string>;
constructor(private httpClient: HttpClient) {
this.refreshLinks();
this.links$ = combineLatest([this._links$, this._query$]).pipe(
map(([links, query]) => links.filter(link => link.linkName.toLowerCase().includes(query)))
);
}
getLinks(): Observable<model.Link[]> {
return this.httpClient.get<model.Link[]>('/api/links');
}
findLink(query: string) {
this._query$.next(query);
}
private refreshLinks() {
this.getLinks().subscribe(links => {
this._links$.next(links);
});
}
}
For know everything is working correctly. I see table with data and buttons in every row.
I've prepared new edit.component for edit button:
form in HTML with data prefilled
scss styles
submit button which who is calling createLink method as below (method from edit.service):
public createLink() {
this.link.id = parseInt(this.linkId);
this.service.createLink(this.link).subscribe(res => {
console.log(res);
this.router.navigate(['/links/manage']);
});
this.publishModal.hide();
}
edit.service.ts (portion of code):
createLink(link: model.Link): Observable<model.Link> {
return this.httpClient.post<model.Link>('/api/createLink', link, this.httpOptions);
}
My changed data are sending to database correctly and after submit I have newer data in DB and I'm navigate back to table with whole links.
I see table of links$ but I have to refresh the browser to see updated rows as well.
In console.log(res); I see updated object, in DB I see it also but I don't see them on the screen.
What's wrong?

Related

html/css - add rows numbers

I am trying to add row numbers in html/css.
Here is the html, react populating the rows.
<table className="table table-striped">
<thead>
<tr>
{/*<th>ID</th>*/}
<th>symbol</th>
<th>close</th>
<th>percent</th>
<th>PE</th>
<th>Rake</th>
<th />
</tr>
</thead>
<tbody>
{ this.props.item_sett_list.map(item_sett_list_item => (
<tr key={item_sett_list_item.id}>
{/*<td>{item_sett_list_item.id}</td>*/}
<td>{item_sett_list_item.symbol}</td>
<td>{item_sett_list_item.close}</td>
<td>{item_sett_list_item.percent}</td>
<td>{item_sett_list_item.pe}</td>
{
this.props.rake_sett_list.length ?
this.props.rake_sett_list.map(rake_sett_list_item => (
<td>{rake_sett_list_item.rake}</td>
)) : <td><button className='btn btn-primary btn-sm'>RAKE</button></td>
}
<td><button onClick={this.props.deleteDCASettings.bind(this, item_sett_list_item.id)}className='btn btn-danger btn-sm'>Delete</button></td>
</tr>
)) }
</tbody>
</table>
I tried to use custom.css from this answer:
The custom.css loads, I can see custom properties in some other elements. However the rows don't get the rows numbers.
How about map indexes:
{ this.props.item_sett_list.map((item_sett_list_item, index) => (
<tr key={item_sett_list_item.id}>
{/*<td>{index}</td>*/}
<td>{item_sett_list_item.symbol}</td>
<td>{item_sett_list_item.close}</td>
<td>{item_sett_list_item.percent}</td>
<td>{item_sett_list_item.pe}</td>
{
this.props.rake_sett_list.length ?
this.props.rake_sett_list.map(rake_sett_list_item => (
<td>{rake_sett_list_item.rake}</td>
)) : <td><button className='btn btn-primary btn-sm'>RAKE</button></td>
}
<td><button onClick={this.props.deleteDCASettings.bind(this, item_sett_list_item.id)}className='btn btn-danger btn-sm'>Delete</button></td>
</tr>
)) }

How to change boolean value within json file using a button in angular & typescript?

My question is, how do I write a function in my table-viewer.component.ts file to change the value from false to true within the JSON file based on whether the user clicks the cancelled button?
I have a JSON file containing the following details.
db.json
"firstName": "Hamza",
"lastName": "Gallagher",
"carReg": "FG67 POI",
"parkingNumber": "00003",
"date": "2021-01-04",
"cancelled": false
etc ..
And I am displaying them in a table with angular, which shows the following:
Image of table
Table-viewer.component.html
<table class="table table-striped table-bordered table-hover">
<thead>
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Car Registration</th>
<th>Parking Number</th>
<th>Date</th>
<th>Status</th>
<th></th>
</tr>
</thead>
<tbody>
<tr *ngFor="let booking of bookings">
<td>{{booking.firstName}}</td>
<td>{{booking.lastName}}</td>
<td>{{booking.carReg}}</td>
<td>{{booking.parkingNumber}}</td>
<td>{{booking.date}}</td>
<td>
<div *ngIf="booking.cancelled" class="red">Cancelled</div>
<div *ngIf="!booking.cancelled" class="green">Booked</div>
</td>
<td>
<button class="btn btn-danger mr-2" (click)="cancelBooking()">Cancel</button>
</td>
</tr>
table-viewer.component.ts
export class TableViewerComponent implements OnInit {
bookings: Booking[] = [];
getBookings(): void {
this.bookingService.getAll().subscribe((book: Booking[]) => {
this.bookings = book;
});
}
constructor(private bookingService: BookingService) {
}
ngOnInit(): void {
this.getBookings();
}
cancelBooking(): void {
// Help
}
}
booking.ts
export interface Booking {
'firstName': string;
'lastName': string;
'carReg': string;
'parkingNumber': string;
'date': string;
'cancelled': boolean;
}
I think it is as simple as:
cancelBooking(booking:Booking){
booking.cancelled = true;
}
And just pass it in the view to the method
Please use this code in your componenet.ts
cancelBooking(index): void {
// Help
this.bookings[index].cancelled = true;
}
Template :
Change the loop code with below code:
<tr *ngFor="let booking of bookings; let i = index">
<td>{{booking.firstName}}</td>
<td>{{booking.lastName}}</td>
<td>{{booking.carReg}}</td>
<td>{{booking.parkingNumber}}</td>
<td>{{booking.date}}</td>
<td>
<div *ngIf="booking.cancelled" class="red">Cancelled</div>
<div *ngIf="!booking.cancelled" class="green">Booked</div>
</td>
<td>
<button class="btn btn-danger mr-2" (click)="cancelBooking(i)">Cancel</button>
</td>
</tr>
Table-viewer.component.html
<table class="table table-striped table-bordered table-hover">
...
<td>
<button class="btn btn-danger mr-2" (click)="cancelBooking(booking: Booking)">Cancel</button>
</td>
</tr>
table-viewer.component.ts
export class TableViewerComponent implements OnInit {
...
cancelBooking(booking): void {
booking.cancelled = !booking.cancelled
// or booking.cancelled = false; or whatever you want to do
}
}
Now, you have the change in the bookings array.
Next, you should implement a service to rewrite a json file.
https://stackoverflow.com/a/52242184/11218448

How to access specific object in JSON using Angular?

I'm trying to access certain data from an API and having trouble doing so. Here is the structure of the JSON from the API:
I'm wanting to access Name, StateName & CityName within value to iterate through a table. I'm getting the obvious error "Cannot find a differ supporting object '[object Object]' of type 'object'. NgFor only supports binding to Iterables such as Arrays", because ngFor isn't iterating through the array. How can I fix my code to iterate through the data to fill my table?
component.ts:
#Component({
selector: 'app-search',
templateUrl: './search.component.html',
styleUrls: ['./search.component.css']
})
export class SearchComponent implements OnInit {
customer: any;
constructor(private Service: CustomerDataService) { }
ngOnInit(): void {
this.getCustomerData();
}
public getCustomerData() {
this.Service.getCustomers().subscribe((data)=>{
console.log(data);
this.customer = data;
})
}
}
HTML:
<div class="container">
<form class="form-inline">
<div class="input-group mb-2">
<div class="has-clear">
<input type="text" name="search" required class="form-control" placeholder="Name" />
<button class="clear-data" type="reset"><i class="icon-close-bold-sm"></i></button>
</div>
<button type="submit" class="btn btn-primary mb-2 ml-3">Search</button>
</div>
</form>
<div class="table-responsive">
<table class="table table-striped">
<thead>
<tr>
<th scope="col">Name</th>
<th scope="col">City</th>
<th scope="col">State</th>
</tr>
</thead>
<tbody>
<tr *ngFor = "let customers of customer">
<td scope="row">{{customers.value.Name}}</td>
<td scope="row">{{customers.value.StateName}}</td>
<td scope="row">{{customers.value.CityName}}</td>
</tr>
</tbody>
</table>
</div>
</div>
The value is an array and not object, so
public getCustomerData() {
this.Service.getCustomers().subscribe((data)=>{
console.log(data);
this.customer = data.value;
})
}
and in your template
<tr *ngFor = "let customers of customer">
<td scope="row">{{customers.Name}}</td>
<td scope="row">{{customers.StateName}}</td>
<td scope="row">{{customers.CityName}}</td>
</tr>
Or you can just edit your template
<tr *ngFor = "let customers of customer.value">
<td scope="row">{{customers.Name}}</td>
<td scope="row">{{customers.StateName}}</td>
<td scope="row">{{customers.CityName}}</td>
</tr>
Consider using | async to access the observable directly in your html
<tr *ngFor = "let customer of customers$ | async">
<td scope="row">{{customer.Name}}</td>
<td scope="row">{{customer.StateName}}</td>
<td scope="row">{{customer.CityName}}</td>
</tr>
and in your component
customers$ : Observable<Customer> = this.getCustomerData();
You can update your getCustomerData with a map operator to return the list of Customers you have inside value property.

ngx-pagination is not getting updated after filtering data

I am using custom filters and ngx-pagination on my JSON data. The problem here is when I am filtering the data my pagination control is not getting updated, still showing the old page size and allowing pagination even if the data is not available. Please suggest.
Right now, it has 21 results without any filter applied
Now, I have applied filters n now it's showing only 1 record but pagination is still showing 5 pages (considering 5 per page size).
table-filter.pipe.ts
import { Pipe, PipeTransform } from "#angular/core";
#Pipe({
name: "tableFilter"
})
export class TableFilterPipe implements PipeTransform {
transform(list: any[], filters: any) {
const keys = Object.keys(filters).filter(key => filters[key]);
const filterUser = (user: { [x: string]: any; }) =>
keys.every(key => {
if (key == "sdob") {
return new Date(user["dob"]) >= new Date(filters[key]);
} else if (key == "edob") {
return new Date(filters[key]) >= new Date(user["dob"]);
} else {
return user[key] === filters[key];
}
});
return keys.length ? list.filter(filterUser) : list;
}
}
app.component.html
<table class="table table-sm table-responsive">
<thead>
<tr>
<th></th>
<th>First Name</th>
<th>Last Name</th>
<th>Email</th>
<th>Gender</th>
<th>DOB (mm/dd/yyyy)</th>
<th>Impact</th>
<th>Score</th>
<th></th>
</tr>
</thead>
<tbody>
<tr class="record-row" (click)="viewUser(user)" *ngFor="let user of allUser | tableFilter: form.value | paginate: { id: 'listing_pagination', itemsPerPage: 5, currentPage: page, totalItems: totalRecords }">
<td><input *ngIf="!isEdit" [(ngModel)]="user.checked" type="checkbox" (change)="checkboxClicked()"></td>
<td>{{user.first_name}}</td>
<td>{{user.last_name}}</td>
<td>{{user.email}}</td>
<td>{{user.gender}}</td>
<td>{{user.dob}}</td>
<td>{{user.impact}}</td>
<td>
<div [ngClass]="getClass(user)">{{user.score}}</div>
</td>
<td>
<button *ngIf="!isEdit" class="btn btn-primary btn-sm" (click)="editUser(user)">Edit</button>
<button class="btn btn-primary btn-sm btn-sm ml-2" (click)="deleteUser(user)">Delete</button>
</td>
</tr>
</tbody>
</table>
<pagination-controls id="listing_pagination" directionLinks="true" (pageChange)="page = $event"></pagination-controls>

Why isn't my form posting any data even though I've set the name property?

So I'm trying to post a form with some data, but for some reason when clicking the button that POSTS the data, I'm not getting anything serversided, all the values are NULL.
As you can see it's a simple form that uses razor and I've set the name and the id properties of the elements I want to send
<table class="table table-hover mb-0">
<thead>
<tr>
<th>#</th>
<th>Name</th>
<th>Version</th>
</tr>
</thead>
<tbody>
#foreach (var _model in Model)
{
<tr>
#using (Html.BeginForm("Start", "Dashboard", FormMethod.Post))
{
<div class="form-group">
<td id="serverid" name="serverid">#Html.DisplayTextFor(x => _model.ServerID) #Html.HiddenFor(x => _model.ServerID)</td>
<td>
#Html.DisplayTextFor(x => _model.ServerName) #Html.HiddenFor(x => _model.ServerName)
</td>
<td>
#Html.DisplayTextFor(x => _model.Version) #Html.HiddenFor(x => _model.Version)
</td>
<td>
<button type="submit" asp-action="Start" asp-controller="Dashboard" class="btn btn-icon waves-effect waves-light btn-success" onclick="Start('#_model.ServerName')"> <i class="fa fa-power-off"></i> </button>
</td>
</div>
}
</tr>
}
</tbody>
</table>
And here is what the model looks like
public class ServerModel
{
public string ServerID { get; set; }
public string ServerName { get; set; }
}
And here is the action that's inside the controller
//The "model" parameter here exists, but all the properties are null when inspecting it
public async Task<IActionResult> Start(ServerModel model)
{
//Doing stuff here
}
Why are all the properties inside the model null when inspecting them after posting? I'm putting a breakpoint to inspect it.
Change your submit button to -
<button type="submit" class="btn btn-icon waves-effect waves-light btn-success"> <i class="fa fa-power-off"></i> </button>
As you are within the form element (generated by beginform) you dont need the additional attributes. Also not entirely sure what your intentions are with -
onclick="Start('#_model.ServerName')
Firstly you can remove the onclick="Start('#_model.ServerName')" of submit button since you are passing the data via Form Post , then modify below codes :
#Html.HiddenFor(x => _model.ServerID)
#Html.HiddenFor(x => _model.ServerName)
To :
<input name="ServerID" type="hidden" value="#_model.ServerID">
<input name="ServerName" type="hidden" value="#_model.ServerName">
So it will match name with model's property name during model binding .