Combobox autocomplete disabled when loaded - combobox

An autocomplete component is loading everythig as expected but once it's loaded it remains disabled because it loads before check the "ready" status and it loads it disabled even when is ready.
Is there a way to load it asynchronously?
import React from 'react'
import usePlacesAutocomplete, { getGeocode, getLatLng } from 'use-places-autocomplete'
import { GoogleMap,useLoadScript,Marker,InfoWindow } from "#react-google-maps/api";
import {Combobox,ComboboxInput,ComboboxPopover,ComboboxList,ComboboxOption} from "#reach/combobox";
import "#reach/combobox/styles.css";
function AutocompleteComp(props) {
const libraries = ["places"];
const { isLoaded, isError} = useLoadScript({
googleMapsApiKey: process.env.NEXT_PUBLIC_COMPONENT_GoogleMap_geolocation_apiKey,
libraries
});
const {
value,
suggestions: { status, data },
setValue,
clearSuggestions,
ready,
} = usePlacesAutocomplete({
callbackName: "Callback Function",
requestOptions: {
types: "address"
componentRestrictions: { country: ["ca","mx"] },
fields: ['address_component', 'adr_address', 'business_status', 'formatted_address', 'geometry', 'icon', 'name', 'permanently_closed', 'photo', 'place_id', 'plus_code', 'type', 'url', 'utc_offset', 'vicinity'],
},
debounce: 300,
});
const handleSelect = ({address}) => () => {
setValue(address, false);
clearSuggestions();
try {
const results = getGeocode({ address });
const { lat, lng } = getLatLng(results[0]);
ReturnState({ address: address, lat: lat, lng: lng, selected: results[0] })
return ({ address: address, lat: lat, lng: lng, selected: results[0] });
} catch (error) {
console.error(`😱 Error:`, error);
}
};
if(isLoaded){
return (
<label htmlFor="search">"Type your search"
<Combobox onSelect={handleSelect}>
<ComboboxInput
id="search"
value={value}
onChange={(e) => setValue(e.target.value)}
className="combobox-input"
placeholder={"Placeholder"}
autoComplete="off"
disabled={!ready} //HERE IS THE PROBLEM
/>
<ComboboxPopover>
<ComboboxList>
{status === "OK" &&
data.map(({ place_id, description }) => (
<ComboboxOption key={place_id} value={description}/>
))}
</ComboboxList>
</ComboboxPopover>
</Combobox>
</label>
)
}
}
export default React.memo(AutocompleteComp)

Related

I want to update my quantity at the same time based on quantity update my available quantity and sell quantity

suppose i have quantity, available_qty, and sell_quantity ,I want if my quantity increase my sell_quantity will increase and available_qty decrease ,if my quantity will decrease my sell_quantity will decrease and available_qty will increase..
import React, { useState } from 'react'
import BackButton from '../../components/UI/BackButton'
import Input from '../../components/UI/Input'
import Button from '../../components/UI/Button'
import {
useUpdateOrderMutation,
useGetOrderByIdQuery,
useGetAllProductQuery,
useGetAllOrderQuery,
} from '../../Redux/Services/services'
import { useParams } from 'react-router-dom'
import { useForm, Controller } from 'react-hook-form'
import { useNavigate } from 'react-router-dom'
const UpdateOrder = () => {
const [noData, setNoData] = useState(false)
const {
control,
handleSubmit,
reset,
formState,
setValue,
formState: { errors, isSubmitSuccessful },
} = useForm({
// resolver: yupResolver(createProductSchema),
defaultValues: {
// Category_name: '',
// subCat_name: '',
selling_price: '',
quantity: '',
available_qty: '',
sell_quantity: '',
// unit: '',
total_cost: '',
},
})
React.useEffect(() => {
if (formState.isSubmitSuccessful) {
reset({ quantity: '' })
}
}, [formState, reset])
const params = useParams()
const order_id = params.id
const [updateOrder, responseInfoOrderUpdate] = useUpdateOrderMutation()
const responseInfoOrderById = useGetOrderByIdQuery(order_id)
const responseInfoProduct = useGetAllProductQuery()
const responseInfoAllOrder = useGetAllOrderQuery()
const orderDetails = responseInfoAllOrder.data
if (responseInfoOrderUpdate.isLoading) return <div>Loading....</div>
if (responseInfoOrderUpdate.isError)
return <h1>An error occured {responseInfoOrderUpdate.error.error}</h1>
if (responseInfoOrderById.isLoading) return <div>Loading....</div>
if (responseInfoOrderById.isError)
return <h1>An error occured {responseInfoOrderById.error.error}</h1>
if (responseInfoProduct.isLoading) return <div>Loading....</div>
if (responseInfoProduct.isError)
return <h1>An error occured {responseInfoProduct.error.error}</h1>
// const totalProductQty = responseInfoOrderById.data
// ?.filter((sellQuantity) => sellQuantity.subCat_id === subCat_id)
// .map((additionSell, i) => additionSell.quantity)
// .reduce((qty, purchase) => qty + purchase, 0)
var qty_data = responseInfoOrderById.data?.quantity
var sellingPrice_data = responseInfoOrderById.data?.selling_price
var available_qty = responseInfoOrderById.data?.available_qty
var sell_quantity = responseInfoOrderById.data?.sell_quantity
const totalProductQty =
parseInt(responseInfoOrderById.data?.available_qty) +
parseInt(responseInfoOrderById.data?.sell_quantity)
console.log('totalProductQty', totalProductQty)
console.log('sell_quantity', sell_quantity)
const sell_qty =
parseInt(totalProductQty) -
parseInt(responseInfoOrderById.data?.available_qty)
// const available_qty =
// parseInt(totalProductQty) -
// parseInt(responseInfoOrderById.data?.sell_quantity)
// console.log('sell_qty', sell_qty)
// console.log('available_qty', available_qty)
// const total_sell = parseInt(sellQty) + parseInt(quantity)
const AvailableProduct = parseInt(totalProductQty) - parseInt(qty_data)
const onSubmit = (data) => {
const orderUpdateData = {
id: order_id,
quantity: data.quantity,
available_qty: available_qty,
selling_price: data.selling_price,
total_cost: data.total_cost,
sell_quantity: sell_quantity,
}
updateOrder(orderUpdateData)
console.log(orderUpdateData, 'orderUpdateData')
}
var total_cost = parseInt(sellingPrice_data) * parseInt(qty_data)
console.log('supplier_name', sellingPrice_data, qty_data, total_cost)
setValue('quantity', qty_data)
setValue('selling_price', sellingPrice_data)
setValue('total_cost', total_cost)
setValue('available_qty', available_qty)
setValue('sell_quantity', sell_quantity)
return (
<div className="page__wrapper">
<BackButton />
<div className="place__order__wrapper">
<form onSubmit={handleSubmit(onSubmit)}>
<div className="inputs__cover">
<Controller
control={control}
rules={{
required: true,
}}
render={({ field: { onChange, onBlur, value } }) => (
<Input
label="Selling price"
type="number"
id="selling_price"
readOnly={true}
onChange={onChange}
onBlur={onBlur}
value={value}
/>
)}
name="selling_price"
/>
{errors.selling_price && (
<span className="field_error">This is required.</span>
)}
<Controller
control={control}
rules={{
required: true,
}}
render={({ field: { onChange, onBlur, value } }) => (
<Input
label="Available qty"
type="number"
id="available_qty"
readOnly={true}
onChange={onChange}
onBlur={onBlur}
value={value}
/>
)}
name="available_qty"
/>
{errors.available_qty && (
<span className="field_error">This is required.</span>
)}
<Controller
control={control}
rules={{
required: true,
}}
render={({ field: { onChange, onBlur, value } }) => (
<Input
label="sell Total qty"
type="number"
id="sell_quantity"
readOnly={true}
onChange={onChange}
onBlur={onBlur}
value={value}
/>
)}
name="sell_quantity"
/>
{errors.sell_quantity && (
<span className="field_error">This is required.</span>
)}
<div className="quantity__input">
<Controller
control={control}
rules={{
required: true,
}}
render={({ field: { onChange, onBlur, value } }) => (
<Input
label="Quantity"
type="number"
id="quantity"
onChange={onChange}
onBlur={onBlur}
value={value}
/>
)}
name="quantity"
/>
</div>
<Controller
control={control}
rules={
{
// required: true,
}
}
render={({ field: { onChange, onBlur, value } }) => (
<Input
label="Total cost"
type="number"
id="total_cost"
onChange={onChange}
onBlur={onBlur}
value={noData ? total_cost.toString() : value}
readOnly={true}
/>
)}
name="total_cost"
/>
{errors.total_cost && (
<span className="field_error">This is required.</span>
)}
</div>
<div className="button__wrapper">
<Button className="add__product__button" type="submit">
Add quantity
</Button>
</div>
<div className="button__wrapper">
<Button className="add__product__button" type="submit">
update quantity
</Button>
</div>
</form>
</div>
</div>
)
}
export default UpdateOrder
model is
const mongoose = require("mongoose");
const OrderSchema = new mongoose.Schema(
{
_id: mongoose.Schema.Types.ObjectId, //convert id to normal form
customer_id: {
type: String,
required: true,
lowercase: true,
},
category_id: {
type: String,
required: true,
lowercase: true,
},
subCat_id: {
type: String,
required: true,
lowercase: true,
},
selling_price: {
type: Number,
required: true,
},
quantity: {
type: Number,
required: true,
},
sell_quantity: {
type: Number,
default: 0,
},
available_qty: {
type: Number,
default: 0,
},
unit: {
type: String,
required: true,
enum: {
values: ["kg", "litre", "pcs", "bag"],
message: "unit must be kg/litre/pcs/bag",
},
},
total_cost: {
type: Number,
required: true,
},
},
{ timestamps: true }
);
module.exports = mongoose.model("order", OrderSchema);
query is
const router = require("express").Router();
const { default: mongoose } = require("mongoose");
const Order = require("../models/Order");
//create order
router.post("/order-save", async (req, res) => {
try {
const customer_id = req.body.customer_id;
const category_id = req.body.category_id;
const subCat_id = req.body.subCat_id;
const selling_price = req.body.selling_price;
const quantity = req.body.quantity;
const sell_quantity = req.body.sell_quantity;
const available_qty = req.body.available_qty;
const unit = req.body.unit;
const total_cost = req.body.total_cost;
const oder_data = new Order({
_id: mongoose.Types.ObjectId(),
customer_id: customer_id,
category_id: category_id,
subCat_id: subCat_id,
selling_price: selling_price,
quantity: quantity,
sell_quantity: sell_quantity,
available_qty: available_qty,
unit: unit,
total_cost: total_cost,
});
const orderData = await oder_data.save();
message = "Order Create Successfully..";
return res.status(200).json(orderData);
} catch (err) {
return res.status(200).json(err);
}
});
//get all order
router.get("/get-order", async (req, res) => {
try {
const order = await Order.find();
return res.status(200).json(order);
} catch (err) {
return res.status(200).json(err);
}
});
//get order by id
router.get("/get-order/:id", async (req, res) => {
try {
const orderById = await Order.findById(req.params.id);
return res.status(200).json(orderById);
} catch (error) {
return res.status(500).json(error);
}
});
//get filter customer by id
router.get("/filter-order/:id", async (req, res) => {
try {
const order = await Order.find({ $and: [{ customer_id: req.params.id }] });
return res.status(200).json(order);
} catch (err) {
return res.status(500).json(err);
}
});
//Update Order
router.patch("/update-order/:id", async (req, res) => {
try {
await Order.findByIdAndUpdate(req.params.id, req.body, {
new: true,
});
message = "Order has been updated...";
return res.status(200).json({ message });
} catch (err) {
return res.status(200).json(err);
}
});
module.exports = router;

How to get SyncFusion grid with custom binding to show/hide spinner

I have a SyncFusion grid that is using custom binding and I'm having two issues. Using React v18 with Redux.
When initially requesting the data to populate the grid, it is not showing the loading spinner, even though I have set it up via a side-effect and a Redux state property (isLoading) to do so. Via the console logs I can see that the side-effects are running as intended, but doesn't show spinner.
Once the initial data request comes back and populates the grid the spinner appears and doesn't stop. I believe it has something to do with the row-detail templates that are being added. If I remove the detail template the spinner does not appear. I have added in a hideSpnner to my external columnChooser button, after I click this, everything works normally.
It's not appearing when I want it to, then appearing and not going away.
Once I'm past this initial data request and force the hideSpinner() via the external column chooser button, subsequent data requests work fine when paging and sorting, spinner shows appropriately.
Not sure if there is a community of SyncFusion users here, but hopefully someone can help.
Here is my slice:
import { createAsyncThunk, createSlice } from "#reduxjs/toolkit";
import { DataStateChangeEventArgs } from "#syncfusion/ej2-react-grids";
import { ServiceRequest } from "./models/ServiceRequest.interface";
import { ServiceRequestResult } from "./models/ServiceRequestResult.interface";
import csmService from "./services/csmMyRequestService";
interface AsyncState {
isLoading: boolean;
isSuccess: boolean;
isError: boolean;
}
interface MyRequestState extends AsyncState {
result: ServiceRequest[];
count: number;
}
const initialState: MyRequestState = {
isLoading: false,
isSuccess: false,
isError: false,
result:[],
count: 0
}
export const getMyRequests = createAsyncThunk(
'csm/getMyRequests',
async (gridCriteria: DataStateChangeEventArgs) => {
try {
return await csmService.getMyRequests(gridCriteria);
} catch (error) {
console.log('Error: ', error);
}
});
export const csmMyRequestSlice = createSlice({
name: 'csmMyRequest',
initialState,
reducers: {},
extraReducers(builder) {
builder
.addCase(getMyRequests.pending, (state) => {
state.isLoading = true;
})
.addCase(getMyRequests.fulfilled, (state, action) => {
state.result = action.payload?.myRequests || [];
state.count = action.payload?.count || 0;
state.isLoading = false;
state.isSuccess = true;
})
.addCase(getMyRequests.rejected, (state) => {
state.result = [];
state.count = 0;
state.isLoading = false;
state.isError = true;
})
},
});
export default csmMyRequestSlice.reducer;
Here is my component:
import { FC, useEffect, useRef, useState } from 'react';
import { Internationalization } from '#syncfusion/ej2-base';
import { ColumnDirective, ColumnsDirective, DataStateChangeEventArgs, Grid, GridComponent } from '#syncfusion/ej2-react-grids';
import { Inject, Page, Sort, Filter, FilterSettingsModel, Resize, ColumnChooser, DetailRow } from '#syncfusion/ej2-react-grids';
import { useAppDispatch, useAppSelector } from '../../../hooks/redux/hooks';
import styles from './MyRequests.component.module.scss';
import { getMyRequests } from '../csmMyRequestSlice';
import { IconButton, styled, Tooltip, tooltipClasses, TooltipProps } from '#mui/material';
import ViewColumnIcon from '#mui/icons-material/ViewColumn';
import { ServiceRequestResult } from '../models/ServiceRequestResult.interface';
let instance = new Internationalization();
const MyRequestsComponent: FC = () => {
const dispatch = useAppDispatch();
const { isLoading, result, count, isSuccess } = useAppSelector((state) => state.csmMyRequestReducer);
let initialMyRequests = { result: [], count: 0 };
const [myRequests, setMyRequests] = useState<ServiceRequestResult>(initialMyRequests);
const pageSettings = {
pageSize: 10,
pageSizes: ["10", "20", "30", "40", "50"]
};
const sortSettings = {
columns: []
};
const columnChooserSettings = {
hideColumns: [
"Contact",
"Request Subtype",
"Reference",
"Sys. Logged Date",
"Sys. Closed Date"
]
};
let myGridInstanceRef: Grid | null;
const format = (value: Date) => {
return instance.formatDate(value, { skeleton: 'yMd', type: 'date' });
};
const dataBound = () => {
}
const dataStateChange = (gridCriteria: DataStateChangeEventArgs) => {
if (myGridInstanceRef && gridCriteria.action) {
const requestType = gridCriteria.action.requestType;
switch (requestType) {
case 'paging':
case 'sorting':
dispatch(getMyRequests(gridCriteria));
break;
}
}
};
const CustomWidthTooltip = styled(({ className, ...props }: TooltipProps) => (
<Tooltip {...props} classes={{ popper: className }} />
))({
[`& .${tooltipClasses.tooltip}`]: {
maxWidth: 500,
fontSize: 13,
color: 'white',
},
});
function gridDetailTemplate(props: any) {
return (
<CustomWidthTooltip title={props.Detail}><p className={`${styles['RequestDetailText']}`}>Detail: {' '}{props.Detail}</p></CustomWidthTooltip>
);
}
let template: any = gridDetailTemplate;
const columnChooserClick = (event: React.MouseEvent<HTMLElement>) => {
if (myGridInstanceRef) {
myGridInstanceRef.hideSpinner(); //Forced hide of spinner here
myGridInstanceRef.columnChooserModule.openColumnChooser();
}
};
useEffect(() => {
if (myGridInstanceRef) {
if (isLoading) {
console.log('is Loading show spinner'); //Goes through here but spinner doesn't display
myGridInstanceRef.showSpinner();
} else {
console.log('not Loading hide spinner'); //Who knows if it gets hidden as it never gets displayed
myGridInstanceRef.hideSpinner();
}
}
}, [isLoading])
useEffect(() => {
if (myGridInstanceRef && isSuccess) {
setMyRequests({ result: result, count: count });
}
}, [result, isSuccess])
useEffect(() => {
if (myGridInstanceRef) {
columnChooserSettings.hideColumns.forEach((field) => {
myGridInstanceRef!.hideColumns(field);
});
const gridCriteria = { skip: 0, take: 10 };
dispatch(getMyRequests(gridCriteria));
}
}, [])
return (
<div className={`${styles['RequestSection']}`}>
<legend className={`${styles['RequestLegend']}`}>My Requests:
<Tooltip title="Show/Hide Columns">
<IconButton
className={`${styles['ColumnChooser']}`}
onClick={columnChooserClick}
size="small"
>
<ViewColumnIcon />
</IconButton>
</Tooltip>
</legend>
<div className={`${styles['RequestGridContainer']}`}>
<GridComponent
ref={(g) => (myGridInstanceRef = g)}
dataSource={myRequests}
allowPaging={true} pageSettings={pageSettings}
allowSorting={true} allowMultiSorting={true} sortSettings={sortSettings}
allowResizing={true}
allowReordering={true}
showColumnChooser={true}
detailTemplate={template.bind(this)}
dataBound={dataBound.bind(this)}
dataStateChange={dataStateChange.bind(this)}
height='100%'
>
<ColumnsDirective>
<ColumnDirective field='ServiceRequestTag' headerText='Request #' />
<ColumnDirective field='Caller.Name' headerText='Caller' />
<ColumnDirective field='Source' />
<ColumnDirective field='Contact.ContactName' headerText='Contact' />
<ColumnDirective field='ServiceType.ServiceTypeName' headerText='Service Type' />
<ColumnDirective field='ServiceRequestType.ServiceRequestTypeName' headerText='Request Type' />
<ColumnDirective field='ServiceRequestSubtype.ServiceRequestSubtypeName' headerText='Request Subtype' />
<ColumnDirective field='Poi.Address' headerText='POI Address' />
<ColumnDirective field='Poi.CityTown' headerText='POI City/Town' />
<ColumnDirective field='ReferenceNumbers' headerText='Reference' />
<ColumnDirective field='OwnerName' headerText='Owner' />
<ColumnDirective field='Status.StatusName' headerText='Status' width='100' />
<ColumnDirective field='LoggedByName' headerText='Logged By' />
<ColumnDirective field='LoggedDate' headerText='Logged Date' type='datetime' format='dd MMM yyyy HH:mm' />
<ColumnDirective field='SystemLoggedDate' headerText='Sys. Logged Date' type='datetime' format='dd MMM yyyy HH:mm' />
<ColumnDirective field='ClosedByName' headerText='Closed By' />
<ColumnDirective field='ClosedDate' headerText='Closed Date' type='datetime' format='dd MMM yyyy HH:mm' />
<ColumnDirective field='SystemClosedDate' headerText='Sys. Closed Date' type='datetime' format='dd MMM yyyy HH:mm' />
<ColumnDirective field='DueDate' headerText='Due Date' type='datetime' format='dd MMM yyyy HH:mm' />
</ColumnsDirective>
<Inject services={[Page, Sort, Resize, ColumnChooser, DetailRow]} />
</GridComponent>
</div>
</div>
)
}
export default MyRequestsComponent;
I think the issue is with the myGridInstanceRef variable. It's not a true reference in the React ref sense. It is redeclared each render cycle so likely it has synchronization issues.
let myGridInstanceRef: Grid | null;
This should probably be declared as a React ref so it's a stable reference from render cycle to render cycle.
const myGridInstanceRef = React.useRef<Grid | null>();
Example:
const MyRequestsComponent: FC = () => {
...
const myGridInstanceRef = React.useRef<Grid | null>();
...
const dataStateChange = (gridCriteria: DataStateChangeEventArgs) => {
if (myGridInstanceRef.current && gridCriteria.action) {
const requestType = gridCriteria.action.requestType;
switch (requestType) {
case 'paging':
case 'sorting':
dispatch(getMyRequests(gridCriteria));
break;
}
}
};
...
const columnChooserClick = (event: React.MouseEvent<HTMLElement>) => {
if (myGridInstanceRef.current) {
myGridInstanceRef.current.hideSpinner();
myGridInstanceRef.current.columnChooserModule.openColumnChooser();
}
};
useEffect(() => {
if (myGridInstanceRef.current) {
if (isLoading) {
console.log('is Loading show spinner'); //Goes through here but spinner doesn't display
myGridInstanceRef.current.showSpinner();
} else {
console.log('not Loading hide spinner'); //Who knows if it gets hidden as it never gets displayed
myGridInstanceRef.current.hideSpinner();
}
}
}, [isLoading]);
useEffect(() => {
if (myGridInstanceRef.current && isSuccess) {
setMyRequests({ result: result, count: count });
}
}, [result, isSuccess]);
useEffect(() => {
if (myGridInstanceRef.current) {
columnChooserSettings.hideColumns.forEach((field) => {
myGridInstanceRef.current.hideColumns(field);
});
const gridCriteria = { skip: 0, take: 10 };
dispatch(getMyRequests(gridCriteria));
}
}, []);
return (
<div className={`${styles['RequestSection']}`}>
<legend className={`${styles['RequestLegend']}`}>My Requests:
<Tooltip title="Show/Hide Columns">
<IconButton
className={`${styles['ColumnChooser']}`}
onClick={columnChooserClick}
size="small"
>
<ViewColumnIcon />
</IconButton>
</Tooltip>
</legend>
<div className={`${styles['RequestGridContainer']}`}>
<GridComponent
ref={(g) => {
myGridInstanceRef.current = g;
}}
...
>
...
</GridComponent>
</div>
</div>
)
}
Found out that it was the actual grid causing the issue, while the grid control they provide is able to be used with React, it is not very React-ful when dealing with side-effects, they seem quite locked into their vanilla javascript event handlers and anything outside of that causes issues.

React component data from GraphQL api result undefined

I'm working on a React component that uses gql and useQuery from GraphQL to fetch data from an API.
My problem is that the data resulting is undefined because probably the state is not handled correctly and the component didn't load the data requested to the API.
I'm new to React and cannot resolve this situation probably a way to wait until the data is loaded and become defined but I have no idea how to do it.
I was trying even to add a useEffect not present in this version but didn't give any differences :( maybe I just don't know how to use it
The component as follows
import { gql, useQuery } from '#apollo/client';
import { useConfiguration } from '#lib/hooks/useConfiguration';
import { useSetConfiguration } from '#lib/hooks/useSetConfiguration';
import { useUnSetConfiguration } from '#lib/hooks/useUnSetConfiguration';
import { FormControlLabel, FormGroup, Switch, Typography } from '#mui/material';
import { useEffect, useState } from 'react';
import { useIntl } from 'react-intl';
const QUERY = gql`
query WEB_useConfiguration($name: String!, $scope: StudyConfigurationScope) {
studyConfiguration(name: $name, filter: $scope) {
configurationOverrideChain {
value
scope
}
}
}
`;
const beforeQuery = ({ studyId }) => ({
variables: { name: 'messaging.email.sender.address', scope: { studyId } },
fetchPolicy: 'network-only',
});
const afterQuery = data => ({
studyConfigurationOverrides:
data?.studyConfiguration?.configurationOverrideChain ?? {},
});
const StudyConfiguration = ({ studyId }) => {
const intl = useIntl();
const [studyConf, setStudyConf] = useState({});
const { data } = useQuery(QUERY, beforeQuery({ studyId }));
console.log('data: ', data); // undefined
const { studyConfigurationOverrides } = afterQuery(data);
// !TODO: make one smart useConfiguration hook instead of 3
// Getting the study config
const smsEnabled = useConfiguration({
name: 'messaging.recruitment.sms.enable',
scope: { studyId },
defaultValue: false,
});
const emailSender = useConfiguration({
name: 'messaging.email.sender.address',
scope: { studyId },
});
const [valueEmailReplay, setValueEmailReplay] = useState(emailSender);
const [valueSmsConf, setValueSmsConf] = useState(smsEnabled);
useEffect(() => {
if (valueSmsConf !== smsEnabled) {
setValueSmsConf(smsEnabled);
}
}, [smsEnabled]); // eslint-disable-line react-hooks/exhaustive-deps
useEffect(() => {
if (valueEmailReplay !== emailSender) {
setValueEmailReplay(emailSender);
}
}, [emailSender]); // eslint-disable-line react-hooks/exhaustive-deps
let suffix;
const globalValue = studyConfigurationOverrides.find(
e => e.scope === 'GLOBAL',
);
const defaultValue = studyConfigurationOverrides.find(
e => e.scope === 'DEfAULT',
);
if (globalValue) {
suffix = globalValue.value;
}
if (defaultValue) {
suffix = defaultValue.value;
}
const emailDomain = suffix?.substring(suffix.indexOf('#'));
const noReplyEmail = `noreply${emailDomain}`;
// Set study config
const [setNoReplyStudyEmail] = useSetConfiguration({
name: 'messaging.email.sender.address',
value: noReplyEmail,
scope: { studyId },
});
const [setSmsMessagingDisable] = useSetConfiguration({
name: 'messaging.recruitment.sms.enable',
value: 'false',
scope: { studyId },
});
// unSet study config
const [setDefaultStudyEmail] = useUnSetConfiguration({
name: 'messaging.email.sender.address',
scope: { studyId },
});
const [setSmsMessagingDefault] = useUnSetConfiguration({
name: 'messaging.recruitment.sms.enable',
scope: { studyId },
});
const handleReplayEmailChange = async event => {
setValueEmailReplay(event.target.checked ? suffix : noReplyEmail);
event.target.checked
? await setDefaultStudyEmail()
: await setNoReplyStudyEmail();
};
const handleSmsConf = async event => {
setValueSmsConf(event.target.checked);
event.target.checked
? await setSmsMessagingDefault()
: await setSmsMessagingDisable();
};
const isEmailEnabled = emailSender === suffix;
return (
<FormGroup>
<FormControlLabel
control={
<Switch checked={isEmailEnabled} onChange={handleReplayEmailChange} />
}
label={
<Typography color="textPrimary">
{intl.formatMessage(
{
defaultMessage:
'Allow candidates to reply to emails (send from {replyEmailTxt} instead of {noReplyTxt})',
},
{ replyEmailTxt: suffix, noReplyTxt: 'noReplyEmail' },
)}
</Typography>
}
/>
<FormControlLabel
control={<Switch checked={valueSmsConf} onChange={handleSmsConf} />}
label={
<Typography color="textPrimary">
{intl.formatMessage({
defaultMessage: `SMS messaging`,
})}
</Typography>
}
/>
</FormGroup>
);
};
export default StudyConfiguration;

React Native login form

I am trying to create Login page in React native using functional component. But it is not working. As soon as enter any text throwing error. value is not changing.
import React from "react";
import { View, Button, Text } from "react-native";
import Inputs from "../../utils/Form/Input";
const LoginForm = () => {
const [formData, setForm] = React.useState({
email: {
value: "",
valid: false,
type: "textinput",
rules: {
isRequired: true,
isEmail: true
}
},
password: {
value: "",
valid: false,
type: "textinput",
rules: {
isRequired: true,
minLength: true
}
}
});
const handleChange = () => {
setForm({ ...formData });
console.log(formData.email);
};
return (
<View>
<Text>Login</Text>
<Inputs
placeholder="Enter email address"
placeholdercolor="red"
autoCapitalize={"none"}
keyboardType={"email-address"}
onChangeText={value => handleChange("email", value)}
value={formData.email.value}
type={formData.email.type}
/>
<Inputs
placeholder="Password"
placeholdercolor="red"
autoCapitalize={"none"}
type={formData.password.type}
value={formData.password.value}
onChangeText={value => setForm("password", value)}
/>
</View>
);
};
export default LoginForm;
Util file
import React from "react";
import { View, Button, TextInput, Picker, StyleSheet } from "react-native";
const Inputs = props => {
let template = null;
switch (props.type) {
case "textinput":
template = (
<TextInput {...props} style={[styles.input, props.overrideStyle]} />
);
break;
default:
return template;
}
return template;
};
const styles = StyleSheet.create({
input: {
width: "100%",
borderBottomWidth: 2,
borderBottomColor: "blue",
fontSize: 16,
padding: 5,
marginTop: 10
}
});
export default Inputs;
You are missing parameters in handleChange function. It should be
const handleChange = (key, value) => {
let data = formData;
data[key].value = value;
setForm(data);
console.log(formData.email);
};
your handleChange change function is not proper and producing error, change your handle change method to this function
const handleChange = (val, data) => {
if (val === 'email') {
setForm({
...formData,
email: {
...formData.email,
value: data,
},
});
} else {
setForm({
...formData,
password: {
...formData.password,
value: data,
},
});
}
};
and change your onChangeText prop of password input to
onChangeText={value => handleChange('password', value)}

How to do search in table?

I want to search with all the pagination and sorter field on place.
That is i want to call handleChange with searchkeyword.
So how can i call handleSearch and than call handleChange from within handleSearch?
import React from "react";
import { withRouter } from "react-router-dom";
import { Table, Button, Icon, Row, Col, Input } from "antd";
import axios from "axios";
const Search = Input.Search;
class App extends React.Component {
state = {
data: [],
searchValue: "",
loading: false,
visible: false,
pagination: {}
};
componentDidMount() {
this.fetch();
}
handleTableChange = (pagination, filter, sorter, value) => {
console.log(pagination, value, sorter, "Table Change");
let sorterOrder = "";
let sorterField = "";
let searchVal = "";
const pager = { ...this.state.pagination };
pager.current = pagination.current;
this.setState({
pagination: pager
});
if (value) {
console.log("inside if");
searchVal = undefined;
} else {
console.log("inside else");
searchVal = value;
}
if (sorter) {
if (sorter.order === "ascend") {
sorterOrder = "ASC";
}
if (sorter.order === "descend") {
sorterOrder = "DESC";
}
sorterField = sorter.field;
}
this.fetch({
page: pagination.current,
sortField: sorterField,
sortOrder: sorterOrder,
...filter,
value: searchVal
});
};
fetch = (params = {}) => {
this.setState({ loading: true });
axios.post("***/****", params).then(res => {
const pagination = { ...this.state.pagination };
let apiData = res.data.result;
if (res.data.status === 1) {
const objects = apiData.map(row => ({
key: row.id,
id: row.id,
firstName: row.firstName,
lastName: row.lastName,
status: row.status,
email: row.email
}));
console.log(res.data);
pagination.total = res.data.count;
this.setState({
loading: false,
data: objects,
pagination
});
} else {
console.log("Database status is not 1!");
}
});
};
handleSearch = value => {
console.log("value", value);
this.setState({
searchValue: value
});
let searchkey = this.state.searchValue;
const pagination = { ...this.state.pagination };
const sorter = { ...this.state.sorter };
console.log("search", value, pagination, sorter);
this.handleTableChange({
value
});
};
render() {
const columns = [
{
title: "First Name",
dataIndex: "firstName",
sorter: true
},
{
title: "Email",
dataIndex: "email",
sorter: true
}
];
return (
<div>
<Search
placeholder="input search text"
className="searchBut"
onSearch={value => this.handleSearch(value)}
/>
<Button
className="addBut"
style={{ marginTop: "0" }}
type="primary"
onClick={() => this.openForm()}
>
+ Add Admin
</Button>
</div>
<Table
bordered
columns={columns}
dataSource={this.state.data}
pagination={{ total: this.state.pagination.total, pageSize: 4 }}
loading={this.state.loading}
onChange={this.handleTableChange}
/>
);
}
}
export default withRouter(App);
here when i give value in search field it will call post request with request payload as follows:
{sortField: "", sortOrder: ""}
sortField: ""
sortOrder: ""
So how can i do that?
I'm not sure what you trying of achieve it here.
But you can always filter the source data of the table. Like following
<Table
bordered
columns={columns}
dataSource={this.state.data.filter(data=> Object.keys(data).filter(key => data[key].includes(searchValue)).length > 0 ? true: false)}
pagination={{ total: this.state.pagination.total, pageSize: 4 }}
loading={this.state.loading}
onChange={this.handleTableChange}
/>
let me know if it helps.

Resources