React js iteration of JSON array is not working - html

i am unable to repeat the row dynamically. when i am using .map method it is showing .map is not a function.
Component
import React, {Component} from 'react';
const pannelWidth = {
width: '90%'
};
const pannelHeader = {
color: 'white'
};
class ProjectList extends Component {
constructor(props) {
super(props);
this.state = {
projectList : ''
}
//this.deleteProjectMessage = this.deleteProjectMessage.bind(this);
}
componentDidMount() {
let d = '';
$.get("http://localhost:8008/api/navigation/all", function (data) {
d = data;
this.setState({
projectList: d
});
}.bind(this));
console.log(this.state.projectList);
}
render() {
var listItems = this.state.projectList.map(function (item, index) {
return <tr>
<td>{item.name}</td>
<td>{item.description}</td>
<td><i className="glyphicon glyphicon-trash"></i></td>
</tr>
});
return(
<div className="container" style={pannelWidth}>
<br/>
<div className="panel panel-primary">
<div className="panel-heading">
<div className="row">
<div className="col-md-2 col-lg-2">
<h4 style={pannelHeader}>Project List</h4>
</div>
<div className="col-md-offset-8 col-lg-offset-8 col-md-2 col-lg-2">
<button className="btn btn-sm btn-success">Create New Project</button>
</div>
</div>
</div>
<div className="panel-body">
<table className="table table-striped">
<thead>
<tr>
<th>Project Name</th>
<th>Description</th>
<th>Action</th>
</tr>
</thead>
<tbody>
{listItems}
</tbody>
</table>
</div>
</div>
</div>
);
}
}
export default ProjectList;
JSON
[
{
"name": "pro",
"description": "Testing of pro"
},
{
"name": "Test",
"description": "Testing of Test"
}
]
i am calling api from my local system and getting above response and updating the state. then i am trying to render in side table row using map() but it is showing map is not a function in console.

you are defaulting projectList to a string, default it to an empty array.
this.state = {
projectList : '' // should be projectList: []
}
You are making an async request so the initial render of the component is trying to call map on the initial state which is
''.map(function (item, index) {
return <tr>
<td>{item.name}</td>
<td>{item.description}</td>
<td><i className="glyphicon glyphicon-trash"></i></td>
</tr>
});

If the data comes back as a string, you can't map it. You first need to parse the JSON text into a JavaScript array.
d = JSON.parse(data);

Related

Data not displaying in the HTML file while using the api?

I am working on a shopping cart application. I'm facing issue while displaying the user selected products in the cart.component.html, as the data is not rendering. DOM is being created every time but the data is not displaying in the cart.component.html ? can anyone suggest how to solve this problem ?
cart.component.html
`
<ng-container *ngIf="products.length !=0">
<div class="container">
<div class="card-table">
<div class="cart-product">
<table class="table table-responsive">
<thead>
<tr>
<th>Sr.No</th>
<th>Product Name</th>
<th>Product Image</th>
<th>Description</th>
<th>Price</th>
<th>Quantity</th>
<th>Total</th>
<!-- <th>Action</th> -->
</tr>
</thead>
<tbody>
<tr *ngFor="let item of products; let i = index">
<td>{{ i + 1 }}</td>
<td>{{ item.title }}</td>
<td>
<img style="width: 120px" src="{{ item.image }}" alt="" />
</td>
<td style="width: 25%">{{ item.description }}</td>
<th style="width: 12%">{{ item.price }}</th>
<td style="width: 12%">{{ item.quantity }}</td>
<td style="width: 12%">{{ item.total }}</td>
<td>
<!-- <button (click)="removeItem(item)" class="btn btn-danger"><i class="fas fa-trash-alt"></i></button> -->
<!-- </td> -->
</td>
</tr>
<tr>
<td colspan="4"></td>
<!-- <td><button (click)="emptycart()" class="btn btn-danger">Empty Cart</button></td> -->
<td>
<button routerLink="/products" class="btn btn-primary">
Shop More
</button>
</td>
<!-- <td><button class="btn btn-success">Checkout</button></td> -->
<td>
<strong>Grand Total : ${{ grandTotal }}</strong>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</ng-container>
<ng-container *ngIf="products.length == 0">
<div class="container">
<div class="card">
<h5 class="card-title">My Cart</h5>
</div>
<div class="center">
<img
src="https://rukminim1.flixcart.com/www/800/800/promos/16/05/2019/d438a32e-765a-4d8b-b4a6-520b560971e8.png?q=90"
alt=""
/>
<h4>Your cart is empty!</h4>
<h6>Add item to it now</h6>
<button routerLink="/products" class="btn btn-primary">Shop Now</button>
</div>
</div>
</ng-container>
cart.component.ts
`
import { Component, OnInit } from '#angular/core';
import { NavbarserviceService } from 'src/app/navbarservice.service';
import { CartService } from 'src/app/service/cart.service';
#Component({
selector: 'app-cart',
templateUrl: './cart.component.html',
styleUrls: ['./cart.component.css']
})
export class CartComponent implements OnInit {
public products : any = [];
public grandTotal !: number;
constructor(private cartService : CartService, public nav: NavbarserviceService) { }
ngOnInit(): void {
this.nav.show();
this.cartService.getProducts()
.subscribe(res=>{
this.products = res;
this.grandTotal = this.cartService.getTotalPrice();
});
}
// removeItem(item: any){
// this.cartService.removeCartItem(item);
// }
// emptycart(){
// this.cartService.removeAllCart();
// }
}
cart.service.ts
`
import { Injectable } from '#angular/core';
import { BehaviorSubject } from 'rxjs';
import { HttpClient } from '#angular/common/http';
import { LoginService } from '../component/login/login.service';
import { UserCart } from './cart';
import { item } from './product';
#Injectable({
providedIn: 'root'
})
export class CartService {
public cartItemList: any = []
public productList = new BehaviorSubject<any>([]);
public search = new BehaviorSubject<string>("");
constructor(private http: HttpClient, private login: LoginService) {
console.log ("constrcutor called")
}
populateDataFromBackend() {
console.log ("populateDataFromBackend called")
var cartItemListLocal: any = []
//return this.productList.asObservable();
//Return data from backend
var apiRequest: string = "http://localhost:3000/userCart?emailId=" + this.login.loggedInUserID;
this.http.get<UserCart[]>(apiRequest)
.subscribe(res => {
console.log(res);
res.forEach(element => {
console.log(element.emailId, element.productId);
var getProductAPI: string = "http://localhost:3000/products?id=" + element.productId;
this.http.get<item>(getProductAPI).subscribe(res => {
//
console.log(res);
cartItemListLocal.push(res);
// this.productList.next (res);
// productListNew.next (cartItemListLocal);
})
});
}
)
console.log("cartItemsLocal\n");
console.log(cartItemListLocal);
this.productList.next(cartItemListLocal);
}
getProducts() {
this.populateDataFromBackend();
return this.productList.asObservable();
}
setProduct(product: any) {
this.cartItemList.push(...product);
this.productList.next(product);
}
addtoCart(product: any) {
var cartItem = new UserCart(this.login.loggedInUserID, product.id);
console.log(cartItem, "cartItem");
this.http.post("http://localhost:3000/userCart", cartItem).subscribe(
(data) => {
console.log("Datasent to cart ", data);
}
)
/*
this.cartItemList.push(cartItem);
this.productList.next(this.cartItemList);
this.getTotalPrice();
console.log(this.cartItemList,"this.cartItemlist")
this.http.post("http://localhost:3000/userCart",this.cartItemList).subscribe(
(data) => {
console.log("Datasent to cart ",data);
}
)
*/
}
getTotalPrice(): number {
let grandTotal = 0;
this.cartItemList.map((a: any) => {
grandTotal += a.total;
})
return grandTotal;
}
// removeCartItem(product: any){
// this.cartItemList.map((a:any, index:any)=>{
// if(product.id=== a.id){
// this.cartItemList.splice(index,1);
// }
// })
// this.productList.next(this.cartItemList);
// }
// removeAllCart(){
// this.cartItemList = []
// this.productList.next(this.cartItemList);
// }
}
product.ts
export class item {
id!: number;
title!: string;
price!: number;
description!: string;
category!: string;
image!: string;
/*
"rating": {
"rate": 3.9,
"count": 120
}*/
}
Can you try calling the http request in the constructor and doing the assignment there?
{{ item?.description }}
and others arrange table cells like this
There are few things I would improve:
First, your interface (or model) product.ts is called item, but you are not using it anywhere. Try to do this:
export class Product {
id: number;
title: string;
price: number;
description: string;
category: string;
image: string;
}
Doing that, you can import it in your component.ts use it when you instantiate a product object, like this:
products : Product[] = [];
Try to do this every time it is possible since we are working with Angular (and TypeScript) and we must avoid using any.
As other people mentioned in the comments, the rest looks good, so try to do that and update the question.

React.js datatable data filter by datepicker and get sum value of column

import React, { useEffect, useState } from "react";
import axios from "axios";
import { Form } from "react-bootstrap";
function SalesReport() {
const [Data, setData] = useState([]);
useEffect(() => {
fetchData();
}, []);
const fetchData = () => {
axios.get("http://localhost:4000/api/cash/showInvoices").then((res) => {
const getData = res.data.data;
setData(getData);
});
};
return (
<div className="row">
<div className="card">
<div className="card-body">
<div className="d-inline-flex col-2 m-2">
<Form.Group controlId="dob">
<Form.Label>Start Date</Form.Label>
<Form.Control
type="date"
name="startDate"
placeholder="Date of Birth"
/>
</Form.Group>
<div className="ms-3">
<Form.Group controlId="dob">
<Form.Label>End Date</Form.Label>
<Form.Control
type="date"
name="enddate"
value={}
placeholder="Date of Birth"
/>
</Form.Group>
</div>
<div className="ms-2 mt-4">
<button className="btn btn-secondary btn-lg" type="button">
Print
</button>
</div>
</div>
<table
id="datatable-buttons"
className="table table dt-responsive nowrap w-100"
>
<thead>
<tr>
<th width="100px">Date</th>
<th>Invoice Id</th>
<th>Pay Method</th>
<th>Total</th>
<th>Customer Id</th>
<th>Cart Id</th>
</tr>
</thead>
<tbody>
{Data &&
Data.map((items) => {
return (
<tr>
<td> {new Date(items.date).toLocaleDateString()}</td>
<td>{items.invoice_id}</td>
<td>{items.pay_method}</td>
<td>{items.total}</td>
<td>{items.customer_id}</td>
<td>{items.inovice_cart_id}</td>
</tr>
);
})}
</tbody>
<tfoot>
<tr className="text-black font-weight-bol">
<td>
<h5 className="total-label">Grand Total</h5>
</td>
<td className="total-col">
<label></label>
</td>
<td className="total-col">
<label></label>
</td>
<td className="total-col">
<label>2234</label>
</td>
<td className="total-col">
<label></label>
</td>
<td className="total-col">
<label></label>
</td>
</tr>
</tfoot>
</table>
</div>
</div>
</div>
);
}
export default SalesReport;
**backend**
*router.js*
const {
getInvoice,
viewInvoiceByDate,
} = require("./cashManagement.controller");
const router = require("express").Router();
const cors = require("cors");
router.get("/showInvoices", getInvoice);
module.exports = router;
*controller.js*
const { getInvoice, viewInvoiceByDate } = require("./cashManagement.service");
module.exports = {
getInvoice: (req, res) => {
getInvoice((err, results) => {
if (err) {
console.log(err);
return;
}
return res.json({
success: 1,
data: results,
});
});
},
}
*service.js*
const pool = require("../../config/database");
module.exports = {
getInvoice: (callBack) => {
var todayDate = new Date().toISOString().slice(0, 10);
pool.query(
`SELECT * FROM cash_management WHERE date='${todayDate}'`,
(errors, results, fields) => {
if (errors) {
return callBack(errors);
}
return callBack(null, results);
}
);
},
}
That picture shows what I'm trying to do. by default today's relevant data show. it took from using "new Date()" method using with mysql select query . So , if I want to get particular days period data , I should select it from data picker. There is two datapickers . one for starting date, second one for end data selecting. if I select just start date , I need data from that day to today . otherwise if I select just endDate , I need to get data from today to end date . so I tried to that someways. It doesn't work properly. My backend code here ,it contains how I got data from database . I just got data from using "newDate()" method to took today data. how it should be changed when entering start date and end date . otherwise here table you can see the total column . and table footer has "GrandTotal " 4th column should get the total values of "total columns" previously I took it direct from database. but now cant , because it is changed by quickly. I think you have clear idea about issue. I tried many ways , but it didn't work. if there any expert help me to solve the issue.

React: Add Button to Component which Navigates to another page

I want to add Button to the Component which after click will navigate to another page.
Currently I am using react 18.0.
Bellow is the component:
import React from 'react';
import EmployeeService from '../Services/EmployeeService';
import { AddEmployee } from '../Functions/AddEmployee';
class ListEmployeeComponent extends React.Component {
constructor(props) {
super(props)
this.state={
employees: []
}
}
componentDidMount() {
EmployeeService.getEmployees().then((res) => {
this.setState({employees:res.data});
});
}
render() {
return (
<div>
<h2 className='text-center'>Employee List</h2>
<div className='row'>
<button className='btn btn-primary' onClick={AddEmployee.bind(this)}>Add Employee</button>
</div>
<div className='row'>
<table className='table table-striped table-bordered'>
<thead>
<tr>
<th>Employee First Name</th>
<th>Employee Last Name</th>
<th>Employee Email Name</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{
this.state.employees.map(
employee =>
<tr key={employee.id}>
<td>{employee.firstName}</td>
<td>{employee.lastName}</td>
<td>{employee.email}</td>
</tr>
)
}
</tbody>
</table>
</div>
</div>
);
}
}
export default ListEmployeeComponent;
this is the button:
import { useNavigate } from 'react-router';
export function AddEmployee(a, b) {
let navigate = useNavigate();
return (
navigate('http://localhost:3000/add-employee')
);
}
And on the attached picture is an error which I am getting when I press button:
Erorr
As the error message says, React hooks need to be used from within a function component. The hook in question here is useNavigate, which you're calling from a regular function, hence the error. If you instead inject the navigate variable into the AddEmployee function, you shouldn't have a problem.
export function AddEmployee(navigate, a, b) {
navigate(...);
}
// then within the component, do something akin to
const navigate = useNavigate();
AddEmployee(navigate, a, b)
Okey after several hours of looking how to solve a problem I have made following
I removed Add Employee function complitely.
I imported Link from react-router-dom and change the Button to be Link to
import {React, Component} from 'react';
import {Link} from 'react-router-dom'
import EmployeeService from '../Services/EmployeeService';
class ListEmployeeComponent extends Component {
constructor(props) {
super(props)
this.state={
employees: []
}
}
componentDidMount() {
EmployeeService.getEmployees().then((res) => {
this.setState({employees:res.data});
});
}
render() {
return (
<div>
<h2 className='text-center'>Employee List</h2>
<div className='row'>
<Link to = '/add-employee' className='btn btn-primary' >Add Employee </Link>
</div>
<div className='row'>
<table className='table table-striped table-bordered'>
<thead>
<tr>
<th>Employee First Name</th>
<th>Employee Last Name</th>
<th>Employee Email Name</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{
this.state.employees.map(
employee =>
<tr key={employee.id}>
<td>{employee.firstName}</td>
<td>{employee.lastName}</td>
<td>{employee.email}</td>
</tr>
)
}
</tbody>
</table>
</div>
</div>
);
}
}
export default ListEmployeeComponent;

Angular 6 DataTables - Table Items Appear/Disappear Upon Sort or Search

I am using Angular-DataTables 6.0 (found here https://l-lin.github.io/angular-datatables/#/welcome) and I have been running into a reoccurring problem. When a table item is added or deleted, the record either vanishes or reappears upon sorting or searching. Is this possibly because the adding/deleting is occurring from outside the dataTable?
I've tried adding the ' datatable="ng" ' fix many others suggested but that didn't change anything. I also attempted to add a re-render function, but in that case I ran into 'object unsubscribed' errors that I couldn't resolve. For reference, some similar problems can be found here: Similar examples include: (angular : lost data after sort datatable)
(Sorting of numbers within brackets in angular datatables)
(https://github.com/l-lin/angular-datatables/issues/852)
Here is my code:
HTML:
<table datatable="ng" [dtOptions]="dtOptions" [dtTrigger]="dtTrigger" class="table table-hover" id="t1">
<thead>
<tr>
<th>
<button id="b5">Asset ID</button>
</th>
<th>
<button id="b5">Employee ID</button>
</th>
<th>
<button id="b5">Asset Type</button>
</th>
<th>View</th>
<th>Delete</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let a of assets; let i = index">
<td>{{ a.assetID }}</td>
<td>{{ a.currentUser }}</td>
<td>{{ a.assetType }}</td>
<td><button id="button1" (click)="viewAsset(a)"><i class="fas fa-search"></i></button></td>
<td><button id="b2" class="btn" (click)="scrapAsset(a)" (mouseenter)="buttonHover(i)" (mouseleave)="buttonHoverLeave(i)"><i class="{{buttonIconArray[i].text}}"></i></button></td>
</tr>
</tbody>
</table>
-elsewhere in the code-
<button class="btn" id="b1" (click)="addAsset()">Add New Asset</button>
TS
dtOptions: DataTables.Settings = {};
dtTrigger = new Subject();
addAsset()
{
this.confirmChanges = false;
//Create a new asset:
let a: Asset = {
assetID: this.assetID,
currentUser: this.currentUser,
assetType: this.dropdownMessage,
}
//send a notification to the user that owns the new asset
let notify: Notice = {
emplyID: a.currentUser,
notificationSource: "Asset",
details: "A new " + this.dropdownMessage + " was added to your assets.",
timeStamp: new Date()
}
//Add the asset to the server
this.AssetsService.addAsset(a)
.subscribe(asset => { this.assets.unshift(asset);
//All of the inputs need to be emptied
this.clearFields();
})
}
scrapAsset(a: Asset)
{
console.log("The ID is " , a.assetID)
//this.AssetsService.deleteAsset(this.currentAsset).subscribe()
this.confirmChanges = false;
//This deletes the asset from the back-end.
this.AssetsService.deleteAsset(a).subscribe(() => {
console.log('test')
this.assets = this.assets.filter(t => t !== a);
this.NotificationsService.addNotice(notify).subscribe();
this.clearFields(); });
}
dtActivate()
{
this.dtOptions = {
pagingType: 'full_numbers',
pageLength: 7,
order: (this.assets.assetType),
orderClasses: false,
};
this.AssetsService.getAssetsIT().subscribe((assetsImported) => {
this.assets = assetsImported;
this.parseData();
// Calling the DT trigger to manually render the table
this.dtTrigger.next();
});
}
This is only a partial section of the code, so if you need to see more, just ask. Thank you for any help you might provide!
I've had the same problem for a long time. After a lot of stack overflow and documentation, I found a solution that fixed my problem. Maybe it helps you too.
Allow datatable to be destroyed
ngOnInit() {
this.dtOptions = {
destroy: true,
...
};
...
}
The method that received new items (called after edit, insert, add...).
onReceived(items){
let isFirst = this.items.length === 0;
this.items = <itemsModel[]>items;
if (isFirst)
this.dtTrigger.next();
else
this.rerender();
}
The rerender as in documentation
rerender(): void {
this.dtElement.dtInstance.then((dtInstance: DataTables.Api) => {
dtInstance.destroy();
this.dtTrigger.next();
});
}
https://l-lin.github.io/angular-datatables/#/advanced/rerender
I hope that this might help you.
this will work, but i am still looking for better solutions
setTimeout(function () {$(function () {$('#ng').DataTable();});}, 10);
You can remove the ng, Following code fixed my problem
<div class="container-fluid">
<div class="page-title">
<h4>Milk Types</h4>
</div>
<div class="row">
<div class="col-md-12">
<div class="card">
<div class="card-block">
<a href="" class="btn btn-success" href='' [routerLink]="['/milk/create-milk']">
<i class="ti-zip pdd-right-5"></i>
<span>Add New Milk</span>
</a>
<div class="table-overflow">
<table class="table table-lg table-hover" datatable [dtTrigger]="dtTrigger" [dtOptions]="dtOptions">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Status</th>
<th>Price</th>
<th></th>
</tr>
</thead>
<tbody>
<tr *ngFor="let drink of data">
<td>
<div class="mrg-top-15">
<b class="text-dark font-size-16">{{ drink.id }}</b>
</div>
</td>
<td>
<div class="mrg-top-15">
<span class="text-info pdd-left-20"><b>{{ drink.name }}</b></span>
</div>
</td>
<td>
<div class="col-md-5">
<div class="toggle-checkbox toggle-success checkbox-inline">
<input type="checkbox" name="isEnabled" id="toggle4" [checked]="drink.isEnabled">
<label for="toggle4"></label>
</div>
</div>
</td>
<td>
<div class="mrg-top-15">
<span class="text-info"><b>KD {{ drink.price }}</b></span>
</div>
</td>
<td>
<div class="mrg-top-10 text-center">
<a href="" class="btn btn-warning">
<i class="ti-comment pdd-right-5"></i>
<span>Edit</span>
</a>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
import { Component, OnInit, Input, OnDestroy , ViewEncapsulation } from '#angular/core';
import { AngularFireDatabase } from 'angularfire2/database';
import { pipe, Subscription } from 'rxjs';
import { MilksItem, MilksDataSource } from './milks-datasource';
import { Subject } from 'rxjs';
#Component ({
templateUrl: 'milk.html'
})
export class MilkComponent implements OnInit {
dtOptions: DataTables.Settings = {};
subscription: Subscription;
data: MilksItem[] = [];
dtTrigger: Subject<MilksItem> = new Subject();
constructor(private db: AngularFireDatabase)
{
}
ngOnInit() {
this.dtOptions = {
pagingType: 'full_numbers'
};
this.subscription = this.db.list<MilksItem>('milkTypes').valueChanges().subscribe(d=>{
console.log('data streaming');
this.data = d;
this.dtTrigger.next();
});
}
ngOnDestroy(): void {
this.subscription.unsubscribe();
this.dtTrigger.unsubscribe();
}
}
Another Working Solution
Just move your data-table inside a separate component
AND
Provide your new options/data as an Input()
import { AfterViewInit, Component, Input, OnChanges, OnDestroy, OnInit, SimpleChanges, ViewChild } from '#angular/core';
import { DataTableDirective } from 'angular-datatables';
import { Subject } from 'rxjs';
#Component({
selector: 'app-datatable',
templateUrl: './datatable.component.html',
styleUrls: ['./datatable.component.scss']
})
export class DatatableComponent implements OnInit, OnDestroy, OnChanges, AfterViewInit {
#ViewChild(DataTableDirective, { static: false }) dt!: DataTableDirective;
#Input() dtOptions: DataTables.Settings = {};
dtTrigger: Subject<any> = new Subject<any>();
constructor() { }
private _initComponent() {
this.dtTrigger.next(this.dtOptions);
}
ngOnInit(): void {
}
ngAfterViewInit(): void {
this._initComponent();
}
ngOnChanges(changes: SimpleChanges): void {
}
ngOnDestroy(): void {
this.dtTrigger.unsubscribe();
}
}
<table #dtA datatable [dtOptions]="dtOptions" [dtTrigger]="dtTrigger"
class="custom-dt-1 table table-sm table-striped card-table w-full row-border hover">
</table>

Reactjs problems when ajax data from json file

I have a problem when I develop a react web application. Here's my code:
class TableContentRow extends React.Component {
render(){
return(
<tr>
<td>{this.props.voucher.merchantName}</td>
<td>{this.props.voucher.voucherCode}</td>
<td>{this.props.voucher.orderId}</td>
<td>{this.props.voucher.deal}</td>
<td>{this.props.voucher.dealDescription}</td>
<td>{this.props.voucher.price}</td>
<td>{this.props.voucher.redemptionStatus}</td>
<td>{this.props.voucher.redemptionTimestamp}</td>
</tr>
);
}
}
class TableContent extends React.Component {
render() {
const rows = [];
this.props.vouchers.forEach((voucher) => {
if(voucher.orderId.indexOf(this.props.filterText) === -1){return;}
rows.push(<TableContentRow voucher = {voucher} key = {voucher.orderId} />);
})
return(
<div className="panel panel-primary">
<div className="panel-heading">
<h3 className="panel-title">
All Vouchers
</h3>
</div>
<table className="table table-striped">
<thead>
<tr>
<th>Restaurant</th>
<th>Voucher Code</th>
<th>Order ID</th>
<th>Deal</th>
<th>Deal Description</th>
<th>Sale Price</th>
<th>Redemption Status</th>
<th>Redemption Timestamp</th>
</tr>
</thead>
<tbody>
{rows}
</tbody>
</table>
</div>
);
}
}
class VoucherAll extends React.Component {
constructor(props){
super(props);
this.handleFilterTextInput = this.handleFilterTextInput.bind(this);
this.loadVouchersFromServer = this.loadVouchersFromServer.bind(this);
this.state = {filterText: ''};
}
handleFilterTextInput(filterText) {
this.setState({
filterText: filterText
});
}
loadVouchersFromServer() {
$.ajax({
url: this.props.url,
success: function(data) {
this.setState({
data: data
});
},
error: function(xhr,status,err) {
console.log(this.props.url, status, err.toString());
}
})
}
componentDidMount() {
this.loadVouchersFromServer();
setInterval(this.loadVouchersFromServer, this.props.pollInterval);
}
render(){
return(
<div className="container">
<TableContent
vouchers = {this.state.data}
filterText = {this.state.filterText}
/>
</div>
);
}
}
ReactDOM.render(
<VoucherAll url = "voucher.json" pollInterval = {2000} />,
document.getElementById('voucherAll')
)
And here's my json file:
{
"merchantName":"xxxx",
"voucherCode":"xxxx",
"orderId":"xxxx",
"deal":"xxxx",
"dealDescription":"xxxx",
"price":"xxxx",
"redemptionStatus":"xxxx",
"redemptionTimestamp":"xxxx-xx-xx"
}
When I run my code, the web page shows nothing. And in the console, I cannot find any relative message. Can anyone help me to figure that out? Thanks.
You are loosing context inside ajax callbacks. Though loadVouchersFromServer is binded success and error callbacks aren't. You could use arrow functions or bind those callbacks.
loadVouchersFromServer() {
$.ajax({
url: this.props.url,
success: data => {
this.setState({
data: data
});
},
error: function(xhr,status,err) {
console.log(this.props.url, status, err.toString());
}.bind(this)
})
}