Why valueChanges does not work in my code? - node.js

I have a MatTableDataSource that shows some elements retrieved from my MongoDB and I want to filter each column of the table in order to have only what matches my input.
This is my code:
datatable.component.ts
export class DatatableComponent implements OnInit {
#ViewChild(MatPaginator) paginator: MatPaginator;
pratiche: any;
displayedColumns: string[] = ['idPratica', 'barcode', 'status', 'firstName', 'lastName', 'fiscalCode', 'pratica'];
dataSource = new MatTableDataSource(this.pratiche);
idFilter = new FormControl('');
barcodeFilter = new FormControl('');
filterValues = {
id: '',
barcode: '',
};
constructor(private praticaService: PraticaService) {
this.dataSource.data = this.pratiche;
this.dataSource.filterPredicate = this.createFilter();
}
async ngOnInit() {
const res = await this.praticaService.getAllPratiche();
this.pratiche = res.data;
this.dataSource = new MatTableDataSource(this.pratiche);
this.dataSource.paginator = this.paginator;
this.idFilter.valueChanges
.subscribe(
id => {
this.filterValues.id = id;
this.dataSource.filter = JSON.stringify(this.filterValues);
}
)
this.barcodeFilter.valueChanges
.subscribe(
barcode => {
this.filterValues.barcode = barcode;
this.dataSource.filter = JSON.stringify(this.filterValues);
}
)
}
createFilter(): (data: any, filter: string) => boolean {
let filterFunction = function (data, filter): boolean {
let searchTerms = JSON.parse(filter);
return data.id.toLowerCase().indexOf(searchTerms.id) !== -1
&& data.barcode.toLowerCase().indexOf(searchTerms.barcode) !== -1
&& data.status.toLowerCase().indexOf(searchTerms.status) !== -1
&& data.firstName.toLowerCase().indexOf(searchTerms.firstName) !== -1
&& data.lastName.toLowerCase().indexOf(searchTerms.lastName) !== -1
&& data.fiscalCode.toLowerCase().indexOf(searchTerms.fiscalCode) !== -1;
}
return filterFunction;
}
}
datatable.component.html
<table mat-table [dataSource]="dataSource">
<ng-container matColumnDef="idPratica">
<th class="header" mat-header-cell *matHeaderCellDef>
ID Pratica
<mat-form-field class="filter" floatLabel="never">
<mat-label></mat-label>
<input matInput [formControl]="idFilter">
</mat-form-field>
</th>
<td mat-cell *matCellDef="let element">{{element.id}}</td>
</ng-container>
<ng-container matColumnDef="barcode">
<th class="header" mat-header-cell *matHeaderCellDef>
Barcode
<mat-form-field class="filter" floatLabel="never">
<mat-label></mat-label>
<input matInput [formControl]="barcodeFilter">
</mat-form-field>
</th>
<td mat-cell *matCellDef="let element">{{element.barcode}}</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let element; columns: displayedColumns;"></tr>
pratica.service.ts
public getAllPratiche(): Promise<any> {
const url = "http://127.0.0.1:3001/pratiche/getPratiche";
return new Promise((resolve, reject) => {
this.http.get(url, { responseType: "json", observe: "response" })
.pipe(map((response: any) => response))
.subscribe(res => {
if (res.error) {
reject(res.error);
} else {
resolve(res.body);
}
}, err => {
reject(err)
});
});
}
I retrieve correctly my data from my MongDb but when I try to filter it, nothing happens. I'm new on angular and probably I am making mistakes on Promise vs Observable. Any suggestion?

Related

Not able to map the fetching value in axios

code
import React, { useEffect, useState } from "react";
import "./main.css"
import { AiOutlineCheck, AiOutlineClose, AiOutlineArrowUp, AiOutlineArrowDown } from "react-icons/ai";
import axios from "axios";
const Header = () => {
const [setdata, fetchdata] = useState([]);
const [setpostData, Postdata] = useState([]);
useEffect(() => {
getfetchData();
}, [])
useEffect(() => {
setdata.forEach(function (val) {
getPostData(val.Player, val.IP, val.Port, val.ChannelName);
});
}, [setdata]);
function getfetchData() {
axios.get("http://localhost:9763/api/getPlayers",
{
headers: {
"accepts": "application/json",
'Access-Control-Allow-Origin': '*',
},
auth: {
username: 'admin',
password: 'password'
},
}).then(response => {
//console.log(response.data)
//console.log([...Object.values(response.data).flat()]);
fetchdata([...Object.values(response.data).flat()]);
}).catch(error => {
console.log(error);
});
}
var temp = [];
// Post Data
function getPostData(Player, IP, Port, channelName) {
var data = {
PlayerName: Player,
ChannelName: channelName,
Port: Port,
IpAddress: IP
}
axios({
method: 'post',
url: 'http://localhost:9763/api/getPlayerStatus',
data,
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
auth: {
username: 'admin',
password: 'password'
}
}).then(response => {
var tempObj;
tempObj = [response.data];
for (var i = 0; i <= tempObj.length; i++) {
if (tempObj[i] !== undefined) {
temp.push(tempObj[i]);
}
}
Postdata(temp);
}).catch(error => {
console.log("Error In Post Data", error);
});
}
console.log("set", setpostData);
return (
<div className="container-fluid pt-2">
<table className=" table-borderless text-center" id="refresh">
<thead>
<tr className="title" >
{
Object.values(setdata).map((val) => {
return (
<th key={val.Player} > <AiOutlineCheck style={{ color: 'black', backgroundColor: "#41fc00", borderRadius: "25px" }} />
{val.ChannelName} </th>
)
})
}
</tr>
</thead>
<tbody>
<tr >
{
setpostData.map((val, index) => {
// console.log("Inside Map", val);
return (
<td key={index}>{val.Properties.Upcounter} </td>
)
})
}
</tr>
<tr>
{
setpostData.map((val, index) => {
// console.log("Inside Map", val);
return (
<td key={index}>{val.Properties.DownCounter} </td>
)
})
}</tr>
</tbody>
</table>
</div >
);
}
export default Header;
not able to map the table row only first fetch data is visible in data row i have 4 data in fetch
Console Image
and why 2 set In console is fetch? please help me i want to store the fetch data in temp and then display in table row for setInterval
Please provide code
first, I fetch channels 1,2,3,4 from get method and then call post data in which I call function parameter and check the get method data in the body parameter of post method and print the data of post method but it is in the form of object in the console and I want to store in temp and them display it in the web page
It looks like you might need to parse the returned value before trying to map over it.
The returned value is JSON, not JS.
JSON.parse(response.data)

TypeError: users.map is not a function in Mern

I am trying to fetch data from backend, I want to load all data which are in database, when I load function then getting an error like "User.map is not a function", please let me know where am wrong.
User.js
import React, { useEffect, useState } from "react";
import { Link } from "react-router-dom";
import { getUsers } from "./apis";
const UserData = () => {
const [users, setUser] = useState([]);
useEffect(() => {
AllUsers();
}, []);
const AllUsers = async () => {
const response = await getUsers();
console.log(response.data);
setUser(response.data ? response.data : []);
};
return (
<div>
<div className="container">
<table className="table table-hover table-bordered mt-5">
<thead>
<tr>
{/* <th scope="col">No</th> */}
<th scope="col">Title</th>
<th scope="col">Details</th>
<th scope="col">Action</th>
</tr>
</thead>
<tbody>
{users.map((user, index) => (
<tr key={index}>
<th scope="row">{user.id}</th>
<td>{user.title}</td>
<td>{user.description}</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
);
};
Api.js
I have added api.js file please check it , and let me know where am wrong
export default UserData;
import Axios from "axios";
const url = "http://localhost:3000/";
export const getUsers = async (id) => {
id = id || "";
return await Axios.get(`${url}/${id}`);
};
export const deleteUser = async (id) => {
return await Axios.delete(`${url}/${id}`);
};
You can use Optional chaining (?.) for check the data is available or not. Because while API's is calling data not set in your state. It's might be a undefined.
const adventurer = {
name: 'Alice',
cat: {
name: 'Dinah'
}
};
const dogName = adventurer.dog?.name;
console.log(dogName);
In your case do with this way.
{users?.map((user, index) => (
<tr key={index}>
<th scope="row">{user.id}</th>
<td>{user.title}</td>
<td>{user.description}</td>
</tr>
))}
import Axios from "axios";
const url = "http://localhost:3000/";
export const getUsers = async (id) => {
id = id || "";
return await Axios.get(`${url}/${id}`);
};
export const deleteUser = async (id) => {
return await Axios.delete(`${url}/${id}`);
};

How can I get the key values from API props response

I couldn't map the second API response https://api.coingecko.com/api/v3/global with error prompted (read property 'map' of undefined), while the first API is fine.
Whats the issue here?
export default function Home(props) {
const { data } = props.result;
const { global } = props.nextResult;
<table className="table2 table-hover table-dark">
<thead>
<tr>
<th>Markets</th>
</tr>
</thead>
<tbody>
{global.map (gg => (
<tr key={gg.endedicos}>
<td>{gg.markets}</td>
</tr>
))}
</tbody>
</table>
export async function getServerSideProps(context) {
const params = {
order: CoinGecko.ORDER.MARKET_CAP_DESC
};
const [result, nextResult] = await Promise.all([
coinGeckoClient.coins.markets({params}),
coinGeckoClient.global()
]);
return {
props: {
result, nextResult
},
}
}

React useSelector first time returns undefined, then everything works fine

so I'm making a mini eCommerce app using MERN stack, i'm fetching products for each seller using his id, so he's the only one who can edit or delete his own products,
in my component i get the user's id from redux state from the user, then i use the id to fetch products for each logged in seller.(in useEffect)
so fetching products depends on the user, and the user is always loaded and no need to fetch it after he login.
the problem is, only the first time after i login and i render the component it gives me
TypeError: products.map is not a function. but if i refresh the page it works fine
so it doesn't see products the first time idk why even if the user is there and the id to fireup the fetching function.
function EditProducts() {
const { user } = useSelector(state => state.userrr);
const { loading, products } = useSelector(state => state.userProductsss);
const dispatch = useDispatch();
useEffect(() => {
console.log(user);
console.log(products);
if (!user) {
return;
} else {
let id = user._id;
dispatch(fetchUserProducts(id));
}
}, [dispatch, user]);
const deleteIt = id => {
dispatch(deleteProduct(id))
.then(res => {
toast.success(res, { position: toast.POSITION.BOTTOM_LEFT });
})
.catch(error => {
toast.error(error, {
position: toast.POSITION.BOTTOM_LEFT,
autoClose: false
});
});
};
console.log(products);
return (
<Container>
<Table striped bordered hover variant='dark'>
<thead>
<tr>
<th>category</th>
<th>Description</th>
<th>Price</th>
<th>Edit</th>
</tr>
</thead>
<tbody>
{loading && (
<tr>
<td colSpan='4'>
<Spinner animation='border' /> loading...{" "}
</td>
</tr>
)}
{!user && !loading && (
<tr>
<td colSpan='4'>Please Log in to access this page</td>
</tr>
)}
{products.map(product => (
<tr key={product._id}>
<td>{product.name}</td>
<td>{product.description}</td>
<td>${product.price}</td>
<td>
<span className='btn btn-primary mr-3'>
<UpdateProductForm
id={product._id}
name={product.name}
description={product.description}
category={product.category}
price={product.price}
numberInStock={product.numberInStock}
productImage={product.productImage}
/>
</span>
<Button className='btn btn-danger' onClick={() => deleteIt(product._id)}>
<FontAwesomeIcon icon={faTrash} />
</Button>
</td>
</tr>
))}
</tbody>
</Table>
</Container>
);
}
export default EditProducts;
this is my reducer
const productReducer = (state = initialState, action) => {
switch (action.type) {
case FETCH_USER_PRODUCTS_STARTED:
return {
...state,
loading: true
};
case FETCH_USER_PRODUCTS_SUCCESS:
return {
...state,
loading: false,
error: null,
products: action.payload.products
};
case FETCH_USER_PRODUCTS_FAILURE:
return {
...state,
loading: false,
error: action.payload.error,
success: null
};
default:
return state;
}
};
this is the actions
export const fetchUserProducts = userId => {
return dispatch => {
dispatch(fetchUserProductsStarted());
axios
.get(`/api/product/${userId}/products`)
.then(res => {
dispatch(fetchUserProductsSuccess(res.data));
})
.catch(error => {
dispatch(fetchUserProductsFailure(error.message));
});
};
};
const fetchUserProductsStarted = () => {
return {
type: FETCH_USER_PRODUCTS_STARTED
};
};
const fetchUserProductsSuccess = products => {
return {
type: FETCH_USER_PRODUCTS_SUCCESS,
payload: {
products
}
};
};
const fetchUserProductsFailure = error => {
return {
type: FETCH_USER_PRODUCTS_FAILURE,
payload: {
error
}
};
};
so the problem was that useEffect couldn't be able to ensure the user data is loaded before the first render here:
const { user } = useSelector(state => state.userrr);
so the user was null, so it couldn't get the products depending on the user id.
what i did is that i loaded the user again inside the component useEffect so it gets the user data.
useEffect(() => {
dispatch(loadUser());
const id = user ? user._id : null;
dispatch(fetchUserProducts(id));
}, [ dispatch, id]);

search functionality on index page

I have code with 3 search fields. One is a RadioButton and two are DropdownList coming from a database.
I have to search base on above criteria but i will get a wrong result.
public ActionResult Index(string searchby,string did, string sid)
{
ViewBag.did = new SelectList(db.destcities, "Id", "name",did);
ViewBag.sid = new SelectList(db.sourcecities, "Id", "name",sid);
var searches = db.searches.Include(s => s.destcity)
.Include(s => s.sourcecity);
If(!String.IsNullOrEmpty(searchby))
{
searches= db.searches.Where(a => a.type == searchby);
}
if(!String.IsNullOrEmpty(did))
{
int q = int.Parse(did);
searches= db.searches.Where(s => s.destcity.Id == q);
}
if (!String.IsNullOrEmpty(sid))
{
int p = int.Parse(sid);
searches= db.searches.Where(c => c.sourcecity.Id == p);
}
return View(searches);
}
and view code is
#model IEnumerable<Web.Models.search>
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>#Html.ActionLink("Create New", "Create") </p>
#using (Html.BeginForm("Index","searches",FormMethod.Get))
{
<label>Trip type</label>
#Html.RadioButton("searchby", "Oneway")<text>Oneway</text>
#Html.RadioButton("searchby", "Roundtrip")<text>Roundtrip</text>
#Html.DropDownList("did", null, htmlAttributes: new { #class = "form-control" })
#Html.DropDownList("sid", null, htmlAttributes: new { #class = "form-control" })
<input type="submit" value="Create" class="btn btn-default" />
}
<table class="table">
<tr>
<th>#Html.DisplayNameFor(model => model.destcity.name)</th>
<th>#Html.DisplayNameFor(model => model.sourcecity.name)</th>
<th>#Html.DisplayNameFor(model => model.vehicle)</th>
<th>#Html.DisplayNameFor(model => model.km)</th>
<th>#Html.DisplayNameFor(model => model.price)</th>
<th>#Html.DisplayNameFor(model => model.type)</th>
<th></th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>#Html.DisplayFor(modelItem => item.destcity.name)</td>
<td>#Html.DisplayFor(modelItem => item.sourcecity.name)</td>
<td>#Html.DisplayFor(modelItem => item.vehicle)</td>
<td>#Html.DisplayFor(modelItem => item.km)</td>
<td>#Html.DisplayFor(modelItem => item.price)</td>
<td>#Html.DisplayFor(modelItem => item.type)</td>
<td>#Html.ActionLink("Edit", "Edit", new { id=item.Id })
| #Html.ActionLink("Details", "Details", new { id=item.Id })
| #Html.ActionLink("Delete", "Delete", new { id=item.Id })
</td>
</tr>
}
</table>

Resources